The principle and application of Windows message and message queue are described in detail in this paper. Share to everyone for your reference. The specific analysis is as follows:
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 rather wait for Windows to pass input to them. The Windows system passes the application's input events to each window, and each window 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 completed. The window message handler function is typically specified when registering a window. You can declare and implement a window message handler function from a typical SDK program.
For Windows XP systems: If the top-level window stops responding to a message for more than a few seconds, the system will assume that the window does not respond. In this case, the system hides the window and then generates a shadow (ghost) window to cover 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 (closes the window that stops responding). At this point only these actions are allowed, in debug mode, the system will not generate 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 Message
8. Query message
It is divided into the following:
1. Windows message
Windows passes user input to the window in the form of a message. Messages can be generated by systems and applications. The system generates a corresponding message for each input event,
For example, the user clicks the mouse, moves the mouse or scroll bar, or the application changes some of the system's properties, such as the system changed the font resources, changed a window of the
Size. Not only that, an application can generate a message that sends a message to specify its form to perform certain tasks or to interact with other applications.
The Windows system passes four arguments when it sends a message to a window message handler: A window handle, a message identifier, and two DWORD values (message parameters).
The window handle identifies the destination window for the message. Windows uses it to determine which window's window message handler function received the message.
A message identifier is a named constant that is used to indicate the meaning of a message. When a window handler receives a message, it determines how to process the message based on the judgment 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. A message parameter (DWORD value) specifies the data or the address of the data to be passed. 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 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 running of windows that use controls created by the registration window class.
Each system-defined message has a unique message identifier and the 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. Here are the common categories:
Prefix Message Category
WM General window (generic window)
ABM Application Desktop Toolbar (application Desktop tool bar)
BM Button Control (Button controls)
CB Combo Box Control (ComboBox controls)
CBEM Extended combo Box control (extended ComboBox controls)
CDM Common dialog box (Normal dialog)
DBT Device (equipment)
DL Drag list box (dropdown)
DM Default push button control (default button controls)
DTM date and Times picker control (date and time selection controls)
EM Edit Control (edit controls)
HDM Header Control (table header controls)
HKM Hot Key controls (Hotkey control)
IPM IP address controls (IP addresses control)
LB list box control (ListBox controls)
LVM List View Control
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)
SB Status bar window (status bar control)
SBM Scroll bar control (scroll bar controls)
STM static control (static controls)
TB Toolbar (tool bar)
TBM Trackbar (track bar)
TCM tab Control (tab controls)
TTM Tooltip Control ()
TVM Tree-view Control ()
UDM Up-down Control ()
Applications can communicate with their windows and other processes by creating custom messages. If the application creates its own message, the window handler functions can parse the information and make the appropriate processing.
Value range of message identifier value:
The system retains a range of messages from 0x0000 to 0X03FF (0x03ff equals wm_user-1). The value in 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. The application can use the values in this range to define its own messages.
You can also use the 0x8000 (Wm_app) to 0xBFF to define your own message if your operating system version (Windows version) master version is 4.0.
In addition, an application can call the RegisterWindowMessage function to register a message, and the operating system returns a message identifier between 0xc000 and 0xFFFF. And this return value is guaranteed to be unique to the system. Therefore, you can avoid conflicts with messages that are used by other applications.
3. Information distribution
Windows uses two methods to distribute to a window message handler function: One is to put the message in the message queue (first-in first out queue), the second is not put to the message queue, directly sent to the window message processing function, let the window processing functions to process the message.
Messages that are distributed to message queues are called queued messages (Queued messages). They are primarily user input events, such as a mouse or keyboard message tray, with wm_mousemove messages, Wm_lbuttondown,wm_keydown, and WM_CHAR messages. There are also a few other, including Wm_timer,wm_paint, as well as wm_quit. Most other messages, which are sent directly to the window process, are called non-queue messages (non queued messages).
(1) Queue (Queued) message
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. To avoid the overhead of creating thread message queues for a non-GUI thread, no message queues are created when all threads create initialization. The system does not create message queues for threads until the first time a thread calls the GDI function. So there are no message queues for those non-GUI threads.
Each time the user moves the mouse and clicks a 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 queues, and if Message Queuing is not empty, each fetch and delete a message, then determine the target window for 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 the mouse and keyboard messages from the window created by the thread. The thread then deletes the information from the queue and tells the system to distribute them to the corresponding window message handler function.
In addition to WM_PAINT, Wm_timer, and wm_quit messages, the system always distributes messages placed at the end of the message queue. This will ensure that a window receives messages in a first-in, first-out order. Wm_paint,wm_timer, and wm_quit messages, are kept in queues and are distributed to window message handlers only if there are no other messages in the queue. In addition, multiple WM_PAINT messages from the same window are merged into a WM_PAINT message, and all invalid parts of the client area are merged. This is to reduce the number of times the window redraw the client area.
When Windows delivers messages to thread Message Queuing, it first populates a MSG structure and then copies the MSG structure to Message Queuing. MSG information includes: Target window, message identifier, two message parameters, time when the message was distributed, mouse cursor position. A thread can use the PostMessage or PostThreadMessage function to send messages to its own message queue or to a message queue of another thread.
Applications can use the GetMessage function to delete messages from their own message queues. View without deleting the message, using the PeekMessage function.
The PeekMessage function returns a MSG structure with message information.
After a message is deleted from Message Queuing, the application can use the DispatchMessage function to instruct the system to send a 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, which gives the window message handler function, which does not deliver the message time and the mouse cursor position, for the two message parameters. The application can obtain this information by Getmessagetime and getmessagepos that are invoked when the message is processed.
A thread can use the WaitMessage function to relinquish control, and when there is no message in its message queue, the call to the WaitMessage function suspends the thread until there is a message in its own message queue.
You can call the Setmessageextrainfo function to associate a message queue with a value to the current thread. 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 sent immediately to the destination window message handler function, bypassing the system's Message Queuing and thread message queues. The system usually 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. The Message notification window is activated, the keyboard input is directed to the window, and the mouse cursor is moved to the edge of the window.
nonqueued messages may also originate from an application calling a system function. For example, a wm_windowposchanged message is sent after the system calls the SetWindowPos function to move a window. Some functions also send nonqueued messages, there are broadcastsystemmessage,broadcastsystemmessageex,sendmessage,sendmessagetimeout, and SendNotifyMessage. For more information about these functions, you can refer to MSDN.
Message processing
The application must delete and process the messages sent to it by the thread message queue. A single-threaded application usually handles the message loop of its WinMain function, deleting and distributing messages to the appropriate window. Multithreaded applications can create a message loop for each thread in a single window. 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 the following three functions called: Getmessage,translatemessage, and DispatchMessage. Note that if there is an error, GetMessage returns-1-so you need to test its return value to determine if-1 of the case
Code fragment:
Copy Code code as follows:
...
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 gets the message from the queue and copies the message contents 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 an 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 argument for GetMessage, then getmessage only gets the message in the message queue that is relevant to the window. GetMessage can also filter messages in queues to get only 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 the input of keyboard characters. Each time the user presses a key, the system generates the corresponding virtual key messages (Wm_keydown and Wm_keyup). The virtual key message contains a virtual key code that identifies the pressed key, not its associated character value. To get this value, the message loop must contain TranslateMessage, which translates the virtual key messages into character messages (WM_CHAR) and puts them into the application's message queue. After several loops, the WM_CHAR message is distributed to a window.
The DispatchMessage function sends a message to a window associated with a window handle in the MSG structure. If the window handle is hwnd_topmost,dispatchmessage, the message is sent to all top-level windows of the operating system. If the window handle is null,dispatchmessage don't do anything.
Once the main thread of an application is initialized, the system starts the application's message loop and creates at least one window. Once started, the message loop continues to delete messages from the thread's message queue and distributes them to the appropriate window. The message loop ends when the GetMessage function obtains a wm_quit message from the list of messages.
A message queue requires only a message loop, even if an application contains more than one window. DispatchMessage always dispatches messages to the correct window, because the message in each queue is the MSG structure that contains the handle of the window to which the message belongs.
You can modify the message loop in a variety of ways. For example, you can delete messages from a queue, but do not distribute them. This is useful when sending messages with no destination window. You can also use getmessage only to get the specified message, which is useful if you have to temporarily bypass the normal message queue FIFO order.
When your application uses shortcut keys, you must be able to convert keyboard messages to command messages. 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.
(3) window message handler 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 function for each window created with the class.
The system sends messages to a window program, and delivers information about the message to the window message handler function, the window message handler function examines the message identifier, and according to the parameters passed, identifies and processes different messages.
A window procedure usually does not ignore a message. If the message is not processed, it must be sent to the System default window message handler, whether by calling the DefWindowProc function to perform a default processing and returning a processing result. 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 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.
I hope this article will help you with your Windows application design.