Reputation: 6615
I am trying to write a screen capture/record application. Here's the part of the code that captures the screen and saves it:
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);
After a thousand or so repetitions, my cout statement will show the newly created handle as 000000000000000 aka. NULL. My app works fine until that point.
I am deleting the created DC and bitmap each time so there is no memory leak. Task Manager also confirms there is no memory leak. So what is happening?
Thank you for anyone who can assist in this.
Upvotes: 4
Views: 3175
Reputation: 37132
As mentioned in the comments, the two problems were 1) you weren't releasing the DC obtained from the desktop window, and 2) you weren't selecting the original bitmap back into the compatible DC before deleting it. Both of these cause a GDI resource leak which will lead to the symptoms you describe.
Fixed code below:
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);
You should also be doing proper error checking (as calls like GetDC
, CreateCompatibleDC
etc can fail and return NULL).
Upvotes: 6