关于操作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

你可能感兴趣的:(资源)