关于CreateBitmap和CreateCompatibleBitmap

wmouse 2006-04-17 09:14:35
首先现象是这样的:
我的程序突然有一天,一个Create出来的窗口画不出东西,开了天窗!跟进去一看,是调用CBitmap::CreateBitmap失败(返回值为FALSE)。用GetLastError查到的原因是“ERROR_NOT_ENOUGH_MEMORY”。
很奇怪,这个view的代码我并没有动啊!我试着改成CBitmap::CreateCompatibleBitmap,好了!算了,不管了,就这么着吧~
谁知,过了些时日,别的窗口又开天窗了!
这次我把CreateBitmap改成CreateCompatibleBitmap,也不是每次都成功,时不时的就会创建失败!

查msdn,关于CreateBitmap API有如下这一段话:
The CreateBitmap function can be used to create color bitmaps.
However, for performance reasons applications should use CreateBitmap to create monochrome bitmaps and CreateCompatibleBitmap to create color bitmaps.
Whenever a color bitmap returned from CreateBitmap is selected into a device context, the system checks that the bitmap matches the format of the device context it is being selected into.
Because CreateCompatibleBitmap takes a device context, it returns a bitmap that has the same format as the specified device context.
Thus, subsequent calls to SelectObject are faster with a color bitmap from CreateCompatibleBitmap than with a color bitmap returned from CreateBitmap.

这段话看着挺绕,说CreateCompatibleBitmap API比CreateBitmap API的效率更高一些。那么,我的问题之一是:
CBitmap的这两个属性,是否也如API一样,CreateCompatibleBitmap比CreateBitmap的效率高??

我的问题之二:搜了一下,我的程序里,有二十多处地方(17个窗口)调用CreateBitmap,10处地方调用CreateCompatibleBitmap,且这些占用bitmap的窗口只在最后退出的时候才销毁。有经验的同仁看看,调用的地方是不是太多了?如果都换成CreateCompatibleBitmap,资源占用情况是否会有所改观?




...全文
1769 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
DoItFreely 2006-04-26
  • 打赏
  • 举报
回复
因为窗口大小已经改变了,原先的bmp大小不合适,所以我是先把原先的bmp删除掉,再重新创建一次。
只要窗口大小不再改变就不创建新的bmp
这样做的好处是省掉了每次绘制时创建DC和bmp的麻烦,缺点是多占了内存
BBirdlyh 2006-04-18
  • 打赏
  • 举报
回复
正如bobob(PDFViewer2.0 Release拉!) 说得,确实是得有m_pMemBitmap = NULL;//
还有一点 为什么要“Create一个符合当前窗口大小的位图”啊,直接STRETCHBLT 不行吗
DoItFreely 2006-04-18
  • 打赏
  • 举报
回复
我的做法是这样子:
声明两个成员
CDC m_dc;
CBitmap m_bmp;

在OnPaint()里面
if(!m_dc.m_hDC)//创建内存DC和bitmap,并Select进去
//接下来使用,并不删除该DC/bitmap

在OnSize()里面
m_dc.DeleteDC();
m_bmp.DeleteObject();

频繁new/delete容易导致内存碎片,除了效率不高之外,在Win9x上经常会导致创建GDI对象失败
lixiaosan 2006-04-18
  • 打赏
  • 举报
回复
bobob比我快一步阿。。。~~~~~
bobob 2006-04-18
  • 打赏
  • 举报
回复
看看这个,或许能有一点用
http://blog.csdn.net/bobob/archive/2005/12/29/565188.aspx
lixiaosan 2006-04-18
  • 打赏
  • 举报
回复
if(NULL != m_pMemBitmap)
{
m_pMemBitmap->DeleteObject();
delete m_pMemBitmap;
m_pMemBitmap = NULL;
}
bobob 2006-04-18
  • 打赏
  • 举报
回复
在Create之前,都有类似如下的代码:
if(NULL != m_pMemBitmap)
{
m_pMemBitmap->DeleteObject();
delete m_pMemBitmap;
}
m_pMemBitmap = new CBitmap;
BOOL b = m_pMemBitmap->CreateCompatibleBitmap(pDC,rcClient.Width(),rcClient.Height());
感觉没有什么可泄漏的。

==================>

