为什么CreateCompatibleBitmap在大约一千次执行后失败?

时间:2013-04-08 02:59:56

标签: c++ bitmap

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

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和位图,因此没有内存泄漏。任务管理器还确认没有内存泄漏。那么发生了什么?

感谢所有能为您提供帮助的人。

1 个答案:

答案 0 :(得分:6)

正如评论中所提到的,这两个问题是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。