Here's a question I get asked quite a bit. Windows uses a totally different model for detecting user input than what DOS programmers are accustomed to. Instead of having the application call the operating system to ask if the user has, for example, pressed a key, Windows calls the application when a user event has occurred. The application then does whatever it needs to and returns control back to the system.
Although this might seem a little upside-down at first, this approach is extremely flexible and works great. However, there are times when it is useful to be able to query the system for user events. For example, if your application is busy with a lengthy operation, it might be nice to detect if the user presses the Escape key as a way to cancel that operation. Fortunately, Windows allows you to do this.
When the user causes a system event by pressing a key or moving the mouse, the operating system stores these events in the appropriate application's message queue. These events are stored there as messages until the application returns control to Windows at which time Windows will send the next message from the queue to the application.
So, to find out if the user has pressed a particular key during a lengthy operation, your application needs to determine if a message for that key is currently in the application's message queue. You can determine this by calling the PeekMessage function as shown in this example.
MSG msg;
// Check for escape key
if (::PeekMessage(&msg, m_hWnd, WM_KEYFIRST,
WM_KEYLAST, PM_REMOVE)) {
if (msg.message == WM_KEYDOWN && msg.wParam
== VK_ESCAPE)
// Break out of your loop or
otherwise stop working break;
}
The first argument to PeekMessage is a MSG structure that receives message information. The second argument is the handle of the window we are interested in. If you are using an MFC window-based class, you can just pass the m_hWnd member here. The next two arguments let us just look for certain types of messages. PeekMessage will return the first message in the queue that falls between these two values. Here, we were just interested in keystrokes so these arguments are set to WM_KEYFIRST and WM_KEYLAST. The last argument can be PM_NOREMOVE or PM_REMOVE and indicates if the message we get information about should be removed from the message queue. If the user pressed Escape, we don't want they keystroke going anywhere else, so we request that PeekMessage removes the message from the queue.
If PeekMessage finds a message within the request range, it returns a non-zero value. If this is the case, the code above checks to see if we found a WM_KEYDOWN message with wParam equal to VK_ESCAPE and, if so, breaks out of whatever the code is doing.