本文不打算告诉大家什么叫GDI,各种GDI函数的作用是什么,有关详细的GDI知识可以去以下网站查看。http://www.panshy.com/articles/dev-66_3.html在这里只是让大家知道如何正确使用GDI,并且查找GDI资源占用问题,也就是类似C++中new完后不delete一样,会把系统资源消耗光,GDI资源也是有限的,消耗太多窗体会卡,还会伴有黑色的现象或者是别的窗体贴在本窗体上等效果。
原文地址:http://c.panshy.com/thread-4-1-1.html
首先让大家来看看一般GDI都有哪些函数,这里只列出贴图和双缓冲用得到的函数:
GetWindowDC 获取整个窗体的DC,包含标题栏这种非客区
GetDC获取窗体的客户区的DC,就是窗体能放控件的地方
CreateCompatibleDC 创建兼容DC
SelectObject选入某一GDI对象到DC中,返回DC中原有的对象
DeleteObject删除对象
ReleaseDC释放DC
DeleteDC删除DC
。。。。
以上函数CreateCompatibleDC与DeleteDC 一对、GetWindowDC - GetDC与ReleaseDC一对、SelectObject与DeleteObject一对
现在介绍以上函数正确使用方法,实例是将内存中的图片贴到窗体上,这里只列出伪代码
LONG lTemp;
PAINTSTRUCT pai = {};
BITMAPINFOHEADER BmihSuccess;
BLENDFUNCTION Blend;
LONG x = 0;
RECT r;
Blend.BlendOp = 0;
Blend.BlendFlags = 0;
Blend.AlphaFormat = AC_SRC_ALPHA;
Blend.SourceConstantAlpha = 255;
::BeginPaint(m_hWnd, &pai);
DWORD dwExStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
if ((dwExStyle & 0x80000) != 0x80000)
{
::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwExStyle ^ 0x80000);
}
CRect rcWindow;
::GetWindowRect(m_hWnd, &rcWindow);
//以上代表不用管,看不懂不要紧
HDC hdcTemp = ::GetWindowDC(m_hWnd); //创建窗体DC,包含标题栏,菜单栏
HDC hdcMemory = ::CreateCompatibleDC(hdcTemp); //内存DC,兼容窗体的DC
ZeroMemory(&BmihSuccess, sizeof(BITMAPINFO));
BmihSuccess.biSize = sizeof (BITMAPINFOHEADER) ;
BmihSuccess.biWidth = rcWindow.Width() ;
BmihSuccess.biHeight = rcWindow.Height();
BmihSuccess.biPlanes = 1 ;
BmihSuccess.biBitCount = 32;
BmihSuccess.biCompression = BI_RGB ;
BmihSuccess.biSizeImage = 0 ;
BmihSuccess.biXPelsPerMeter = 0 ;
BmihSuccess.biYPelsPerMeter = 0 ;
BmihSuccess.biClrUsed = 0 ;
BmihSuccess.biClrImportant = 0 ;
HBITMAP hBitMap = ::CreateDIBSection(hdcTemp,
(BITMAPINFO *)&BmihSuccess, 0, NULL, NULL, 0) ; //创建一个GDI对象
HGDIOBJ oldObj = ::SelectObject(hdcMemory, hBitMap); //将GDI对象选入DC
////////////////////////////////////////////////////////////////////////////////////
Gdiplus::Graphics gph(hdcMemory);
Gdiplus::Bitmap *m_pImgLeft;
_pImgLeft = new Bitmap(_T("c:\\Login_msg_left1.png"));
if(m_pImgLeft != NULL)
{
gph.DrawImage(m_pImgLeft, 0, 0,
m_pImgLeft->GetWidth(), m_pImgLeft->GetHeight());
}
:UpdateLayeredWindow(m_hWnd, hdcTemp,
&CPoint(rcWindow.left, rcWindow.top),
&CSize(rcWindow.Width(), rcWindow.Height()),
hdcMemory, &CPoint(0, 0), 0, &Blend, ULW_ALPHA);
/////////以上圈起来的代码不用管//////////////////////////////////////////
以下是重点,是释放GDI资源的重点,顺序是选回旧的GDI对象,删除创建的GDI对象,删除DC
::SelectObject(hdcMemory, oldObj);
::DeleteObject(hBitMap);
::ReleaseDC(m_hWnd, hdcTemp);
::DeleteDC(hdcMemory);
::EndPaint(m_hWnd, &pai);
打开任务栏管理器,选中进程那一个选项卡,点菜单中的查看-》选择列 子菜单,找到GDI对象
确定后在进程列表就能看到
如果是窗体使用GDI,只要把窗体不断放大缩小,就能查看到GDI的使用情况,如果没有正确释放会,你会发现GDI对象数值一直在涨。
好了,今天就说到这呢,有不懂的,可以回复问我。