Bitmaps in Win32 GUI

I have a problem loading a bitmap file into a window in a Win32 gui application. What am I doing wrong. Everything compile fine and no errors in loading.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
char bmpfile[] = "Wizard.bmp";


/***********************************************
bool LoadBMPIntoDC ( HDC hDC, LPCTSTR bmpfile )

Takes in a device context and the name of a
bitmap to load. If an error occurs the function
returns false, else the contents of the bmp
are blitted to the HDC

************************************************/

bool LoadBMPIntoDC (HDC hDC, LPCTSTR bmpfile )
{
	// check if params are valid
	if ( ( NULL == hDC  ) || ( NULL == bmpfile ) )
        MessageBox(0, "Window Parameters Failed!", "Error!", MB_ICONSTOP | MB_OK);
		return false;

	// load bitmap into a bitmap handle
	HANDLE hBmp = LoadImage ( NULL, bmpfile, IMAGE_BITMAP, 0, 0,
		LR_LOADFROMFILE );

	if ( NULL == hBmp )
        MessageBox(0, "Window Handler Failed!", "Error!", MB_ICONSTOP | MB_OK);
		return false;        // failed to load image

	// bitmaps can only be selected into memory dcs:
	HDC dcmem = CreateCompatibleDC ( NULL );

	// now select bitmap into the memory dc
	if ( NULL == SelectObject ( dcmem, hBmp ) )
	{	// failed to load bitmap into device context
		DeleteDC ( dcmem );
        MessageBox(0, "Window Load Failed!", "Error!", MB_ICONSTOP | MB_OK);
		return false;
	}

	// now get the bmp size
	BITMAP bm;
	GetObject ( hBmp, sizeof(bm), &bm );
	// and blit it to the visible dc
	if ( BitBlt ( hDC, 0, 0, bm.bmWidth, bm.bmHeight, dcmem,
		0, 0, SRCCOPY ) == 0 )
	{	// failed the blit
		DeleteDC ( dcmem );
        MessageBox(0, "Window Failed!", "Error!", MB_ICONSTOP | MB_OK);
		return false;
	}

	DeleteDC ( dcmem );  // clear up the memory dc

	return true;
}
1. In line 30, you should use hDC instead of NULL as argument to CreateCompatibleDC().
2. You need to save the object returned by SelectObject() in line 33. It will be the previous bitmap that you absolutely need if you want to free the resources associated with hBmp.
3. Before deleting the compatible DC in line 52, you need to select the old bitmap obtained in line 33, and then delete the DC.
4. You are leaking the bitmap in hBmp. Use DeleteObject() to release it after you have de-selected it from the compatible DC.

Other than that, I think it should work.
Thanks for your help. I will try your suggestions and see how it works out. One of the things I don't understand is the call return false but none of the message boxes get printed out. Can you explain why?
The if() in line 17 is missing the braces, meaning only the MessageBox() call is inside the if(), then line 19 is inconditionally executed every time.

You already follow the best practice of putting the value to the left when comparing inside if()'s. Here's another good practice: Always add braces to your statements, even if you know for sure it is a one-liner.

UPDATE: The if() in line 25 suffers from the same lack of braces.
Last edited on
Thanks buddy. Just notice that. Always good to have another pair of eyes looking at it.
I fixed the braces but still no Message box printout in the call. Here is the code with the fix and the call. The call return false and make the message box unknown print. What is going on?

The call from Winmain
1
2
3
4
if (LoadBMPIntoDC(hDC, bmpfile) == FALSE) {
    MessageBox(0, "Unknown!", "Error!", MB_ICONSTOP | MB_OK);
}
 
It should be noted that this function is in another cpp file that is included in the project
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
bool LoadBMPIntoDC (HDC hDC, LPCTSTR bmpfile )
{
	// check if params are valid
	if ( ( NULL == hDC  ) || ( NULL == bmpfile ) )
    {
        MessageBox(0, "Window Parm Invalid!", "Error!", MB_ICONSTOP | MB_OK);
		return FALSE;
    }
	// load bitmap into a bitmap handle
	HANDLE hBmp = LoadImage ( NULL, bmpfile, IMAGE_BITMAP, 0, 0,
		LR_LOADFROMFILE );

	if ( NULL == hBmp )
    {
        MessageBox(0, "Window Handler Invalid!", "Error!", MB_ICONSTOP | MB_OK);
		return FALSE;        // failed to load image
    }
	// bitmaps can only be selected into memory dcs:
	HDC dcmem = CreateCompatibleDC ( NULL );

	// now select bitmap into the memory dc
	if ( NULL == SelectObject ( dcmem, hBmp ) )
	{	// failed to load bitmap into device context
		DeleteDC ( dcmem );
        MessageBox(0, "Window Load Failed!", "Error!", MB_ICONSTOP | MB_OK);
		return FALSE;
	}

	// now get the bmp size
	BITMAP bm;
	GetObject ( hBmp, sizeof(bm), &bm );
	// and blit it to the visible dc
	if ( BitBlt ( hDC, 0, 0, bm.bmWidth, bm.bmHeight, dcmem,
		0, 0, SRCCOPY ) == 0 )
	{	// failed the blit
		DeleteDC ( dcmem );
        MessageBox(0, "Window Blit Failed!", "Error!", MB_ICONSTOP | MB_OK);
		return FALSE;
	}

	DeleteDC ( dcmem );  // clear up the memory dc
	return TRUE;
}
@webJose.

I placed the code in the main file and now it return an error message. Windows Blit Failed. Why does that not work from an external cpp file included in the project?. The call are defined as external in a header used in the main and it does see the function in the external file but the message boxes won't print out on a failure. What am I overlooking?
Also... By changing the NULL in line 19 (30) to hDC create a load failure.
Last edited on
Sounds like the hDC you are passing from WinMain() is invalid. What is the source of this DC?
Defined global in WinMain()
HDC hDC;

And external in the header file.
extern HDC hDC;
@webJose.

I have another question.

HDC hDC = CreateCompatibleDC(NULL);
HBITMAP Wizard = (HBITMAP)LoadImageA(NULL, ("Wizard.bmp") ,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

SelectObject(hDC, Wizard);

HDC hdc_x = GetDC(HWND_DESKTOP);
BitBlt(hdc_x, iX, iY, 32, 32, hDC, 0, 0, SRCCOPY);
ReleaseDC(HWND_DESKTOP,hdc_x);

I look up the definition of the BitBlt() function and understand that iX and iY is a rectangle where to place the bitmap in. My question is this rectangle reference to the window you created or the whole screen?
Per

I found out that it reference to the whole screen. How do you get it to reference to your current window?
Last edited on
1. Your definition of the hDC variable is not what I meant. How do you fill this variable? A call to what function to obtain what DC during what window message (if in the window procedure)? That's what you need to show now.

2. An HDC for a given window has a bitmap object of the size of the window if the DC was obtained for the non-client area (via GetWindowDC(), for instance), or the size of the client area (in all other cases). The point (0, 0) will always be the upper left corner, meaning the coordinates are relative to the window.
Use your window handle as parameter to GetDC.
Stupid me. I just have to use the handler to the window.

HDC hdc_x = GetDC(hWnd);
BitBlt(hdc_x, iX, iY, 32, 32, hDC, 0, 0, SRCCOPY);
ReleaseDC(hWnd, hdc_x);

All set. Thanks for your help.
Topic archived. No new replies allowed.