Problem - HDC & BitBlt & PictureControl - stops working after some time

So, hello there.
I have a problem - i have three bitmaps, one created with LoadImage (originalBitmap, loaded from file), the rest of them (displayBitmap, collisionBitmap) created by CreateCompatibleBitmap. I have a dialog with PictureControl control.

It goes on like this - there are two scrollbars which manipulate which part of bitmaps (originalbitmap and collisionBitmap) shall be displayed on PictureControl. By using Bitblt and TransparentBlt i copy the corresponding bitmaps onto displayBitmap. There's also a function that draws rectangles on collisionBitmap when i click in the corresponding place..

After some time (by time, i mean moving the scrollbars and/or clicking the bitmap) it stops working. Nothing is copied, nothing is displayed. Only blank.

The corresponding functions -

int WindowStructure::refreshPictureControl(){

HWND hPictCont = GetDlgItem(windowHandle, IDC_PICCONTROL);

windowHDC = ::GetWindowDC(NULL);
originalHDC = ::CreateCompatibleDC(windowHDC);
::SelectObject(originalHDC,originalBitmap);
displayHDC = ::CreateCompatibleDC(windowHDC);
displayBitmap = ::CreateCompatibleBitmap(windowHDC,pictureControlWidth,pictureControlHeight);
::SelectObject(displayHDC,displayBitmap);
additionalDisplayHDC = ::CreateCompatibleDC(windowHDC);

BitBlt(displayHDC,0,0,pictureControlWidth,pictureControlHeight,originalHDC,horizontalOffset,verticalOffset,SRCCOPY);


::SelectObject(additionalDisplayHDC,collisionBitmap);
TransparentBlt(displayHDC,0,0,pictureControlWidth,pictureControlHeight,additionalDisplayHDC,horizontalOffset,verticalOffset,pictureControlWidth,pictureControlHeight,RGB(0,0,0));

::DeleteDC(originalHDC);
::DeleteDC(additionalDisplayHDC);
::DeleteDC(displayHDC);
::DeleteDC(windowHDC);

LONG ln = ::GetWindowLong(hPictCont,GWL_STYLE);

::SetWindowLong(hPictCont,GWL_STYLE,(ln|SS_BITMAP)&(~SS_CENTERIMAGE));

SendMessage(hPictCont, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)displayBitmap);

return (INT_PTR)TRUE;
}

The function that draws rectangles -

int WindowStructure::drawColourRectangle(){

windowHDC = ::GetWindowDC(NULL);
additionalDisplayHDC = ::CreateCompatibleDC(windowHDC);
::SelectObject(additionalDisplayHDC,collisionBitmap);

HBRUSH purpurowyPedzel;
RECT infoRectangle = {chosenChipsetX*32,chosenChipsetY*32,(chosenChipsetX+1)*32,(chosenChipsetY+1)*32};

purpurowyPedzel = CreateSolidBrush(RGB(255,0,255));


FillRect(additionalDisplayHDC,&infoRectangle,purpurowyPedzel);


DeleteObject(purpurowyPedzel);

::ReleaseDC(windowHandle,windowHDC);
::ReleaseDC(windowHandle,additionalDisplayHDC);

refreshPictureControl();

return 1;
}


the refreshPictureControl i called from within drawColourRectangle and when scrollbars are moved.

I know that i'm doing something wring with HDC's, but i fail to see the point.
You're doing cleanup all wrong. What's probably happening is a ginourmous memory leak, and future calls are failing to allocate the memory required.

Nearly every GDI function has its appropriate cleanup action. What's worse, the cleanup action you need to take is different for each thing.

1) For SelectObject() to put a HBITMAP in a HDC, you need to clean up by calling SelectObject() again with the old bitmap.
2) For CreateCompatibleDC(), or any CreateDC type function, you need to call DeleteDC() -- NOT ReleaseDC(). ReleaseDC should only be used to clean up GetDC() or GetWindowDC()
3) To clean up CreateBitmap or CreateCompatibleBitmap, or LoadBitmap, or any of those kinds of things, you call DeleteObject. Do not attempt to call DeleteObject on an object that is selected in a DC. Also do not try to DeleteObject something you didn't create yourself.

Also, consider the differences between GetWindowDC and GetDC. GetWindowDC gets the DC for the entire window (title bar, menu bar, etc all included), whereas GetDC just gets the client area (ie: the part you actually draw in). Since you're passing NULL you're getting the entire desktop! (This is very strange -- do you not have your own window created or something?)

Here's an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
HBITMAP bmp = /* assume previously loaded */;
HDC displaydc = GetDC( hwnd_to_your_window );
HDC mdc = CreateCompatibleDC( displaydc ); // NULL also might work here, IIRC

// select the 'bmp' into 'mdc'
//   be sure to record the value returned, so we can put it back
HBITMAP bmpold = (HBITMAP)SelectObject(mdc,bmp);

   // use mdc and displaydc to draw here

  // then... when all done:

// select the old bitmap back into mdc, then delete it
SelectObject(mdc,bmpold);
DeleteDC(mdc);

// release display
ReleaseDC(displaydc);

// safe to cleanup 'bmp' if you need to destroy it.  Use DeleteObject() for that.
//   do not try to destroy it if it is selected in a DC.
DeleteObject(bmp);

  // but do NOT DeleteObject(bmpold) -- you didn't create it, so don't delete it. 
Topic archived. No new replies allowed.