Win32 application. HBITMAP LoadImage fails to load anything

user1919573 picture user1919573 · Dec 14, 2013 · Viewed 8.6k times · Source

I'm writing a function that quickly draws an image of a menu for a game I'm making. I'm able to draw the background and text blocks just fine but I'm having trouble creating a bitmap image on the screen

bool menu::drawMenu(PAINTSTRUCT ps)
{
HWND hWnd = GetActiveWindow();
HDC hdc = GetDC(hWnd), hdcMem;

//Draw a new background

HPEN blackPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
SelectObject(hdc, blackPen);
SelectObject(hdc, blackBrush);
Rectangle(hdc, 0, 0, 1080, 720);

//insert selection text

TextOut(hdc, 30, 0, L"New Game", 8);
TextOut(hdc, 30, 30, L"Exit Game", 9);

//draw arrow sprite

HBITMAP arrow = (HBITMAP)LoadImage(NULL, L"C:\\Users\\Tim\documents\\visual studio 2013\\Projects\\BoulderBisque\\BoulderBisque\\arrow.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    DWORD lastError = GetLastError();
if (arrow == NULL)
{
    TextOut(hdc, 0, 60, L"Image Load Failed", 17);
    return false;
}
hdcMem = CreateCompatibleDC(hdc);
if (hdcMem == NULL)
{
    TextOut(hdc, 0, 90, L"Memory Creation Failed", 22);
    return false;
}
SelectObject(hdcMem, arrow);
BitBlt(hdc, 0, choice * 30, 16, 16, hdcMem, 0, 0, SRCCOPY);

//cleanup

ReleaseDC(hWnd, hdc);
DeleteDC(hdcMem);

return true;
}

As of now arrow is NULL and I get the Load Image Failed textbox. I am using the relative path of arrow.bmp I also tried using a full path, that didn't work either.

You may have noticed that this function is outside the WndProc. Everything else draws fine. I tried running it in there too everything but the arrow.bmp loads.

What am I doing wrong to cause arrow.bmp to be NULL? I have other methods I plan to run in similar ways so getting this function to run would really be a big help.

EDIT* Whenever I give the full path name it still fails to load. Also is this not the appropriate code for SO? This is my first question...

EDIT** The aditional '/'s haven't fixed the issue.

EDIT*** Using GetLastError, I found the error code to be 2, ERROR_FILE_NOT_FOUND

Answer

David Heffernan picture David Heffernan · Dec 14, 2013

Your early versions of the question checked the return value of LoadImage but then did nothing more. The documentation says this:

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

So, if the function fails, call GetLastError to find out why. When you do so, you obtain the error code ERROR_FILE_NOT_FOUND. Which is pretty conclusive. The filename that you specified does not exist.

Do note that the code in the latest update to the question calls GetLastError unconditionally. That is a mistake, one that is seen all too frequently here on Stack Overflow. The documentation only tells you to call GetLastError when the call to LoadImage fails. If the call to LoadImage succeeds, then the value return by GetLastError is meaningless. Error handling in Win32 is largely handled in the same way as LoadImage does it, but not always. So you have to read the documentation very carefully.


Perhaps instead of

C:\\Users\\Tim\documents\\...

you meant

C:\\Users\\Tim\\documents\\...

OK, now you've got the path right. The call to LoadImage returns NULL, but GetLastError is no longer helpful and returns ERROR_SUCCESS. Which is weird in itself.

I believe that the problem is that your image uses a format that LoadImage does not understand. I took your .bmp file, loaded it in Paint.net and then re-saved it. Once I did that, the re-saved image was loaded successfully.


Rather than trying to load this from a file it would make far more sense to link the image as a resource and load it that way.