MFC message details
1. How to use MFC to send a message,
First, obtain the pointer to the cwnd class object that receives the message;
Then, call the member function sendmessage () of cwnd ().
Lresult res = pwnd-> sendmessage (uint MSG, wparam, lparam );
The pwnd Pointer Points to the target cwnd class object. The MSG variable is a message. The wparam and lparam variables contain the parameters of the message, for example, where to click or select a menu item. The message returned by the target window is placed in the variable res.
To send a message to a window without a cwnd class object, you can use the handle of the following target window to directly call Windows API:
Lresult res =: sendmessage (hwnd, uint MSG, wparam, lparam );
Hwnd is the handle of the target window.
2. How to use MFC to send a message
Sending a message using MFC is almost the same as sending a message, but sending a message using postmessage () instead of sendmessage (). The returned res value is different. Res is not a value returned by the target window, it is a Boolean value that indicates whether a message is successfully put in the message queue.
3. retrieve a sent message
Normally, once a message is sent, the application sends it in the background. However, in special cases, you need to delete a message by yourself. For example, you want to stop the application before the application receives a message. There are two ways to delete a message from the application message queue, but neither of them involves MFC.
■ Method 1: peat the message queue without interfering with anything and check whether a message is there.
Bool res =: peekmessage (lpmsg, hwnd, uint wmsfiltermin, uint wmsgfiltermax, uint wremovemsg );
■ Method 2: wait until a new message reaches the queue, delete the message, and return the message.
Bool res =: getmessage (lpmsg, hwnd, uint wmsgfiltermin, uint wmsgfiltermax );
In the two methods, the hwnd variable specifies the window to intercept messages. If the variable is set to null, all window messages will be intercepted. The wmsgfiltermin and wmsgfiltermax variables correspond to the MSG variable in sendmessage () and specify the range for viewing messages. If "0, 0" is used, all messages are intercepted. If wm_keyfirst, wm_keylast, wm_mousefirst, wm_mouselast are used, all keyboard or mouse messages are intercepted. The wremovemsg variable specifies whether peekmessage () should be deleted from the queue. (Getmessage () always deletes messages ). This variable can have two values:
■ Pm_remove, peekmessage () will delete the message.
■ Pm_noremove and peekmessage () will keep the message in the queue and return a copy of it.
Of course, if you leave the message in the message queue and call peekmessage () again to view messages of the same type, the same message will be returned.
The lpmsg variable is a pointer to the MSG structure. MSG contains the retrieved message.
Typedef struct tagmsg {
Hwnd; // window handle message is intended
Uint message;
Wparam;
Lparam;
DWORD time; // The time the message was put in the queue
Point pt; // the location of the mouse cursor when
// Message was put in the queue
} MSG;
4. How does MFC receive a sent message?
The only difference between MFC processing and sending a message is that the sent message takes some time in the application's message queue. Before the message pump pops up, it must be in the queue all the time.
Message Pump
The message pump in the MFC application is in the member function run () of the cwinapp. When the application starts to run, run () is called. Run () divides the time into two parts. Some are used for background processing, such as canceling temporary cwnd objects, and others are used to check message queues. When a new message comes in, run () extracts it-that is, get the message from the queue using getmessage (), run two message translation functions, and then use dispatchmessage () the function calls the expected target window process of the message.
The message pump calls two translation functions: pretranslatemessage () and: translatemessage (). The MFC class of the target window can be called to use retranslatemessage to translate messages before sending a message to it. For example, cframewnd uses pretranslatemessage () to convert the acceleration key (for example, CTRL + S to store files) convert to a command message. Messages before translation are usually processed, and translated messages (if any) are re-sent to the queue. : Translatemessage is a window function that converts the original key code to a key character. Once a message is sent by dispatchmessage (), MFC processes it like a message sent by sendmessage.
5. How does MFC process a received message?
The purpose of processing the received message is very simple: Direct the message to a function that processes the message through the message identifier in the message. Non-MFC Windows use simple case statements to achieve this goal. Each case statement executes some functions or calls other functions.
Mainwndproc (hwnd, uint message, W Param wparam, lparam)
{
Switch (Message)
{
Case wm_create:
:::
Break;
Case wm_paint:
:::
Break;
Default:
Return (defwindowproc (hwnd, message, wparam, lparam ));
}
Return (null );
}
Any missed messages will be transmitted to a default message processing function. However, the case statement cannot be well adapted to C ++ and encapsulation technologies. In the C ++ environment, a message is required to be processed by a member function that specifically processes the type of message. Therefore, MFC does not use case statements, but uses more complex and Roundabout methods. However, it allows a private class to process messages, but only needs to do the following three things:
■ Derived class from the cwnd class object that will receive the message (the command message is c0000target ).
■ Write a member function to process messages in a derived class.
■ Define a query table (called a message image) in the class, which has the entry of the member function and the identifier of the message to be processed.
Next, MFC calls the following functions in turn to guide the input of messages to the processing function.
1) afxwndproc () receives the message, searches for the cwnd object to which the message belongs, and then calls afxcallwndproc ().
2) afxcallwndproc () Stores messages (Message identifiers and parameters) for future reference, and then calls windowproc ().
3) windowproc () sends a message to onwndmsg (). Then, if the message is not processed, it is sent to defwindowproc ().
4) onwndmsg () either calls oncommand () for the wm_command message or calls ony y () for the wm_notify message (). Any missed message is a window message. Onwndmsg () searches for message images to find a processing function that can process messages in any window. If onwndmsg () cannot find such a processing function, the message is returned to windowproc (), which sends the message to defwindowproc ().
5) oncommand () check whether this is a control notification (lparam is not null); if it is, oncommand () tries to map the message to the control that creates the notification; if it is not a control notification, or the control rejects the ing message, oncommand () calls on1_msg ().
6) onnotify () also tries to map messages to the control that creates notifications. If the ing fails, ony y () calls the same on1_msg () function.
7) according to the message receiving Class, onreceivmsg () potentially transmits command messages and control notifications in a process called command routing. For example, if the class that owns the window is a framework class, the command and notification messages are also transmitted to the view and document class, and a message processing function is found for the class.
Why message image?
After all, this is the c ++ language. Why does onwndmsg () not call a predefined virtual function for each window message? Because it occupies too much CPU. If so, when scanning a message image to accelerate this process, onwndmsg () may do unexpected things and get stuck in the assembler. Note that you can modify this process by reloading windowproc (), onwndmsg (), oncommand (), on1_y (), or on1_msg. The onwndmsg () overload can be inserted before window messages are sorted. The oncommand () or oncommand y () overload can be inserted before the message is reflected.