deleting HBITMAP causes an access violation at runtime
I have the following code to take a screenshot of a window, and开发者_C百科 get the colour of a specific pixel in it:
void ProcessScreenshot(HWND hwnd){
HDC WinDC;
HDC CopyDC;
HBITMAP hBitmap;
RECT rt;
GetClientRect (hwnd, &rt);
WinDC = GetDC (hwnd);
CopyDC = CreateCompatibleDC (WinDC);
//Create a bitmap compatible with the DC
hBitmap = CreateCompatibleBitmap (WinDC,
rt.right - rt.left, //width
rt.bottom - rt.top);//height
SelectObject (CopyDC, hBitmap);
BitBlt (CopyDC, //destination
0,0,
rt.right - rt.left, //width
rt.bottom - rt.top, //height
WinDC, //source
0, 0,
SRCCOPY);
COLORREF col = ::GetPixel(CopyDC,145,293);
// Do some stuff with the pixel colour....
delete hBitmap;
ReleaseDC(hwnd, WinDC);
ReleaseDC(hwnd, CopyDC);
}
the line 'delete hBitmap;' causes a runtime error: an access violation. I guess I can't just delete it like that?
Because bitmaps take up a lot of space, if I don't get rid of it I will end up with a huge memory leak. My question is: Does releasing the DC the HBITMAP is from deal with this, or does it stick around even after I have released the DC? If the later is the case, how do I correctly get rid of the HBITMAP?
You must destroy GDI objects with DeleteObject
, not delete
. The latter is only used to free objects allocated using new
.
delete
should only be used to deallocate things allocated via new
.
HBITMAP
is a bitmap handle and you need to release the associated object using the GDI function DeleteObject
.
Strictly, you should save the result of SelectObject
from when you selected the bitmap into the device context and pass that to another call to SelectObject
to ensure that the bitmap is not in use by the device context when you call DeleteObject
. Things often work if you don't do this, especially if you're about to release the device context anyway but it is safest to do so.
精彩评论