views:

131

answers:

2

Hi,

I have the following code to take a screenshot of a window, and 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?

+6  A: 

You must destroy GDI objects with DeleteObject, not delete. The latter is only used to free objects allocated using new.

avakar
+2  A: 

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.

Charles Bailey