How do you make a program start idling after finish rendering DirectX sprites?

Started by
17 comments, last by szecs 12 years, 11 months ago
Here's the Windows Procedure:


[source lang="cpp"]

MSG msg_struct;
ZeroMemory(&msg_struct, sizeof(MSG));
while (msg_struct.message != WM_QUIT)
{
??if (GetMessage(&msg_struct, NULL, NULL, NULL)) //PeekMessage(&msg_struct, NULL, NULL, NULL, PM_REMOVE)
??{
????TranslateMessage(&msg_struct);
????DispatchMessage(&msg_struct);
??}
??else
??{
????UpdateWindow(Core::global_hWnd);
????if (!Core::RunDirect3DStuffs(Core::global_hWnd))
??????return 1;
??}
}

[/source]

The commented part means that anytime I switch the GetMessage() with PeekMessage() and vice versa, I always see my program hangs upon initial startup, then the mouse cursor keeps playing the "Busy..." idle animation. (The blue circle in Windows 7/Vista, or the hourglass animation in Windows XP.)

Until my mouse leaves the window, it will not change back to "Idle" arrow. (The normal pointing-to-the-upper-left arrow.) I'm curious to know how do developers get rid of this minor problem? What is the solution?

Thanks in advance.
Advertisement
Maybe try the following variant (based on the loop provided at http://www.mvps.org/directx/articles/writing_the_game_loop.htm):
MSG msg_struct;
// prime the message structure
PeekMessage(&msg_struct, NULL, 0, 0, PM_NOREMOVE);
while (msg_struct.message != WM_QUIT)
{
if (PeekMessage(&msg_struct, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg_struct);
DispatchMessage(&msg_struct);
}
else // you may not want the below to be an else condition - this depends on your own program so try both ways and see which works the way you want
{
// http://msdn.microsoft.com/en-us/library/dd145167%28v=vs.85%29.aspx
// don't mix D3D stuff with WM_PAINT - it's evil
// UpdateWindow(Core::global_hWnd);
if (!Core::RunDirect3DStuffs(Core::global_hWnd))
return 1;
}
}

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Then it's the same thing. It's just like adding a do...while to the current while loop.

Would throttling increase the chance that my program can idle, which is what I really wanted? When it's idling, my mouse would then return to normal cursor animation, instead of hanging there.

It would appear the main change to make is to use while( PeekMessage(...) ) instead of if( PeekMessage(...) ).

Something like:

while( running )
{
while( PeekMessage(...) )
{
if( message==WM_QUIT ) //.. exit the procedure. e.g., return( some_code )
Translate...
Dispatch...
}
if( DoD3DStuff(...) ) DoStuff(...);
}

It's more common in a run loop ( that's not a Window Procedure, by the way.. that's different ) to process all the windows messages that are in the queue each time through the loop before you update the window.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


It would appear the main change to make is to use while( PeekMessage(...) ) instead of if( PeekMessage(...) ).
It's more common in a run loop ( that's not a Window Procedure, by the way.. that's different ) to process all the windows messages that are in the queue each time through the loop before you update the window.


Then under what conditions would the message queue becomes empty and my program then automatiically becomes idle?

Because I see that, even though my message queue is empty, the program is too busy checking if the message queue is still empty (accordingly to the while(PeekMessage()) second loop.) or not.

In short, how do people make the program idle when the game loads and boots up the main menu? Right when it finishes the main menu rendering, the mouse would be normal (i.e. Not running the "Busy..." animation).
GetMessage() is a blocking function - it won't return until there is a message posted and only returns false on WM_QUIT, so the loop you initially posted will only enter the else block once, just before the program exits.

The loop Buckeye posted is the conventional way to do a Win32 game loop.

[quote name='Buckeye' timestamp='1304726195' post='4807538']
It would appear the main change to make is to use while( PeekMessage(...) ) instead of if( PeekMessage(...) ).
It's more common in a run loop ( that's not a Window Procedure, by the way.. that's different ) to process all the windows messages that are in the queue each time through the loop before you update the window.


Then under what conditions would the message queue becomes empty and my program then automatiically becomes idle?

Because I see that, even though my message queue is empty, the program is too busy checking if the message queue is still empty (accordingly to the while(PeekMessage()) second loop.) or not.

In short, how do people make the program idle when the game loads and boots up the main menu? Right when it finishes the main menu rendering, the mouse would be normal (i.e. Not running the "Busy..." animation).
[/quote]
The message loop becomes empty when all the messages have been processed. Once you're into the game loop, the queue will be empty most of the time. PeekMessage returns FALSE when there's no message and you'll move on to if( DoStuff ).

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Note, that the loop with the if also reads all the messages. Because the Update function is in the else block.

I just wanted to note that. It seems that everyone is so carried away with the while thing, that no one notices that the if-else block does the same in this case (there are cases when not (I cannot think of any at the moment), and I use while too)

Note, that the loop with the if also reads all the messages. Because the Update function is in the else block.

I just wanted to note that. It seems that everyone is so carried away with the while thing, that no one notices that the if-else block does the same in this case (there are cases when not (I cannot think of any at the moment), and I use while too)

You make a good point, szecs, only if PeekMessage is used, not GetMessage. GetMessage always returns non-zero unless the message is WM_QUIT, making the if( GetMessage() )... else alternate-routine construct ( OP ) valueless.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Is that code part of your window procedure or your message pump (maybe message pump isn't the correct terminology, but it's what I've always called it)? Because, as Buckeye said, it isn't a window procedure and if you use it as one things will not work as expected. Here is a small example of how a (minimal) window procedure and a message pump could look (untested):


//Use this window procedure when creating the window
LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}

void MessagePump()
{
MSG msg;
while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

void MainLoop()
{
while (running)
{
MessagePump();
//Do everything else one would like to do in a frame
}
}


In the above code you probably would want to detect relevant messages, such as the window being closed, etc.

This topic is closed to new replies.

Advertisement