【问题标题】:Why does CreateCompatibleBitmap fail after about a thousand executions?为什么 CreateCompatibleBitmap 在大约一千次执行后会失败?
【发布时间】:2013-03-30 00:47:02
【问题描述】:

我正在尝试编写屏幕捕获/记录应用程序。这是捕获屏幕并保存它的代码部分:

width = GetSystemMetrics(SM_CXMAXTRACK)+8;
height = GetSystemMetrics(SM_CYMAXTRACK)-8;

hwindowDC=GetDC(GetDesktopWindow());
hwindowCompatibleDC=CreateCompatibleDC(hwindowDC);
SetStretchBltMode(hwindowCompatibleDC,COLORONCOLOR);  

// create a bitmap
hbwindow = CreateCompatibleBitmap( hwindowDC, width, height);
cout << " handle to newly created bitmap: " << hbwindow << "\n";

SelectObject(hwindowCompatibleDC, hbwindow); //copy from hwindowCompatibleDC to hbwindow
StretchBlt( hwindowCompatibleDC, 0,0, width, height, hwindowDC, 0, 0,width,height, SRCCOPY); //change SRCCOPY to NOTSRCCOPY for wacky colors !

src.create(height,width,CV_8UC4);   
src.empty();
GetDIBits(hwindowCompatibleDC,hbwindow,0,height,src.data,(BITMAPINFO *)&bi,DIB_RGB_COLORS); 


DeleteDC(hwindowCompatibleDC); 
DeleteObject(hbwindow);

大约一千次重复后,我的 cout 语句将新创建的句柄显示为 000000000000000 aka。空值。在此之前,我的应用程序运行良好。
我每次都删除创建的 DC 和位图,因此没有内存泄漏。任务管理器还确认没有内存泄漏。那么发生了什么?

感谢任何可以为此提供帮助的人。

【问题讨论】:

  • 您应该从 DC 中选择对象,然后删除对象,然后删除 DC。
  • 虽然听起来很奇怪,但在删除 dc 和位图之前尝试将 old 位图重新选择到您的 dc 中(为了绝对好的衡量,请选择旧的,然后删除 hbwindow,然后删除兼容的 dc)。此外,这场惨败结束时的ReleaseDC(hWindowDC) 似乎不见了。
  • @JesseGood 记住。删除你创造的,释放你得到的。 应该释放窗口 DC,所以你是对的。
  • @WhozCraig:是的,我刚刚意识到这一点。谢谢。 编辑:是的,这一点很好。
  • 始终检查返回值并酌情调用GetLastError

标签: c++ bitmap


【解决方案1】:

如 cmets 中所述,这两个问题是 1) 您没有释放从桌面窗口获得的 DC,以及 2) 您在删除之前没有将原始位图选择回兼容的 DC。这两者都会导致 GDI 资源泄漏,从而导致您描述的症状。

下面的固定代码:

width = GetSystemMetrics(SM_CXMAXTRACK)+8;
height = GetSystemMetrics(SM_CYMAXTRACK)-8;

hwindowDC=GetDC(GetDesktopWindow());
hwindowCompatibleDC=CreateCompatibleDC(hwindowDC);
SetStretchBltMode(hwindowCompatibleDC,COLORONCOLOR);  

// create a bitmap
hbwindow = CreateCompatibleBitmap( hwindowDC, width, height);
cout << " handle to newly created bitmap: " << hbwindow << "\n";

// SAVE OLD BITMAP
HGDIOBJ hOldBmp = SelectObject(hwindowCompatibleDC, hbwindow); //copy from hwindowCompatibleDC to hbwindow
StretchBlt( hwindowCompatibleDC, 0,0, width, height, hwindowDC, 0, 0,width,height, SRCCOPY); //change SRCCOPY to NOTSRCCOPY for wacky colors !

src.create(height,width,CV_8UC4);   
src.empty();
GetDIBits(hwindowCompatibleDC,hbwindow,0,height,src.data,(BITMAPINFO *)&bi,DIB_RGB_COLORS); 

// RESTORE OLD BITMAP
SelectObject(hwindowCompatibleDC, hOldBmp);
DeleteDC(hwindowCompatibleDC); 
DeleteObject(hbwindow);

// RELEASE WINDOW DC
ReleaseDC(GetDesktopWindow(), hwindowDC);

您还应该进行适当的错误检查(因为像 GetDCCreateCompatibleDC 等调用可能会失败并返回 NULL)。

【讨论】:

  • 您听起来好像知道自己在说什么,所以我相信这就是答案。但 ReleaseDC 不接受 1 个参数。
  • 当然你是对的 :) 已在答案中修复。尝试同时做三件事的危险!
  • @user396483 你选择了......明智 =) 记住,释放得到的东西,删除你的东西创建。这几乎适用于 GDI Windows 中的所有工作。 (当然,如果适用的话,恢复你的垃圾)。顺便说一句,+1 答案。
  • 分离附加的东西;P
猜你喜欢
  • 1970-01-01
  • 2015-11-21
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-17
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
相关资源
最近更新 更多