首页 > 代码库 > 关于操作DC时的资源泄露

关于操作DC时的资源泄露

首先应明确一个概念 句柄, 关于句柄的详细介绍请见这里

对于句柄的使用小结:借来的要归还,创建的要释放,选出的要选入【尤其是针对GDI的一些句柄而言,如HPEN,HBRUSH等】

 

1. 使用GetDC() 获取的设备上下文指针在不使用的时候必须调用ReleaseDC()进行释放

例如:

1 CDC *pDC = GetDlgItem(IDC_TEST)->GetDC();2 3 /*...............*/4 5 GetDlgItem(IDC_TEST)->ReleaseDC(pDC);
View Code

 

2. 在创建了DC或其他GDI资源后,如果不再使用则需要将所创建的资源进行释放

例如:

1 CDC dcMem;2 3 dcMem.CreateCompatibleDC(NULL);4 5 /*..............*/6 7 dcMem.DeleteDC();

 

3. 在将创建的GDI绘图对象选入了设备上下文后,如果使用完毕则需要将之前选出的旧有的GDI绘图对象选入,然后在删除所创建的GDI对象

例如:

 1 CBitmap bmp; 2  3 bmp.CreateCompatibleBitmap(pDC, nWidht, nHeight); 4  5 CBitmap *pBmpOld = memDC.SelectObject(&bmp); 6  7 /*..................................*/ 8  9 memDC.SelectObject(pBmpOld);10 11 bmp.DeleteObject();

说明:一定要注意SelectObject的操作通常要成对出现,否则可能会导致GDI资源泄露。例如上面的例子,如果在最后我们没有执行语句

memDC.SelectObject(pBmpOld);只是调用了bmp.DeleteObject(),此时对于bmp资源的释放是失败的,即无法将之前所创建的位图图像删除。

 

Attach 的需要Detach

例如:

 1 CImage img; 2  3 if (SUCCEEDED(img.Load(strFileName))) 4  5 { 6  7   HBITMAP hBitmap = img.Detach(); 8  9   /*......................*/10 11   img.Attach(hBitmap);12 13 }14 15 img.Destroy();

 

1. 被选入的绘图对象(如:bitmap、brush等)无法删除,只有当调用SelectObject将对象选出后才可以删除
2. 对于SelectObject()成对出现的原因?
例如:
1 bitmap = CreateCompatibleBitmap(...); 2 HBITMAP oldbitmap = SelectObject(hdc, bitmap); 3 ... 4 SelectObject(hdc, oldbitmap); 5 DeleteObject(&bitmap) 
注意:
1. SelectObject必须成对存在
2. 对于上面代码段的第四行,调用SelectObject将oldbitmap选入之后不需要将返回值再赋给bitmap,此时bitmap已经是最新的位图对象了(哪怕在语句3对选入的位图进行了操作)
3. 对于GDI绘图资源的释放一定要注意,一旦有资源没有得到释放,而且执行的频率又非常频繁的情况下,就很容易导致资源无法创建的问题。尤其是在OnCtlColor中一定不要创建画刷等绘图对象,而是应该将需要用到的绘图对象定义为类的成员变量。
4. 由于对于GDI而言,windows只使用了16位字段来指明句柄,因此所能创建的GDI句柄总数应不大于64K个,实际上受其他一些限制,整个windwos系统中大概可以容纳约16384(0x4000)个GDI对象。一旦超过这个总数,就会使得Windows抛出ResourceException

关于操作DC时的资源泄露