Reprint Source: http://blog.csdn.net/bichenggui/article/details/4677494
Windows message and Message Queuing
Unlike MS-DOS-based applications, Windows applications are event (message)-driven. They do not explicitly call functions, such as C run-time library calls, to get input, but instead wait for Windows to pass input to them. The Windows system passes the input events of the application to each window, each of which has a function called a window message handler function. The window message processing function handles various user input and returns control to the system after processing is complete. Window message processing functions are typically specified when registering a window. You can find out how the window message handler function is declared and implemented from a typical SDK program.
For Windows XP systems: If the top-level window stops responding for more than a few seconds, the system will assume that the window is not responding. In this case, the system hides the window and then generates a shadow (ghost) window covering it. This shadow window has the same z-axis order, position, size, and display properties. The shadow window allows the user to move it, resize it, or even close it (close the window that stops responding). Only these actions are allowed at this time, and in debug mode the system does not generate a shadow window.
This section discusses the following topics:
Windows messages
1. Message type
2. Message Delivery
3. Message Processing
4. Message filtering
5. Post message and send Message
6. Message deadlock
7. Broadcast messages
8. Querying messages
1. Windows messages
Windows passes user input to the window in the form of a message. Messages can be generated by systems and applications. The system generates the corresponding message for each input event,
For example, the user clicks the mouse, moves the mouse or scroll bar, or the application changes certain properties of the system, for example, the system changes the font resource, changes the window's
Size. Not only that, the application can generate a message that advertises the sending message to specify its form to perform certain tasks or interact with other applications.
The Windows system passes four parameters when sending messages to a window message handler function: Window handle, message identifier, two DWORD value (message parameter).
The window handle identifies the destination window for the message. Windows uses it to determine which window of the window the message handler receives the message.
A message identifier is a named constant used to indicate the meaning of the message. When a window handler receives a message, it determines how the message is handled by judging the message identifier, for example, the message identifier WM_PAINT message tells the window that the client area of the program window has changed and must be redrawn. The message parameter (DWORD value) specifies the data to be passed or the address of the data. The message parameter can be an integer value, a pointer value. can also be null.
A window procedure must determine how the message parameters are interpreted based on the message identifier.
2. Windows message Type
This section describes the two types of messages:
(1) system-defined messages
(2) application-defined messages
System-defined messages
The operating system sends messages to the application to communicate with the application. The operating system uses messages to control the operation of the application, passing user input and some other useful information to the application.
Applications can also send system-defined messages that the application uses to control the operation of windows that use the controls created by the registration window class.
Each system-defined message has a unique message identifier and a corresponding symbolic constant (defined in the header file of the Windows SDK). Symbolic constants typically indicate the category to which a system-defined message belongs. Different prefixes indicate different categories. The following is a common category:
Prefix Message Category
WM General window (normal windows)
ABM Application Desktop Toolbar (Application desktop toolbar)
BM Button Control (Button controls)
CB Combo Box control (combo box controls)
CBEM Extended combo Box control (extended ComboBox controls)
CDM Common dialog box (Normal dialog)
DBT Device (Devices)
DL Drag list box (drop-down)
DM Default push Button control
DTM Date and time picker control (date and timing selection control)
EM Edit Control (edit controls)
HDM Header Control (table header controls)
HKM Hot Key Control (Hotkey controls)
IPM IP Addresses control (IP address controls)
LB list box control (ListBox controls)
LVM List View Control (ListBox)
MCM Month Calendar control (Math calendar controls)
PBM Progress Bar (progress bar control)
PGM Pager Control ()
PSM Property sheet (Properties page)
RB Rebar Control (separator bar control)
SB Status bar window (status bar control)
SBM Scroll bar control (scroll bar controls)
STM static control (static controls)
TB Toolbar (Tool strip)
TBM Trackbar (track bar)
TCM tab Control (tab controls)
TTM Tooltip Control ()
TVM Tree-view Control ()
UDM Up-down Control ()
(2) application-defined messages
The application can communicate with its own window and other processes by creating a custom message. If the application creates its own message, the window handler can parse the information and make the appropriate processing.
Value range of message identifier value:
The system retains a range of messages, ranging from 0x0000 to 0x03ff (0x03ff equals wm_user-1). The value within this range is a system-defined message. Applications cannot use these values as their own custom messages.
The value from 0x0400 (numeric wm_user) to 0x7FFF is reserved for the application. Applications can use values in this range to define their own messages.
If your version of the operating system (Windows version) is version 4.0, you can also define your own messages using values from 0x8000 (Wm_app) to 0xBFF.
In addition, the application can call the RegisterWindowMessage function to register a message, and the operating system returns a message identifier between 0xc000 and 0xFFFF. and ensure that the return value is unique to the system. Therefore, you can avoid conflicts with messages that are used by other applications.
3. Distribution of information
Windows uses two methods to distribute to a window message handler: One is to put the message in the message queue (FIFO queue), the other is not put into the message queue, send directly to the window message handler function, let the window processing function to process the message.
Messages distributed to Message Queuing are called queued messages (Queued messages). They are primarily user input events, such as mouse or keyboard message disks, with WM_MOUSEMOVE messages, Wm_lbuttondown,wm_keydown, and WM_CHAR messages. There are others, including Wm_timer,wm_paint, as well as wm_quit. Most other messages, which are sent directly to the window procedure, are called non-queue messages (non queued messages).
(1) Queue (Queued) messages
Windows can display any number of windows at the same time. At this point, the system uses Message Queuing to correctly distribute keyboard and mouse events to the correct window.
Windows maintains a system message queue and maintains a separate thread message queue for each GUI thread, respectively. In order to avoid the overhead of creating thread Message Queuing for non-GUI threads, Message Queuing is not created when all threads create initialization. Message Queuing is created for threads only when the thread first invokes the GDI function. So those non-GUI threads are not Message Queuing.
Whenever the user moves the mouse and clicks the button or keyboard, the device driver for the mouse or keyboard converts the input into a message and places the message in the system message queue. Deleting Windows checks its own message queue, and if Message Queuing is not empty, remove and delete a message each time, then determine the target window of the message, and then place the message in the thread message queue of the thread that created the window. The thread's message queue receives all mouse and keyboard messages for the window created by the thread. The thread then removes the information from the queue and tells the system to distribute it to the corresponding window message handler.
In addition to WM_PAINT, Wm_timer, and wm_quit messages, the system always dispatches messages placed at the end of the message queue. This will ensure that a window receives messages in First-in, first-out order. Wm_paint,wm_timer, and wm_quit messages, are kept in the queue and are distributed to window message handlers only if there are no other messages in the queue. Additionally, multiple WM_PAINT messages from the same window are merged into one WM_PAINT message, and all invalid portions of the client area are merged. This is to reduce the number of times the window redraws the client area.
When Windows passes a message to a thread message queue, it first populates a MSG structure and then copies the MSG structure to the message queue. The information in MSG includes: Target window, message identifier, two message parameters, time of message dispatch, mouse cursor position. A thread can use the PostMessage or PostThreadMessage feature to send messages to its message queue or to another thread's message queue.
An application can use the GetMessage function to remove messages from its own message queue. The PeekMessage function is used to view the message without deleting it.
The PeekMessage function returns a MSG structure with message information.
After the message is removed from the message queue, the application can use the DispatchMessage function to instruct the system to send the message to a window message handler function. The DispatchMessage parameter is a pointer to the MSG structure obtained by the previous call to GetMessage or PeekMessage. DispatchMessage passes the window handle, the message identifier, these two message parameters to the window message handler, which does not pass the message delivery time and the mouse cursor position. Applications can obtain this information by invoking the Getmessagetime and getmessagepos that are invoked when the message is processed.
A thread can use the WaitMessage function to hand over its own control, and when it does not have a message in its message queue, the call to the WaitMessage function suspends the thread until it has a message in its message queue.
You can call the Setmessageextrainfo function to associate a value to the current thread's message queue. Then call the Getmessageextrainfo function to get the value associated with the last message that was obtained by the GetMessage or PeekMessage function. You can go to MSDN to see more information about these functions.
(2) Non-queue (nonqueued) messages
The nonqueued message is immediately sent to the destination's window message handler, bypassing the system's Message Queuing and thread Message Queuing. The system typically sends nonqueued messages to notify those events that affect the window. For example, when a user activates a new application window, the system sends some column messages to the window, including Wm_activate,wm_setfocus,wm_setcursor. These message notification windows are activated, keyboard input is directed to the window, and the mouse cursor moves within the bounds of the window.
Nonqueued messages can also originate from application call system functions. For example, the system calls the SetWindowPos function to move a window after a wm_windowposchanged message is sent. Some functions also send nonqueued messages, with Broadcastsystemmessage,broadcastsystemmessageex,sendmessage,sendmessagetimeout, and SendNotifyMessage. For more information about these functions, you can check out MSDN.
Message processing
The application must delete and process messages that are sent to its thread message queue. A single-threaded application typically processes the message loop in its WinMain function, deleting and distributing messages to the appropriate window. Multithreaded applications can create a message loop for a window on each thread. The following sections describe a message
How the Loop works and describes the role of the window message handler function:
(1) message loop
(2) Window processing function
Message loops
A simple message loop contains a call to the following three functions: Getmessage,translatemessage, and DispatchMessage. Note that if there is an error, GetMessage returns-1-so you need to test its return value to determine the case of-1
Code snippet:
...
MSG msg;
BOOL BRet;
while ((BRet = GetMessage (&msg, NULL, 0, 0))! = 0)
{
if (BRet = =-1)
{
Handle the error and possibly exit
}
Else
{
TranslateMessage (&MSG);
DispatchMessage (&MSG);
}
}
The GetMessage function obtains the message from the queue and copies the contents of the message to a MSG structure. It returns a value other than 0, which returns false and ends the message loop unless a WM_QUIT message is encountered. In a single-threaded application, the end message loop is often the first step in shutting down the application. The application can call the PostQuitMessage function to respond to Wm_destroy and end the message loop.
If you specify a window handle as the second parameter of the GetMessage, then getmessage only gets the messages related to this window in the message queue. GetMessage can also filter messages in the queue to get only the messages within the specified range. For more information on message filtering, please refer to message filtering.
The thread's message loop must include TranslateMessage if the thread needs to accept input for keyboard characters. Each time the user presses a key, the system generates the corresponding virtual key message (Wm_keydown and Wm_keyup). The virtual key message contains a virtual key that identifies the key that was pressed, not its associated character value. To obtain this value, the message loop must contain TranslateMessage, which is used to translate the virtual key message into a character message (WM_CHAR) and put it in the application's message queue. After several cycles, the WM_CHAR message is sent and distributed to a window.
The DispatchMessage function sends a message to the window associated with the window handle in the MSG structure. If the window handle is hwnd_topmost,dispatchmessage, the message is sent to all the top-level windows of the operating system. If the window handle is null,dispatchmessage do nothing.
Once the main thread of an application is initialized, the system launches the application's message loop and creates at least one window. Once started, the message loop continuously deletes messages from the thread's message queue and distributes them to the appropriate window. When the GetMessage function obtains a wm_quit message from the message list, the message loop ends.
A message queue requires only one message loop, even if an application contains multiple windows. DispatchMessage always dispatches the message to the correct window, because the message in each queue is the MSG structure, which contains the handle to the window to which the message belongs.
You can modify the message loop in several ways. For example, you can delete messages from the queue, but not distribute them. This is useful when sending some messages that do not have a destination window. You can also use GetMessage to get only the specified message, which is useful if you have to temporarily bypass the normal Message Queuing FIFO order.
When an application uses a shortcut key, it must be able to convert the keyboard message to a command message. Therefore, the application's message loop must include the TranslateAccelerator function call. For more information about shortcut keys, see keyboard accelerators.
If a thread uses a modeless dialog box, the message loop must include the IsDialogMessage function so that the dialog box can receive keyboard input.
(2) window message processing function
The window message function receives and processes all messages sent to the window. Each window class has a window message handler function that uses the same window message handler for each window created by the class.
The system sends the message to a window's program, and passes the message information to the window message handler function, the window message processing function checks the message identifier, identifies and processes the different messages according to the passed parameters.
A window procedure typically does not ignore a message. If the message is not processed, it must be sent to the System default window message handler, which performs a default processing by calling the DefWindowProc function, and returns the result of a process. The window program must then return the value as the result of its own message processing. Most window message handlers handle only a small portion of the message and return the other to the system's default window message handler function.
Because the window message handler function is shared by all windows that belong to the same window class, it can handle messages from several different windows. To determine the specific window message, the window message handler function can check the window handle in the message structure.
"Go" Windows message and Message Queuing in detail