Skip to main content
gamedev.net
🔒 Locked

PeekMessage()

Started by Shadowflare 3 replies 950+ views
Original Post
Shadowflare
Shadowflare
Greetings, I have a problem that's been hounding me and I can't figure out it's source. Basically, in a simple windows application, I'm using PeekMessage() in my main program loop to handle incoming messages. The problem is that it doesn't seem to be picking up the WM_QUIT message. Here is my WndProc and my loop:

// The WndProc function
LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	switch(nMsg)
	{
	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}

	return DefWindowProc(hWnd, nMsg, wParam, lParam);
}


// My program loop
BOOL bDone = FALSE;
MSG  msg;

// ...unimportant code...

while(bDone == FALSE)
{
        PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE);

	if(msg.message == WM_QUIT)
		bDone = TRUE;
        else {
             // ...game handling code...
        }

	TranslateMessage(&msgMessage);
	DispatchMessage(&msgMessage);

}

If I close my program, it destroys the window but continues to run. I'm obviously doing something wrong. Any help would be appreciated!
Aardvajk
Aardvajk
I think you need to return 0; after you handle WM_CLOSE and WM_DESTROY, rather than let the case drop through to DefWindowProc(). Otherwise your loop and so on look very similar to some code I have to hand so I don't see any other potential causes.

I'm not sure about that though. Worth a try.

LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam){	switch(nMsg)	{	case WM_CLOSE:		DestroyWindow(hWnd);		return 0;	case WM_DESTROY:		PostQuitMessage(0);		return 0;	}	return DefWindowProc(hWnd, nMsg, wParam, lParam);}


I'm also not sure if you need to call DestroyWindow() as part of WM_CLOSE. I've never handled WM_CLOSE directly and always passed that along to DefWindowProc() personally.

HTH

[EDIT] The SDK help has just confirmed that if you handle WM_CLOSE, you should return 0; after calling DestroyWindow() rather than letting DefWindowProc() have another bash at it. It also confirms that if you handle WM_DESTROY, you should return 0; I'd guess those are your problem.
Shadowflare
Shadowflare
I modified my code thus to try out your solution:

LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam){	switch(nMsg)	{	case WM_DESTROY:		PostQuitMessage(0);		break;	default:		return DefWindowProc(hWnd, nMsg, wParam, lParam);	}		return 0;}


You were right about WM_CLOSE, my program doesn't seem to even encounter it, so why clutter? :P

Returning 0 instead of DefWindowProc() didn't work though.

I actually discovered that the WM_QUIT message must be getting sent, because if I change my loop to use GetMessage() instead:

while(GetMessage(&msg, hWnd, 0, 0) > 0) // This is a no-no, I know, just for testing purposes =P{     // ...code...     TranslateMessage(&msg);     DispatchMessage(&msg);}  


the program exits the way it's supposed to, even using my former WndProc(). I'm baffled by this O,o

The problem here is that my program is a game, and so GetMessage() will not work since I've got rendering going on.
Evil Steve
Evil Steve
You should pass NULL for the hWnd parameter. WM_QUIT is a thread message, not a window message, and passing a non-NULL window handle will only give you window messages.

So always pass NULL for the hWnd parameter to PeekMessage() and GetMessage() unless you have a reason to do otherwise.
Shadowflare
Shadowflare
Thanks Evil, that was the problem. Thanks also to EasilyConfused for trying to help, I appreciate it!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.