Click here to Skip to main content
15,902,447 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hello everyone!

I would like to start by saying thanks to everyone who takes some time to view this thread and try to help.

I work on a project where .bmp file must be a background image of a main window.

I work in MS Visual Studio Express Edition 2008, in C++, using WIN32 API, on Windows XP.

I have found solution for putting .bmp file as background image here, on CodeProject.

After modifying my code everything worked fine after my application started.The picture was where it supposed to be.

The problem comes when I maximize the main window.
The picture gets duplicated, and after few more minimizes/maximizes, my background becomes entirely white.

I will submit my code in hope that it will help in finding a solution.

Bitmaps dimensions are 256 x 256, and it was created from a .png file via free converter I have found online (the .png file was quite large).

I have even captured some snapshots of the problem in Paint, but I don't know how to make them available to those who view this question ( I will gladly e-mail them).

If there is anything else I can do, just say it, and I will do it.

IMPORTANT UPDATE #1 ( updated on May,5th 2013):

After adding the following code, picture doesn't duplicate anymore, but after few minimizes/maximizes my background becomes white :

C#
case WM_SIZE:
        InvalidateRect(hwnd,NULL,FALSE);
        break;


IMPORTANT UPDATE #2 ( updated on May,5th 2013):

I have changed my code in the part where the window class is registered from
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

to
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);


After few minimizes/maximizes the picture completely dissapears and background becomes black ( just as I have changed it, in window class registration).
I suspect that the problem is some sort of a leak,but I just can't figure it out.

IMPORTANT UPDATE #3 ( updated on May, 5th 2013):

I have solved the problem, and have submitted my solution.
Please comment on it, I will welcome it.
I will also accept other solutions, as well.
Thank you.

Now, the code:

#include "resource.h"
#include <windows.h>

// THIS DIALOG IS IRRELEVANT FOR MY QUESTION

BOOL CALLBACK FilterDialog( HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam )
{
	switch( Message)
	{
	case WM_INITDIALOG:
		return TRUE;
		break;

	case WM_COMMAND:
		switch( LOWORD(wParam) )
		{
		case IDOK:
			EndDialog(hwnd, IDOK);
			break;
		case IDCANCEL:
			EndDialog(hwnd, IDCANCEL);
			break;
		}

		break;

	default:
		return FALSE;
	}

	return TRUE;
}

/*************************** main window procedure *******************************/

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	HBITMAP hBitmap = LoadBitmap( GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1) );
	
	// Dimensions of a bitmap that will be painted on client area

	BITMAP bp;
	GetObject( hBitmap, sizeof(bp), &bp);

	switch(msg)
	{
	case WM_PAINT:

		HDC hdcInst,hdcBitmap;
		PAINTSTRUCT ps;

		hdcInst = BeginPaint(hwnd,&ps);
		
		// Create a memory device compatible with the above DC variable

		hdcBitmap = CreateCompatibleDC(hdcInst);

		// Select the new bitmap

		SelectObject(hdcBitmap, hBitmap);

		// Get client coordinates for the StretchBlt() function

		RECT r;
		GetClientRect(hwnd,&r);

		// troublesome part, in my oppinion
		
		StretchBlt( hdcInst, 0, 0, r.right - r.left, r.bottom - r.top, hdcBitmap, 0, 0, bp.bmWidth,bp.bmHeight, MERGECOPY); 

		// Cleanup

		DeleteDC(hdcBitmap);
		EndPaint(hwnd, &ps);

		break;

        // WM_COMMAND handles creation of a dialog, and is irrelevant for my question

	case WM_COMMAND:
		switch( LOWORD(wParam) )
		{
		case IDM_PRETRAGA1:
			DialogBox( GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1),hwnd,FilterDialog);
			break;
		default:
			break;
		}

		break;

	case WM_CLOSE:
                // delete bitmap handle
		DeleteObject(hBitmap);

		DestroyWindow(hwnd);
		break;

	case WM_DESTROY:
                // delete bitmap handle
		DeleteObject(hBitmap);

		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}

