Windows uses two methods to route messages to a window procedure. The first method involves posting messages to a first-in, first-out queue called a message queue. The second method involves sending messages directly to a window procedure.
Messages that are posted to a message queue are called queued messages. These consist primarily of messages that result from user input through the mouse or keyboard, for example, WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN, and WM_CHAR. Other queued messages include the timer message (WM_TIMER), the paint message (WM_PAINT), and the quit message (WM_QUIT). Most other messages are typically sent directly to a window procedure—these are called non-queued messages.
Windows can display any number of windows at the same time, but only one window at a time can receive user input from the mouse or keyboard. Windows uses message queues to route mouse and keyboard input to the appropriate window. A message queue is a system-defined memory object that temporarily stores messages. Windows maintains a single system message queue and any number of thread message queues, one for each thread that creates a window.
As the user moves the mouse, clicks the mouse's buttons, or types at the keyboard, the device driver for the mouse or keyboard converts the input from the device into messages and places them into the system message queue. Windows removes the messages, one at time, from the system message queue, examines them to determine the destination window, then posts them to the message queue of the thread that created the destination window. A thread's message queue receives all mouse and keyboard messages for all of the windows created by the thread. The thread removes messages from its queue and directs Windows to pass them to the appropriate window procedure for processing. For more information about threads, see Chapter 3, “Processes and Threads.”
With the exception of the WM_PAINT message, Windows always posts messages to the end of a message queue. A window procedure typically receives messages from the beginning of the queue. This ensures that a window receives its input messages in the proper sequence. A WM_PAINT message is kept in the queue and is forwarded to the window procedure only when the queue contains no other messages. Multiple WM_PAINT messages for the same window are combined into a single WM_PAINT message, combining all invalid parts of the client area into a single area. This is done to reduce the number of times a window must redraw the contents of its client area.
The system posts a message to a thread's message queue by filling an MSG structure and copying the structure to the message queue. Information in the MSG structure includes the handle of the window for which the message is intended, the message identifier, the two message parameters, the message time, and the mouse-cursor position. A thread can post a message to its own message queue by using the PostMessage function, or to the queue of another thread by using the PostThreadMessage function.
An application can remove a message from its queue by using the GetMessage function. It can examine a message without removing it by using the PeekMessage function. This function fills an MSG structure with information about a message.
After removing a message, an application can use the DispatchMessage function to direct Windows to pass the message to a window procedure for processing. DispatchMessage takes a pointer to the MSG structure that was filled by a previous call to the GetMessage or PeekMessage function. The DispatchMessage function passes the window handle, message identifier, and the two message parameters to the window procedure, but does not pass the time or mouse-cursor position. An application can retrieve this information by calling the GetMessageTime and GetMessagePos functions while processing a message.
Non-queued messages are sent immediately to the destination window procedure, bypassing the system message queue and thread message queue. Windows typically sends non-queued messages to notify a window of events that have affected it. For example, when the user activates a new application window, Windows sends the window a series of messages that includes WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR. These messages notify the window that it has been activated, that keyboard input is being directed to the window, and that the mouse cursor has been moved within the borders of the window. Non-queued messages can also result when an application calls certain Windows functions. For example, Windows sends the WM_WINDOWPOSCHANGED message after an application uses the SetWindowPos function to move a window.
An application can send a message by calling the SendMessage, SendNotifyMessage, or SendDlgItemMessage function. For more information about sending messages, see Section 0.2.4, “Sending a Message.”