Home > Blockchain >  GetObject failing when trying to load a bitmap
GetObject failing when trying to load a bitmap

Time:10-26

I've been trying to load a simple bitmap and draw a button using that bitmap. So far, so good. I've found that you're supposed to be able to create said button with the BS_OWNERDRAW flag and intercept the WM_DRAWITEM message in WndProc. Which is exactly what I've done. If I draw simple shapes such as FillRect, it works very well. GetLastError() also returns 0. The bitmap is loaded from a resource file, compiled with windres and linked along with the rest with gcc. If I extract the .bmp using 7zip from the .exe, I have no trouble opening it with anything. I've also tried with more than one, even drawn one using paint, the bitmap itself seems fine. Here's the code:

void on_WM_DRAWITEM(DRAWITEMSTRUCT* drawItem, HWND hwnd)
{
    HRSRC bmRes = FindResourceW(NULL, (LPCWSTR)MAKEINTRESOURCE(MY_BITMAP), (LPCWSTR)RT_BITMAP);
    HBITMAP hBm = LoadResource(NULL, bmRes);
    BITMAP bm;
    HDC memDC = CreateCompatibleDC(drawItem->hDC);
    if(hBm != NULL)
    {
        printf("HRSRC: %p\n", bmRes);
        printf("HBITMAP: %p\n", hBm);
        printf("HDC: %p\n", memDC);

        if(GetObject(hBm, sizeof(bm), &bm) != 0)
        {
            printf("Not printing\n");
            WINBOOL b = DrawStateW(memDC, NULL, NULL, (LPARAM)hBm, 0, 0, 0, 0, 0, DST_BITMAP);
            //BitBlt(drawItem->hDC, 0, 0, 50, 50, memDC, 0, 0, SRCCOPY);
        }
        printf("BITMAP: %p\n", bm);
        printf("BITMAP BITS: %p\n", bm.bmBits);
    }
    DeleteDC(memDC);
    DeleteObject(bmRes);
    DeleteObject(hBm);
}

The output of these prints:

HRSRC: 00007ff665ce70a0
HBITMAP: 00007ff665d484c0
HDC: 000000002d010e19
BITMAP: 000000d387bfef70
BITMAP BITS: 000014e0000014e0

Everything seems valid, nothing is null. Despite failing, the bits seems like they're getting set. I've tried to check the memory at this address, but it doesn't seem like I have access to this address range. I'm not sure how windows handles are supposed to work vs pointers, am I supposed to be able to print them like that, as pointers?

Even if I put the BitBlt or DrawStateW, both of which are supposed to work, outside the if, they both fail as well.

Compiled using gcc with MinGW.

CodePudding user response:

LoadResource() returns an HGLOBAL handle to a block of memory, not an HBITMAP handle to a bitmap image. They do not represent the same thing, so GetObject() fails due to you giving it the wrong type of handle.

You should enable STRICT Type Checking in your project so your code will fail to compile when mismatches like this occur.

The correct way to get an HBITMAP handle for a bitmap in a resource is to use LoadBitmap() or LoadImage() instead, eg:

void on_WM_DRAWITEM(DRAWITEMSTRUCT* drawItem, HWND hwnd)
{
    HBITMAP hBm = (HBITMAP) LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(MY_BITMAP), IMAGE_BITMAP, 0, 0, 0);
    if (hBm != NULL)
    {
        ...
        DeleteObject(hBm);
    }
}
  • Related