CreateCompatibleBitmap,关于兼容DC的创建与资源回收
2012-11-10 09:14
447 查看
其实,我的C++入门就是从GDI开始的,想在CE上面写应用程序,若兼程序界面太难看那就必须用回GDI了。GDI是一种古老而又非常麻烦的技术,在C#年代还好点,但VC++下,玩GDI记得最最重要的一点是,一定要注意GDI资源的回收,否则你的程序会没跑几下就弹出错误窗口,原因大概都是内存泄漏。所以凡是遇上CPen,CBrush,CBitmap,GetDC()...等等,请打醒十二分精神。
因为以前吃了太多的亏,原则上我对GDI资源的回收还是挺有自信的,但这世界上总是存在着许多新的状况跟不同的问题的,昨晚认真研究了自己一段有BUG代码,在此作一番记录。
凡在窗体上绘图,必要用到双缓存的技术,而这又离不开两个函数:CreateCompatibleDC与CreateCompatibleBitmap,大概的意思,创建一个跟显示屏幕格式一致的内存段,在此内存段里画好图之后再拷贝到屏幕里(这是我非标准的理解方式),具体的API用法网上有很多很详细的教程,而正常的创建与资源回收的代码如下:
以上经自己实践检验过的代码,ASSERT()的部分都能通过,表示就是真的可以用,若你喜欢的话完全可以写个while函数来测试一下,若资源没回收的话,程序不到跑100次就已经挂掉了。但如果我在同一个pDC下创建两个MemDC时,回收就会有问题了,代码如下:
经过调试后的结论是,pBmp与pBmp2是指向的是同一个东西,MemDC.SelectObject(pBmp)这一句话是断开bmp与MemDC的关联,若不事先断开的话bmp.DeleteObject()就会失败,所以一旦先执行了bRes = pBmp->DeleteObject()这一句,那MemDC.SelectObject(pBmp2)这一句就存在问题了(事实上pBmp2已经被删掉了),导致后面全线崩溃。于是,如果是双兼容DC的话,其正常的回收代码应该如下所示。总之不管三七二十一,先断开兼容DC与兼容位图的关联后,再作相关的资源回收。
因为以前吃了太多的亏,原则上我对GDI资源的回收还是挺有自信的,但这世界上总是存在着许多新的状况跟不同的问题的,昨晚认真研究了自己一段有BUG代码,在此作一番记录。
凡在窗体上绘图,必要用到双缓存的技术,而这又离不开两个函数:CreateCompatibleDC与CreateCompatibleBitmap,大概的意思,创建一个跟显示屏幕格式一致的内存段,在此内存段里画好图之后再拷贝到屏幕里(这是我非标准的理解方式),具体的API用法网上有很多很详细的教程,而正常的创建与资源回收的代码如下:
CDC * pDC = this->GetRealDC();//真实的窗体DC,一般在CWnd下使用GetDC()获得 CDC MemDC; CBitmap bmp; CBitmap * pBmp = NULL; CRect rc = this->GetRect();//窗体的尺寸,一般在CWnd类使用GetClientRect()获得 BOOL bRes = FALSE ; bRes = MemDC.CreateCompatibleDC(pDC); ASSERT(bRes); bRes = bmp.CreateCompatibleBitmap(pDC , rc.Width() , rc.Height()); ASSERT(bRes); pBmp = MemDC.SelectObject(&bmp); ASSERT(pBmp); //Do something //... //一般兼容DC的回收原则是先创建后删除 MemDC.SelectObject(pBmp); bRes = pBmp->DeleteObject(); pBmp = NULL; ASSERT(bRes); bRes = bmp.DeleteObject(); ASSERT(bRes); bRes = MemDC.DeleteDC(); ASSERT(bRes);
以上经自己实践检验过的代码,ASSERT()的部分都能通过,表示就是真的可以用,若你喜欢的话完全可以写个while函数来测试一下,若资源没回收的话,程序不到跑100次就已经挂掉了。但如果我在同一个pDC下创建两个MemDC时,回收就会有问题了,代码如下:
CDC * pDC = this->GetRealDC();//真实的窗体DC,一般在CWnd下使用GetDC()获得 CDC MemDC; CBitmap bmp; CBitmap * pBmp = NULL; CRect rc = this->GetRect();//窗体的尺寸,一般在CWnd类使用GetClientRect()获得 CDC MemDC2; CBitmap bmp2; CBitmap * pBmp2 = NULL; BOOL bRes = FALSE ; bRes = MemDC.CreateCompatibleDC(pDC); ASSERT(bRes); bRes = bmp.CreateCompatibleBitmap(pDC , rc.Width() , rc.Height()); ASSERT(bRes); pBmp = MemDC.SelectObject(&bmp); ASSERT(pBmp); bRes = MemDC2.CreateCompatibleDC(pDC); ASSERT(bRes); bRes = bmp2.CreateCompatibleBitmap(pDC , rc.Width() , rc.Height()); ASSERT(bRes); pBmp2 = MemDC2.SelectObject(&bmp2); ASSERT(pBmp); //Do something //... MemDC.SelectObject(pBmp); bRes = pBmp->DeleteObject(); pBmp = NULL; ASSERT(bRes);//通过 bRes = bmp.DeleteObject(); ASSERT(bRes);//通过 bRes = MemDC.DeleteDC(); ASSERT(bRes);//通过 MemDC2.SelectObject(pBmp2); bRes = pBmp2->DeleteObject(); pBmp2 = NULL; ASSERT(bRes);//失败 bRes = bmp2.DeleteObject(); ASSERT(bRes);//失败 bRes = MemDC2.DeleteDC(); ASSERT(bRes);//通过
经过调试后的结论是,pBmp与pBmp2是指向的是同一个东西,MemDC.SelectObject(pBmp)这一句话是断开bmp与MemDC的关联,若不事先断开的话bmp.DeleteObject()就会失败,所以一旦先执行了bRes = pBmp->DeleteObject()这一句,那MemDC.SelectObject(pBmp2)这一句就存在问题了(事实上pBmp2已经被删掉了),导致后面全线崩溃。于是,如果是双兼容DC的话,其正常的回收代码应该如下所示。总之不管三七二十一,先断开兼容DC与兼容位图的关联后,再作相关的资源回收。
MemDC.SelectObject(pBmp); MemDC2.SelectObject(pBmp2); bRes = pBmp->DeleteObject(); ASSERT(bRes); if (pBmp2 != pBmp) { bRes = pBmp2->DeleteObject(); ASSERT(bRes); } pBmp = NULL; pBmp2 = NULL; bRes = bmp.DeleteObject(); ASSERT(bRes);//通过 bRes = MemDC.DeleteDC(); ASSERT(bRes);//通过 bRes = bmp2.DeleteObject(); ASSERT(bRes);//通过 bRes = MemDC2.DeleteDC(); ASSERT(bRes);//通过
相关文章推荐
- 关于CreateCompatibleBitmap创建位图失败的解决方法
- 解决用CreateCompatibleBitmap()创建兼容位图出现的黑底问题
- CreateCompatibleDC创建兼容DC
- CreateCompatibleDC与CreateCompatibleBitmap
- CreateCompatibleBitmap 和 CreateCompatibleDC
- CreateCompatibleDC与CreateCompatibleBitmap
- CreateCompatibleBitmap 创建透明位图。
- 什么是DC,以及CreateCompatibleDC,CreateCompatibleBitmap,SelectObject的作用
- 调用CreateCompatibleBitmap建立内存DC只有两种颜色的问题
- MFC 把通过CreateCompatibleBitmap创建的HBITMAP 填充白色
- wince6.0 兼容位图CreateCompatibleBitmap和非兼容位图CreateDIBSection的区别
- CreateCompatibleDC,CreateCompatibleBitmap,SelectObject详解
- CreateCompatibleDC,CreateCompatibleBitmap,SelectObject详解
- 画图时 内存不停 增长 的解决 CreateCompatibleDC(NULL) 创建失败
- VC++学习笔记(关于CDC的成员函数CreateCompatibleDC(HDC hdc))
- CreateCompatibleDC,CreateCompatibleBitmap,SelectObject详解
- CreateCompatibleDC与CreateCompatibleBitmap
- Bitmap处理之创建可自动回收资源的ImageView
- Bitmap处理之创建可自动回收资源的ImageView
- Bitmap处理之创建可自动回收资源的ImageView