Archived

This topic is now archived and is closed to further replies.

Message Handling and WM_QUIT/WM_DESTROY

This topic is 5575 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi Folks, I finally got around to writing my first little Windows program which uses the native Windows GDI to plot random pixels of random colors over a 1024X768 surface, but I have one problem, when I click the "X" on my window, the program window will close and nothing will show up on the task manager, but if I try and recompile later on, it tells me that it cannot access the .EXE file, which I have taken to mean that the program is still running. If anyone can help I would appreciate it a lot. Here is my source:
  
// Basic Program to Draw a Window


#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>
#include <time.h>
	
LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	if(msg == WM_PAINT)
	{
		PAINTSTRUCT ps;
		HDC hdc;
		hdc = BeginPaint(hwnd, &ps);
		EndPaint(hwnd, &ps);
		return(0);
	}
	return(DefWindowProc(hwnd, msg, wparam, lparam));
}

int WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine,
				   int nCmdShow)
{
	int x, y, red, green, blue;
	srand((unsigned)time(NULL));
	HDC hdc;
    MSG msg;
	WNDCLASSEX BasicWindow;

	BasicWindow.cbSize = sizeof(WNDCLASSEX);
	BasicWindow.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
	BasicWindow.lpfnWndProc = MsgHandler;
	BasicWindow.cbClsExtra = 0;
	BasicWindow.cbWndExtra = 0;
	BasicWindow.hInstance = hInstance;
	BasicWindow.hIcon = LoadIcon(NULL, IDI_WINLOGO);
	BasicWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
	BasicWindow.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	BasicWindow.lpszMenuName = NULL;
	BasicWindow.lpszClassName = "Basic Window";
	BasicWindow.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
	
	RegisterClassEx(&BasicWindow);

	HWND hwnd;
	if(!(hwnd = CreateWindowEx(NULL,
							   "Basic Window",
							   "Basic Window",
							   WS_VISIBLE | WS_CAPTION | WS_TILEDWINDOW,
							   0,
							   0,
							   1024,
							   768,
							   NULL,
							   NULL,
							   hInstance,
							   NULL)))
	{
		return(0);
	}

	hdc = GetDC(hwnd);
	while(TRUE)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			if(msg.message == WM_QUIT)
			{
				break;
			}
			if(msg.message == WM_DESTROY)
			{
				PostQuitMessage(0);
				return(0);
			}
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		x = rand() % 1024 + 1;
		y = rand() % 768 + 1;
		red = rand() % 255 + 1;
		green = rand() % 255 + 1;
		blue = rand() % 255 + 1;
		SetPixel(hdc, x, y, RGB(red, green, blue));
	}
	return(msg.wParam);
}
  

Share this post


Link to post
Share on other sites
When you click the X to close your program, Windows sends a WM_DESTROY message to destroy the program, but doesn't actually close the window.

You need to include the WM_DESTROY message in your WinProc handler, and if that message is received, then do a PostQuitMessage(0); like this.


    
LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)

{
switch(msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
return(0);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return(0);
break;
}
default:
{}
}
return(DefWindowProc(hwnd, msg, wparam, lparam));
}


Now, I've only written one windows program myself, so If I'm wrong, sorry =)

~~~~~~~~~~~
Chris Vogel
~~~~~~~~~~~


[edited by - Radagar on September 10, 2002 12:01:06 AM]

Share this post


Link to post
Share on other sites
No, that''s correct. You definitely need to test for WM_DESTROY, because clicking the ''X'' to close the window only removes it from the screen. When you send a PostQuitMessage(0), that tells Windows to kill the program itself.

John.

Share this post


Link to post
Share on other sites
Hey Again,

I tried compiling again, and still when I click the ''X'', the program closes, but still runs in the background. I''m really confused now. My code looks fine and shouldn''t have ANY problems?

Share this post


Link to post
Share on other sites
bower12345:

Did you put the WM_DESTROY block in your MsgHandler function? I don''t think that Windows will know to let the program end if you''ve got it in WinMain().

John.

Share this post


Link to post
Share on other sites
Yes, I moved my code from WinMain to the MsgHandler function. I also thought that maybe since I wasn''t releasing the device context at the end of my program that that might have been the problem, but I still see no change in the program. Here is the updated code:


  
// Basic Program to Draw a Window


#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>
#include <time.h>

LRESULT CALLBACK MsgHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
return(0);
}
case WM_QUIT:
{
return(0);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return(0);
break;
}
default:
{
return(DefWindowProc(hwnd, msg, wparam, lparam));
}
}
}

int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
int x, y, red, green, blue;
srand((unsigned)time(NULL));
HDC hdc;
MSG msg;
WNDCLASSEX BasicWindow;

BasicWindow.cbSize = sizeof(WNDCLASSEX);
BasicWindow.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
BasicWindow.lpfnWndProc = MsgHandler;
BasicWindow.cbClsExtra = 0;
BasicWindow.cbWndExtra = 0;
BasicWindow.hInstance = hInstance;
BasicWindow.hIcon = LoadIcon(NULL, IDI_WINLOGO);
BasicWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
BasicWindow.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
BasicWindow.lpszMenuName = NULL;
BasicWindow.lpszClassName = "Basic Window";
BasicWindow.hIconSm = LoadIcon(NULL, IDI_WINLOGO);

RegisterClassEx(&BasicWindow);

HWND hwnd;
if(!(hwnd = CreateWindowEx(NULL,
"Basic Window",
"Basic Window",
WS_VISIBLE | WS_CAPTION | WS_TILEDWINDOW,
0,
0,
1024,
768,
NULL,
NULL,
hInstance,
NULL)))
{
return(0);
}

hdc = GetDC(hwnd);
while(TRUE)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
x = rand() % 1024 + 1;
y = rand() % 768 + 1;
red = rand() % 255 + 1;
green = rand() % 255 + 1;
blue = rand() % 255 + 1;
SetPixel(hdc, x, y, RGB(red, green, blue));
}
ReleaseDC(hwnd, hdc);
return(msg.wParam);
}


Any help would be appreciate greatly. Thanks!

Share this post


Link to post
Share on other sites
Hi,
actually the PostQuitMessage() only sends WM_QUIT to your window
it does nothing to your program. The point is that your app is
running an infinite loop:

while (true) {...}

you should use something like

while(bRunApp) {...}

and in your messagehandler:

if (message=wm_quit) bRunApp=false;

I think that''ll work.
good luck.

--::[Madhed]::-

Share this post


Link to post
Share on other sites