Queued and Nonqueued Messages

I've talked about Windows sending messages to a window, which means that Windows calls the window procedure. But a Windows program also has a message loop that retrieves messages from a message queue by calling GetMessage and dispatches them to the window procedure by calling DispatchMessage.

So, does a Windows program poll for messages (exactly as a normal program polls for keyboard data) and then route these messages to some location? Or does it receive messages directly from outside the program? Well, both.

Messages can be either ”queued“ or ”nonqueued.“ The queued messages are those that are placed in a program's message queue by Windows and retrieved and dispatched in the message loop. The nonqueued messages are sent to the window directly when Windows calls the window procedure. The result is that the window procedure gets all the messages—both queued and nonqueued—for the window. Structurally, Windows programs are very clean, because they have one central point of message processing. It is said that queued messages are posted to a message queue while nonqueued messages are sent to the window procedure.

The queued messages are primarily those that result from user input in the form of keystrokes (such as WM_KEYDOWN and WM_KEYUP), characters that result from keystrokes (WM_CHAR), mouse movement (WM_MOUSEMOVE), and mouse button clicks (WM_LBUTTONDOWN). Queued messages also include the timer message (WM_TIMER), the repaint message (WM_PAINT), and the quit message (WM_QUIT). The nonqueued messages are everything else. In many cases the nonqueued messages result from queued messages. When you pass a nonqueued message to DefWindowProc within the window procedure, Windows often processes the message by sending the window procedure other messages.

This process is obviously complex, but fortunately most of the complexity is Windows' problem rather than our program's. From the perspective of the window procedure, these messages come through in an orderly, synchronized manner. The window procedure can do something with these messages or ignore them. For this reason, the window procedure has been called the ”ultimate hook.“ Messages notify the window procedure of almost everything that affects the window.

The nonqueued messages often result from calling certain Windows function calls or by explicitly sending a message by calling SendMessage. (Messages can also be placed in a message queue by calling PostMessage.)

For example, when WinMain calls CreateWindow, Windows creates the window and in the process sends the window procedure a WM_CREATE message. When WinMain calls ShowWindow, Windows sends the window procedure WM_SIZE and WM_SHOWWINDOW messages. When WinMain calls UpdateWindow, Windows sends the window procedure a WM_PAINT message.

Messages are not like hardware interrupts. While processing one message in a window procedure the program will not be interrupted by another message. Only when the window procedure calls a function that generates a new message will the message procedure process the message before the function returns.

The message loop and the window procedure do not run concurrently. When the window procedure is processing a queued message, it is the result of a call to DispatchMessage in WinMain. DispatchMessage does not return until the window procedure has processed the message.

But notice that the window procedure must be reentrant. That is, Windows often calls WndProc with a new message as a result of WndProc calling DefWindowProc with a previous message. This is one reason that a Windows program requires a 8-KB stack, as indicated in the module definition (.DEF) file. In most cases the reentrancy of the window procedure presents no problem, but you should be aware of it.

In many cases, the window procedure must retain information it obtains in one message and use it while processing another message. This information must be saved in variables defined as static in the window procedure or in global variables.

Of course, you'll get a much better feel for all this in later chapters as the window procedures are expanded to process more messages.