views:

10

answers:

1

I have the picture control created with SS_BITMAP style and bitmap created on a memory DC. so can or how can you set the HBITMAP of a DDB for the control? It doesn't work with using:

Edit:

    HDC hDC = GetDC(hPB); //hPB, Handle to static control.
    HDC hMemDC = ::CreateCompatibleDC(hDC);
    HBITMAP hDDB = ::CreateCompatibleBitmap(hDC, 17, 14);
    SelectObject(hMemDC, hDDB);

    //Draw on DDB     

    SendMessage(hPB, STM_SETIMAGE, IMAGE_BITMAP, LPARAM(hDDB));

    DeleteObject(hDDB);
    DeleteObject(hBrush);
    ReleaseDC(hPB, hDC);
+1  A: 
  1. GDI handles have a process affinity - you cannot STM_SETIMAGE to a static control in another process.

  2. Next: STM_SETIMAGE is not guaranteed to make a copy of the bitmap - mostly it retains the passed in HBITMAP handle. In the line following the SendMessage you delete the hDDB handle leaving the static control with an invalid bitmap.

The static control expects to control the life of the passed in bitmap - and will attempt to DestroyObject the bitmap handle when it is destroyed - this means you must:

  1. Destroy any old HBITMAP returned by the SendMessage call - calling STM_SETIMAGE transfers ownership (and responsibility to destroy) of the old bitmap to the calling code.(1)
  2. Dont pass a single HBITMAP to multiple controls as the first one to close will destroy it - ruining the party for the other controls.

Note: If your app uses common controls 6 to get the visual styles controls, the static control never destroys any bitmap passed via STM_SETIMAGE, so the app needs to destroy any returned handles AND passed in handles.


I think that //Draw on DDB is in place of removed code? In which case, looking at the sample code that IS present, my psychic powers say that the problem is because you are not selecting the bitmap OUT of the memory DC. You need to make it look like this (re-arranged to cleanup in inverse order of creation):

HDC hDC = GetDC(hPB);
HBITMAP hDDB = ::CreateCompatibleBitmap(hDC, 17, 14);
HDC hMemDC = ::CreateCompatibleDC(hDC);
HGDIOBJ hOld = SelectObject(hMemDC, hDDB);
//Draw on DDB here...    
SelectObject(hMemDC,hOld); // this releases the hDDB
DeleteDC(hMemDC);
ReleaseDC(hPB, hDC);

HBITMAP hbmPrev = (HBITMAP)SendMessage(hPB, STM_SETIMAGE, IMAGE_BITMAP, LPARAM(hDDB));
if(hbmPrev && hbmPrev != hDDB)
  DeleteObject(hbmPrev);
Chris Becke
It doesn't set the bitmap even when i run the line SendMessage in debugger. I also commented the line followed "DeleteObject(hDDB)".
xor
See addition. It seems that you are not restoring hMemDC to its initial state after painting. HBITMAPs cannot be selected into multiple DCs at once, so the STM_SETIMAGE call might be failing because of that.
Chris Becke