晕,真是这样写的话就泄露了,而且露的很厉害
if(NULL != m_pMemBitmap)
{
m_pMemBitmap->DeleteObject();
delete m_pMemBitmap;
m_pMemBitmap = NULL;//光delete, m_pMemBitmap 是不会为NULL的
}
wmouse 2006-04-18
  • 打赏
  • 举报
回复
OnSize时窗口大小改变了,Create一个符合当前窗口大小的位图(Create前先销毁旧的)。
BBirdlyh 2006-04-18
  • 打赏
  • 举报
回复
能不能再具体点,为什么会在OnSize 里频繁的CREATEBITMAP 呢
wmouse 2006-04-18
  • 打赏
  • 举报
回复
在Create之前,都有类似如下的代码:
if(NULL != m_pMemBitmap)
{
m_pMemBitmap->DeleteObject();
delete m_pMemBitmap;
}
m_pMemBitmap = new CBitmap;
BOOL b = m_pMemBitmap->CreateCompatibleBitmap(pDC,rcClient.Width(),rcClient.Height());
感觉没有什么可泄漏的。

“不是调用地方多少的问题,你可能经常创建而没有销毁”
——在创建之前,都会这样销毁一下。
我之所以担心调用的地方多,是因为这些窗口在程序运行过程中,一直没有销毁,所以MainFrame OnSize的时候,大家都OnSize,于是都创建Bitmap(当然创建之前会先销毁旧的),即便是Z-Order在下面的窗口也会创建。
这样,二十个窗口都占用Bitmap资源,即便没有资源泄漏,是否也会造成我描述的现象?


关于资源泄漏,我再用boundchecker查查看~
wmouse 2006-04-18
  • 打赏
  • 举报
回复
你把所有关于gdi操作的地方都贴出来,让大家看看
——挺多的,别说贴着累,大家看着都累。


或者,如果gdi使用情况很复杂的话你用boundschecker测试一下
——boundschecker没有显示和gdi有关的提示(我没有用boundschecker build,只用boundschecker调试,尽量多跑分支)


不过我会根据bobob的经验总结对照一下我程序里有哪些不合理的地方
bobob 2006-04-18
  • 打赏
  • 举报
回复
你把所有关于gdi操作的地方都贴出来,让大家看看
或者,如果gdi使用情况很复杂的话你用boundschecker测试一下
xiangrujian 2006-04-18
  • 打赏
  • 举报
回复
学习
wmouse 2006-04-18
  • 打赏
  • 举报
回复
不对呀,即便是
if(NULL != m_pMemBitmap)
{
m_pMemBitmap->DeleteObject();
delete m_pMemBitmap;
}
m_pMemBitmap = new CBitmap;
也不会造成什么恶劣问题吧?
delete之后虽然没有置为NULL,在之后紧接着new了。下次进来的时候,m_pMemBitmap不是NULL,正好去DeleteObject();
即便在括号里让m_pMemBitmap = NULL;出来就紧接着new了,对条件没什么影响呀!不管是否置为NULL,下次都会满足if(NULL != m_pMemBitmap),都会去DeleteObject();



另外,bobob你的帖子我看了,有收获,多谢!
wmouse 2006-04-18
  • 打赏
  • 举报
回复
哦呵呵,居然犯了这么低级的错误,我赶紧瞧瞧去~
bobob 2006-04-18
  • 打赏
  • 举报
回复
多谢大家!

我知道单单delete是不会置为NULL的,如果不m_pMemBitmap = NULL;是说这块内存就不会给别人使用么(因此泄漏)?似乎涉及到window内存管理的问题。

==============>
你看看你的判断条件
wmouse 2006-04-18
  • 打赏
  • 举报
回复
多谢大家!

我知道单单delete是不会置为NULL的,如果不m_pMemBitmap = NULL;是说这块内存就不会给别人使用么(因此泄漏)?似乎涉及到window内存管理的问题。



回答BBird,尺寸改变后我并不是缩放,而是根据新的尺寸,重新布局,用相同的字体绘制,所以要重新create。

To Freely:
你是在m_bmp.DeleteObject();之后又m_bmp.CreateBitmap(...);是么?
菜牛 2006-04-18
  • 打赏
  • 举报
回复
不是调用地方多少的问题,你可能经常创建而没有销毁。看看你创建的地方是不是会重复调用。
DentistryDoctor 2006-04-17
  • 打赏
  • 举报
回复
估计你有资源泄漏。

19,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