Deep analysis of the message in VC (in)

Source: Internet
Author: User
Tags bool getmessage message queue range

Queue messages and non-queue messages

From the way messages are sent, messages can be divided into 2 types: Queue messages and non-queue messages. Message queues can be divided into system message queues and thread message queues. System message queues are maintained by Windows, thread message queues are maintained by each GUI thread, and to avoid creating message queues for Non-gui, all threads are generated without Message Queuing, and only when the thread first invokes the GDI function system to create a message queue for the thread. Queue messages are sent to system message queues, then to thread message queues, and non-queue messages are sent directly to the destination window process.

For queue messages, the most common is the mouse and keyboard-triggered messages, such as Wm_mousermove,wm_char, and other messages, such as WM_PAINT, Wm_timer, and Wm_quit. When the mouse or keyboard event is triggered, the corresponding mouse or keyboard driver converts the events to the corresponding messages and then transports them to the system message queue, which is processed by the Windows system. The Windows system is at the right time, take a message out of the system message queue and determine that the message is to be sent to that window, based on the MSG message structure we referred to earlier, and then send the message to the appropriate queue of the thread that created the window, and the following things should be bothered by thread Message Queuing. Windows is starting to get busy with its own business. The thread sees the message in its own message queue, takes it out of the queue, and sends it through the operating system to the appropriate window process.

In general, the system always posts the message at the end of the message queue. This ensures that the window accepts messages in a first-in, first-out order. However, WM_PAINT is an exception, and multiple wm_paint of the same window are merged into one WM_PAINT message, merging all invalid areas into an invalid area. The purpose of merging Wm_pain is to reduce the number of times a window is refreshed.

Non-queue messages will bypass system queues and message queues, sending messages directly to the window process. The system sends a non-queue message notification window, and the system sends a message notification window. For example, when a user activates a window system to send Wm_activate, Wm_setfocus, and Wm_setcursor. These messages inform the window that it was activated. Non-queue messages can also be generated by calling a system function when the application is invoked. For example, when a program calls the SetWindowPos system to send a wm_windowposchanged message. Some functions also send non queue messages, such as the functions we are going to talk about below.

Sending messages

Having learned the above basic theories, we can make a simple message sending and receiving.

There are 3 ways to send a message to a window: Send, send, and broadcast.

The functions that send messages are SendMessage, Sendmessagecallback, SendNotifyMessage, SendMessageTimeout, and the functions of sending messages are mainly PostMessage, PostThreadMessage, PostQuitMessage; functions to broadcast messages all I know is broadcastsystemmessage, Broadcastsystemmessageex.

SendMessage's prototype is as follows: Lresult SendMessage (HWND hwnd,uint msg,wparam wparam,lparam), which sends a message to one or more windows. Wait until the message is processed before returning. However, it should be noted that if the window receiving the message is part of the same application, the window function of the window is immediately invoked as a subroutine, and if the window receiving the message is created by another thread, the window system switches to the appropriate thread and invokes the corresponding window function. This message will not be placed in the target application queue. The return value of the function is returned by the window function of the window that receives the message, and the value returned depends on the message being sent.

The PostMessage prototype is as follows: BOOL PostMessage (HWND hwnd,uint msg,wparam wparam,lparam LPARAM), which places a message in the message queue of the thread that created the HWND window. This function will return control as soon as the message is processed. Note that if the HWND parameter is HWND_BROADCAST, the message will be sent to all overlapping and pop-up windows in the system, but the child window will not receive the message; If the HWND parameter is NULL, The function is similar to calling the PostThreadMessage function by setting the dwThreadID parameter to the flag of the current thread.

From these 2 representative functions above, we can see how the message is sent and how it is sent: whether the sent message is processed immediately and whether the function returns immediately. The sent message is processed immediately, the function is returned after processing, and the sent message is not processed immediately, he is placed in an advanced first queue and waits until the application is empty, but the function returns immediately after the message is placed.

In fact, there is not much difference between sending a message to a window processing process and directly calling the window processing, and the only difference is that you can ask the operating system to intercept all messages being sent, but not to intercept the direct calls to the window's process.

Messages sent by mail usually correspond to user input events, because these events are not very urgent and can be slow to buffer, such as the mouse, keyboard messages will be sent, and buttons and other messages will be sent.

