Jump to content
  • Advertisement
Sign in to follow this  
webwraith

PeekMessage() and GetMessage() not quitting the message loop

This topic is 2954 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

I'm in the process of writing a small wrapper for DirectX that just covers initialization. It's remarkably simple in that the majority of the settings are hard-coded, as it's just for use as a learning experience, however, I've run into some problems.

It's my message loop. I have two versions (one with GetMessage(), the first one I wrote in this piece, primarily for testing, and the other with PeekMessage(), which is the one I intend to use) These are as follows;

GetMessage;

MSG msg;

BOOL bret = -1;

while( ( bret = GetMessage( &msg, dx_win.handle(), 0, 0 ) ) != 0 ){
if( bret < 0 ){
wdx::MessageError( NULL, TEXT( "WinMain()" ) );
break;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}

if( bret < 0 )
wdx::MessageError( NULL, TEXT( "WinMain()" ) );

dx_win.Destroy();

return bret;



PeekMessage;

while( true ){
if( dx_win.PeekMsg() == false )
break;
// do other game stuffs here
}

/* dx_win.PeekMsg() */
bool DirectX9Window::PeekMsg(){
if( window == NULL )
return false;
MSG msg;

if( PeekMessage( &msg, window, 0, 0, PM_REMOVE ) != 0 ){

if( msg.message == WM_QUIT )
return false;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return true;
}



The problem I'm having with the second one (and the first when I change the comparison of GetMessage's return from '>0' to '!=0' and remove the 'if' block inside it) is that the window closes, but the application continues. I'm pretty sure it's not a problem with the WndProc, either;

// DirectX9Window is the name of the class, and is the type of dx_win in
// the previous code snippets
LRESULT CALLBACK DirectX9Window::MessageProc( UINT msg, WPARAM wp, LPARAM lp ){
if( msg == WM_DESTROY ){ // this is probably done in DefWindowProc anyway, but nevermind
PostQuitMessage( 0 );
}
else
return DefWindowProc( window, msg, wp, lp );
}



The MessageError() function( creates a Message Box, formatting the result of GetLastError() ) is never called in the GetMessage snippet, but if I take out the surrounding 'if' block, the loop never quits. Thanks to breakpoints, I've found that there's a system error stating
{No Paging File Specified} No paging file was specified in the system configuration.

which doesn't make much sense to me, as I wasn't aware I would need a specified paging file to close a window.

Anyway, the long and short of my problem is that neither of the two message pumps above quit once my window is closed, with the exception of the GetMessage modifications I've already mentioned. As you can see, I'm programming in C++, in VC++ 2010 Express, and I'm getting a little frustrated with it. Time to go to bed and see if it's clearer in the morning..

Share this post


Link to post
Share on other sites
Advertisement
Pass NULL instead of the window-handle to PeekMessage/GetMessage. WM_QUIT does not belong to a window, and is also sent after the window is destroyed, so the window handle will be invalid then. You usually want to handle all messages in the thread message queue, not just those associated with a specific window. More information: GetMessage.

Share this post


Link to post
Share on other sites
Thank you very much for that, I can't believe (but somewhat guessed) it was that simple. Just my luck :P

It never occurred to me that messages could be for the application, rather than just the windows opened by it.

Again thanks for the correction.

[Edited by - webwraith on August 22, 2010 12:15:21 PM]

Share this post


Link to post
Share on other sites
There's still a small problem with your message loop:


while( true ){
if( dx_win.PeekMsg() == false )
break;
// do other game stuffs here
}

/* dx_win.PeekMsg() */
bool DirectX9Window::PeekMsg(){
if( window == NULL )
return false;
MSG msg;

if( PeekMessage( &msg, window, 0, 0, PM_REMOVE ) != 0 ){

if( msg.message == WM_QUIT )
return false;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return true;
}






Let's imagine there are multiple messages waiting for you to process. But what you're doing is this:
1. Get and process one message.
2. Make game stuff (update, render etc.)
3. Get back to 1 as long as the message is not WM_QUIT.
You'll process all the waiting messages very slowly because you will be rendering after every single one.

You should do rendering only if PeekMessage returned false at the current frame.
This is the idea:

while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
// do game stuff....
}
}





In your case you could maybe for example not return just bool (true/false) from
bool DirectX9Window::PeekMsg()
but three different values which would mean
- there was no message
- there was a message other than WM_QUIT
- there was WM_QUIT message

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!