Every Windows app has at its core a loop that looks something like this:
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0 )
{
if (bRet == -1 )
{
// handle the error and possibly exit
}
else
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
It's the application's job--not the operating system's--to ensure that messages are dispatched.
As you probably know, early Windows games used an alternate method where, instead of calling the blocking GetMessage
function, they'd call PeekMessage
, and then call the game's main processing loop if there was no message to handle. Various forms of delays were used to try to get an adequate frame rate without taking 100% CPU. There just wasn't a good enough timer to give a smooth frame rate.
Today, it might not be necessary to explicitly write a loop that calls DoEvents
. It might be possible now to get a smooth frame rate by using the built-in timer pool timers (exposed in .NET by System.Threading.Timer
, and wrapped by System.Timers.Timer
).
As I recall, there were also issues with getting mouse and keyboard events in a timely manner. We used direct keyboard and mouse access rather than depending on the message loop, because the message loop was often too slow and sometimes would cause us to lose information.
I've not written games in a number of years, and I don't know what .NET is like as a games platform. It's possible that input is still a problem--that the message queue simply isn't fast enough to give the lightning-quick response that game developers want. So they bypass the message queue for critical tasks.