Broadcast messages are used less, broadcastsystemmessage function prototypes are as follows:

Long Broadcastsystemmessage (DWORD dwflags,lpdword lpdwrecipients,uint uimessage,wparam wparam,lparam LPARAM); The function can send a message to the specified receiver, which can be an application, an installable driver, a network driver, a system-level device-driven message, and any combination of them. It should be noted that if the dwflags parameter is bsf_query and at least one recipient returns Broadcast_query_deny, the return value is 0, and if Bsf_query is not specified, the function sends the message to all recipients and ignores its return value.

Receipt of messages

There are 3 main functions of receiving messages: GetMessage, PeekMessage, WaitMessage.

The GetMessage prototype is as follows: BOOL GetMessage (lpmsg lpmsg,hwnd hwnd,uint wmsgfiltermin,uint); This function is used to get messages in the range of message values that are related to the window specified by the HWND parameter and wmsgfiltermin and Wmsgfiltermax parameters. Note that if the HWND is NULL, GetMessage gets the message that belongs to any window that calls the function application, and if both Wmsgfiltermin and Wmsgfiltermax are 0, GetMessage returns all the available messages. After the function is fetched, messages other than the WM_PAINT message in the message queue are deleted, and WM_PAINT is deleted only after it has been processed.

The PeekMessage prototype is as follows: BOOL PeekMessage (lpmsg lpmsg,hwnd hwnd,uint wmsgfiltermin,uint) That is used to view Message Queuing for an application, and if there is a message placed in the structure that lpmsg refers to, however, unlike GetMessage, the PeekMessage function does not wait until a message is placed in the queue. Similarly, if the HWND is NULL, PeekMessage gets the message that belongs to any window that calls the function application, and if hwnd=-1, then the function returns only the message sent to the Postappmessage function that has the HWND parameter null. If both Wmsgfiltermin and Wmsgfiltermax are 0, then PeekMessage returns all available messages. After the function is fetched, messages other than the WM_PAINT message in the message queue are deleted, and WM_PAINT is deleted only after it has been processed.

The WaitMessage prototype is as follows: BOOL vaitmessage (); When an application has nothing to do, the function gives control to another application, suspending the application until a new message is placed in the application's queue before returning.

Processing of messages

Next we talk about the message processing, first we look at VC message pump:

while(GetMessage(&msg, NULL, 0, 0))
{
    if(!TranslateAccelerator(msg.hWnd, hAccelTable, &msg))
    {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
    }
}

First, GetMessage gets a message from the message queue in the main thread of the process and copies it to the MSG structure, and if there are no messages in the queue, the GetMessage function waits for a message to come back. If you pass a window handle to GetMessage as the second argument, only the message from the specified window can be obtained from the queue. GetMessage can also filter messages from message queues to accept only messages that fall within the message queue. This is the time to use Getmessage/peekmessage to specify a message filter. This filter is a range of message identifiers or a form handle, or both. This is useful when the application is looking for a message to post into the message queue. Wm_keyfirst and Wm_keylast constants are used to accept all keyboard messages. Wm_mousefirst and Wm_mouselast constants are used to accept all mouse messages.

TranslateAccelerator then determines whether the message is a key message and is an accelerator message, and if so, the function converts several key messages into a callback function that is passed to the window by an accelerator key message. Once the accelerator key is processed, the function TranslateMessage converts two key message wm_keydown and Wm_keyup to a WM_CHAR, but it should be noted that the message Wm_keydown,wm_keyup will still be passed to the window's callback function.

After processing, the DispatchMessage function sends this message to the callback function that is already set in the window specified by the message. If the message is Wm_quit, the GetMessage returns 0 to exit the loop body. An application can use PostQuitMessage to end its own message loop. Typically called in the Wm_destroy message in the main window.

Here is a common example to illustrate the use of this message pump:

if (::PeekMessage(&msg, m_hWnd, WM_KEYFIRST,WM_KEYLAST, PM_REMOVE))
{
      if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)...
}

Here we accept all the keyboard messages, so we use Wm_keyfirst and wm_keylast as arguments. The last parameter can be either Pm_noremove or pm_remove, indicating whether the message information should be removed from the message queue.

So this small code is to determine whether to press the ESC key, if it is processed.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.