/******************************* WinMain ************************************/

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX wc;
	HWND hwnd;
	MSG Msg;

	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = 0;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1)); // icon from resource
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground =(HBRUSH)(COLOR_WINDOW+1); 
	wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); // menu from resource
	wc.lpszClassName = "Main_Window";
	wc.hIconSm = (HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_ICON1),IMAGE_ICON,16,16,0); // icon from resource

	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	/************************ main window *************************/

	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "Main_Window", "Rudarsko Geoloski Fakultet",
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 500, NULL, NULL, hInstance, NULL);

	if(hwnd == NULL)
	{
		MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}

	return Msg.wParam;
}
Posted
Updated 4-May-13 15:17pm
v4
Comments
CPallini 4-May-13 18:00pm    
Why are you using MERGECOPY?
MyOldAccount 4-May-13 18:06pm    
I use it to stretch the picture all over client area.
CPallini 4-May-13 18:15pm    
OK. Why didn't you use SRCCOPY instead?
MyOldAccount 4-May-13 18:33pm    
I am fairly inexperienced.
I tried SRCCOPY, and got the same result.
MyOldAccount 4-May-13 19:11pm    
After handling WM_SIZE with InvalidateRect(hwnd,NULL,FALSE); things worked for 2 or 3 minimizes/maximizes.
Then the background turned to white.
Does this information help you in anyway?

1 solution

I have cracked it!

Just a few modifications, and it all works.

IMPORTANT INFORMATION:
This solution was improved thanks to remarks from member CPallini.

Here are the final adjustments:

C++
// hBitmap variable is declared as static and is outside of switch(...) statement

static HBITMAP hBitmap = LoadBitmap( GetModuleHandle(NULL), 
                          MAKEINTRESOURCE(IDB_BITMAP1) );

// solved issue with duplicated picture with InvalidateRect(...);
case WM_SIZE:
     InvalidateRect(hwnd,NULL,FALSE);
     break;

// added curly braces, HBITMAP variable is declared static,cleanup is reorganized

case WM_PAINT:
{
     HDC hdcInst,hdcBitmap;
     PAINTSTRUCT ps;
     BITMAP bp;
     RECT r;
     
     hdcInst = BeginPaint(hwnd,&ps);
		
     // Create a memory device compatible with the above DC variable

     hdcBitmap = CreateCompatibleDC( hdcInst);
 
     // Select the new bitmap

     SelectObject(hdcBitmap, hBitmap);
			
     GetObject( hBitmap, sizeof(bp), &bp);
		
     // Get client coordinates for the StretchBlt() function

     GetClientRect(hwnd,&r);
 
     // stretch bitmap across client area
		
     StretchBlt( hdcInst, 0, 0,r.right - r.left, r.bottom - r.top, hdcBitmap, 0, 
         0, bp.bmWidth,bp.bmHeight, SRCCOPY); 
 
     // Cleanup

     DeleteDC(hdcBitmap);
     EndPaint(hwnd, &ps);
}
     break;

// this part below removes flickering !

case WM_ERASEBKGND:
     return (LRESULT)1;

// cleanup for bitmap

case WM_CLOSE:

     DeleteObject(hBitmap);
     DestroyWindow(hwnd);
     break;

case WM_DESTROY:

     DeleteObject(hBitmap);
     PostQuitMessage(0);
     break;
 
Share this answer
 
v5
Comments
CPallini 5-May-13 16:28pm    
OK, no cleanup needed at program termination, but you're loading the bitmap every time WM_PAINT is issued. That's not needed (though I don't know how it impacts overall performance).
MyOldAccount 5-May-13 16:41pm    
I agree with you about WM_PAINT part, but I just do not know how to rearrange code properly.

If I put the statement HBITMAP hBitmap = LoadBitmap( GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1) ); outside of switch(...) statement the problems with background becoming black ( as described above) return. I guess I need to rearrange other statements linked with it as well but I do not know how to do it.

If you could provide some advice, I would highly appreciate it, since I am inexperienced in win32.

****************************************
MODIFICATION TO THIS REPLY:

I have placed the statement that loads bitmap outside switch(..) and made it static, deleted the part that destroys the bitmap in WM_PAINT and now I have just one question:
Should I delete bitmap in WM_DESTROY and WM_CLOSE or should I just leave it since it will be destroyed anyway?
Thanks anyway Mr. Pallini, you have been very helpfull.
CPallini 5-May-13 16:55pm    
Sorry I didn't notice that before. You have to either make hBitmap a global variable or make it a static local variable of the WndProc. This way you may use your original code. e.g.
HBITMAP hBtimap; // global variable put it at the top of your source file
//..
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
hBitmap = LoadBitmap( GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1) );
//..

**************************************
MODIFICATION ACCORDING TO YOUR MODIFICATION :-)
You have to perform cleanup (at least because it is clean programming: someone or 'an older you' might use your code in a different context thus making GDI resources leaking).
MyOldAccount 5-May-13 17:04pm    
Thank you so much.
I would like to do cleanup in WM_DESTROY and WM_CLOSE, and delete cleanup statement in my WM_PAINT code above, since that bitmap is needed until the program ends.
Will that make any leaks?
If so, can you recomend me what to do?
Thanks again. :)

CPallini 5-May-13 17:21pm    
No leaks, in my opinion, your code will be OK.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900