Win32 Main Message Loop
Hello all ! Here is something for Win32 experts, from someone who is not so expert.
Looking at various Win32 OpenGL code on the Web, I found many different ways to deal with Windows Message Loop.
Nehe uses this form:
while(!done)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// do OpenGL stuff
}
}
I''ve also seen forms in which ''else'' part is omitted, like:
while(!done)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// do OpenGL stuff
}
Then, there is this quite different form where they use Message Loop as:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
and all the OpenGL stuff is rendered in main Window Procedure under WM_PAINT message:
case WM_PAINT:
if (hGLRC)
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
GLDraw(&hDC);
EndPaint(hWnd, &ps);
return 0;
}
So, the question is, does anyone know what is the best way to deal with Win32 Message Loop, performance-wise ?
Are there any speed penalties of doing it in a particular way ?
Which one of the above methods is the best one to use ?
Thank you all for reading this.
Pho
The first one is the best of the three because it'll handle incomming message before letting OpenGL render. If the program is run without hardware acceleration and there's a frame time of several seconds this can provide a way out for the user.
The second will render the OpenGL scene every time through the loop possably delaying critical messages that will lock up the system. If you had a fram rate of 20 fps and there were 30 messages pending it would talk 1.5 seconds to process them all, this can cause serious performance penalties.
The third version is technically the correct way to do a win32 app. the window is drawn every time it recieves a WM_PAINT message and at no other time. For something like a 3d editor that would work fine as the image only need updateing when something changes. However a game or demo would have to constantly force paint messages and that would take up cpu time.
The down side with PeekMessage is that it returns wether thers a message or not, the constant looping causes the cpu time to peg at 100% and stay there. GetMessage waits for a messages allowing other programs to do things however there has to be a message sent to the window before it will return.
I use a hy-bred message loop that's dependant on the active status of the program. I've sent it to nehe on several occasions but he's never taken any interest in it. If your currious here's a scaled down version of what I use...
while(!done){
if(Active){
if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){
if(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
done = true;
}
else
Idle();
}
else{
if(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
done = true;
}
}
Edited by - avianRR on March 23, 2001 1:57:21 AM
The second will render the OpenGL scene every time through the loop possably delaying critical messages that will lock up the system. If you had a fram rate of 20 fps and there were 30 messages pending it would talk 1.5 seconds to process them all, this can cause serious performance penalties.
The third version is technically the correct way to do a win32 app. the window is drawn every time it recieves a WM_PAINT message and at no other time. For something like a 3d editor that would work fine as the image only need updateing when something changes. However a game or demo would have to constantly force paint messages and that would take up cpu time.
The down side with PeekMessage is that it returns wether thers a message or not, the constant looping causes the cpu time to peg at 100% and stay there. GetMessage waits for a messages allowing other programs to do things however there has to be a message sent to the window before it will return.
I use a hy-bred message loop that's dependant on the active status of the program. I've sent it to nehe on several occasions but he's never taken any interest in it. If your currious here's a scaled down version of what I use...
while(!done){
if(Active){
if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){
if(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
done = true;
}
else
Idle();
}
else{
if(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
done = true;
}
}
Edited by - avianRR on March 23, 2001 1:57:21 AM
------------------------------Piggies, I need more piggies![pig][pig][pig][pig][pig][pig]------------------------------Do not invoke the wrath of the Irken elite. [flaming]
March 23, 2001 02:07 AM
avianRR:
is there a reason you peek without removing and then get the message?
wouldn''t it make more sense to just peek using PM_REMOVE?
is there a reason you peek without removing and then get the message?
wouldn''t it make more sense to just peek using PM_REMOVE?
March 23, 2001 02:30 AM
I use the following..
> do
> {
> if( bIsActive )
> bMsgFound = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
> else
> bMsgFound = GetMessage( &msg, NULL, 0U, 0U );
>
> if( bMsgFound )
> {
> TranslateMessage( &msg );
> DispatchMessage( &msg );
> }
> else
> {
> // No messages are waiting so make use of idle time.
> UpdateFrame();
> }
> } while ( !done );
> do
> {
> if( bIsActive )
> bMsgFound = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
> else
> bMsgFound = GetMessage( &msg, NULL, 0U, 0U );
>
> if( bMsgFound )
> {
> TranslateMessage( &msg );
> DispatchMessage( &msg );
> }
> else
> {
> // No messages are waiting so make use of idle time.
> UpdateFrame();
> }
> } while ( !done );
I use this loop in DemoGL.
--
Get productive, Get DemoGL: http://www.demogl.com
voidKernelLoop(){ bool bQuitMainLoop; MSG mMsg; // check if there are messages in the queue. If so: process them. for(bQuitMainLoop=false;!bQuitMainLoop;) { while(PeekMessage(&mMsg, NULL, 0, 0, PM_NOREMOVE)) { if(GetMessage(&mMsg, NULL, 0, 0)) { TranslateMessage(&mMsg); DispatchMessage(&mMsg); } else { bQuitMainLoop=true; break; } } // we''re displaying content. That needs to be as smooth as possible so no messagewaitin'' if(m_gpDemoDat->GetSystemState()==SSTATE_ARUN_KERNELLOOP) { ExecuteTimeLine((long)(m_gpDemoDat->GetfElapsedTimeInSecs() * 1000)); m_gpDemoDat->CalcElapsedTimeInSeconds(); RenderFrame(); } else { WaitMessage(); } } ////////////////// // a WM_QUIT message has been received. ////////////////// // set new system state. m_gpDemoDat->SetSystemState(SSTATE_ARUN_POSTKERNELLOOP); // Control should be given back to the caller''s main routine, but we first have to // do some cleanup of handles and windows. CleanUpKernelInternals();}
--
Get productive, Get DemoGL: http://www.demogl.com
--
Get productive, Get DemoGL: http://www.demogl.com
Get productive, Get DemoGL: http://www.demogl.com
There was an article posted on gamedev.net a while back by Javier Otaegui which gave another method of dealing with the message loop, which I''ve used and had some success with..
I use the standard Peek/Translate/Dispatch loop in WinMain, sleeping after each iteration (20ms or so, doesnt matter too much).. For the actual rendering/game code, a new thread is created (before the start of the messaging loop), from which you can execute a separate game loop, or use a more linear programming style if that suits you more..
Have a read of the article in any case, it goes into a lot more detail..
----------------------------------------
Damian.
Email: damian@returnity.com
Web: www.gamedevcentral.com
I use the standard Peek/Translate/Dispatch loop in WinMain, sleeping after each iteration (20ms or so, doesnt matter too much).. For the actual rendering/game code, a new thread is created (before the start of the messaging loop), from which you can execute a separate game loop, or use a more linear programming style if that suits you more..
Have a read of the article in any case, it goes into a lot more detail..
----------------------------------------
Damian.
Email: damian@returnity.com
Web: www.gamedevcentral.com
----------------------------------------Damian.Email: damian@returnity.comWeb: www.gamedevcentral.com
The reason I peek at the message without removine it is that getmessage returns wether or not the message is WM_QUIT.
if it is we exit. As I said it''s a scaled down version of my message loop theres actually several other thing''s in the actual loop that I didn''t put in so as not to confuse anyone.
if it is we exit. As I said it''s a scaled down version of my message loop theres actually several other thing''s in the actual loop that I didn''t put in so as not to confuse anyone.
------------------------------Piggies, I need more piggies![pig][pig][pig][pig][pig][pig]------------------------------Do not invoke the wrath of the Irken elite. [flaming]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement