What is a message, message handler function, message map?
The message simply means that a command is issued to the program by the input device to perform an operation. A specific operation is a series of your code. Called a message handler function.
In the SDK, the message is very easy to understand, when the window is established there will be a function (window processing function) to start a message loop, we can also clearly see the context of the message processing. A switch case statement can be done, the message loop will not end until the Wm_quit message is encountered, and the rest of the messages are intercepted and the corresponding handler function is called.
But in MFC, which encapsulates the API, the message seems to be getting a little more complicated, and we don't see the familiar switch case statement, instead of something called a message map. Why MFC to introduce the message mapping mechanism, you can imagine that in the current program development activities, your program has more than one form, the main window even if there is only one, the menu, toolbars, controls These are child windows, then we need to write how many switch case, and also to assign a message handler to each message, how complicated it is. Therefore, MFC uses a new mechanism. Using an array to map the window message and the corresponding message handler, you can understand that this is a table. This mechanism is the message map. This table is defined in the window base class CWnd, derived class message map if you have no action it is empty, that is, if you do not add the message handler manually, the parent class's message handler is executed when the derived window accepts a message. It is obviously efficient to do so.
Message structure provided by MFC
At the same time, MFC defines the following two main structures:
Afx_msgmap_entry
struct afx_msgmap_entry{
UINT nmessage; ID number of Windows message
UINT NCode; Notification of control messages
UINT NID; The ID of the Windows Control message
UINT Nlastid; Represents a range of messages that are mapped to a specified range
UINT NSig; Represents the action ID of a message
Afx_pmsg PFN; Pointers to Message handler functions
};
Afx_msgmap
struct afx_msgmap{
#ifdef _afxdll
Const afx_msgmap* (pascal* Pfngetbasemap) ();
#else
Const afx_msgmap* Pbasemap;
#endif
Const afx_msgmap_entry* Lpentries;
};
Afx_msgmap can get the message map entry address of the base class and get its own message map entry address.
The process of MFC's next message is generally the case.
1, _afxcbtfilterhook intercept the message (this is a hook function)
2, _afxcbtfilterhook the window process is set to AfxWndProc.
3. function AfxWndProc receive messages sent by the Windows operating system.
4, Function AfxWndProc Call function Afxcallwndproc for message processing.
5, the function Afxcallwndproc calls the CWnd class method WindowProc carries on the message processing.
How do I add my own messages?
We already know the message mechanism of window, how to join our own message? Okay, let's see.
A standard message handler is like this.
The default handler for standard Windows messages (wm_xxxx WM is an abbreviation of window message) is predefined in the CWnd class. The class library names these handlers based on the message name. For example, the handler for the WM_PAINT message is declared in CWnd as:
afx_msg void OnPaint ();
The AFX_MSG keyword indicates the role of the C + + virtual keyword by making these handlers distinct from other CWND member functions. Note, however, that these functions are not actually virtual but are implemented through message mapping. At the beginning of this article, we explained why we should do this.
All classes that are capable of message processing are based on the CCmdTarget class, meaning that the CCmdTarget class is the parent class for all the message-processing classes that can be processed. The CCmdTarget class is the basis and core of MFC's processing of command messages.
To override a handler defined in a base class, simply define a function in the derived class that has the same prototype and create a message-map entry for this handler. We can build most of the window messages or custom messages through ClassWizard, through ClassWizard can automatically establish the message map, and the message processing function framework, we just need to fill in the blanks we want to do, add the things you want to do to the processing function. This is very simple, not to elaborate. But maybe we need to add some Windows messages or custom messages that are not supported by ClassWizard, so we need to build a framework for message mapping and message processing, usually in the following steps:
First step: Define the message. Microsoft recommends that user-defined messages are at least wm_user+100, because many new controls also use Wm_user messages.
#define Wm_mymessage (wm_user + 100)
Step two: Implement the message handler function. The function uses the Wpram and lparam parameters and returns Lpesult.
Lpesult cmainframe::onmymessage (WPARAM WPARAM, LPARAM LPARAM)
{
TODO: Handle user-defined messages, fill in the blanks.
return 0;
}
Step three: Describe the message handler function in the afx_msg block of the class header file:
{{afx_msg (CMainFrame)
afx_msg LRESULT onmymessage (WPARAM WPARAM, LPARAM LPARAM);
}}afx_msg
Declare_message_map ()
Fourth step: In the message block of the user class, use the ON_MESSAGE macro directive to map the message to the message handler function.
On_message (Wm_mymessage, OnMyMessage)
As you can see, the user-defined message is the same as the message we added through ClassWizard, which is the use of the On_message macro, which establishes the message map.
In fact, the message category can be divided into a variety of, said above is only one of them. There are three main message categories: (The following section is from MSDN)
1. Windows messages
Such messages mainly include messages beginning with the prefix wm_, except for WM_COMMAND. Windows messages are processed by Windows and views. Such messages often come with parameters that determine how messages are handled.
2. Control notification
Such messages include WM_COMMAND notification messages that are sent from controls and other child windows to their parent window. For example, when a user executes an action that may change text in an edit control, the edit control sends a WM_COMMAND message to its parent that contains the En_change control notification code. The window handler for the message responds to this notification message in some appropriate way, such as retrieving the text in the control.
The framework transmits the control notification message as if it were transmitting other WM_ messages. However, there is an exception to the BN_CLICKED control notification message that is sent by the button when the user clicks the button. The message is specially handled as a command message and is routed like any other command.
3. Command message
Such messages include WM_COMMAND notification messages that are emitted by user interface objects (menus, toolbar buttons, and shortcut keys). The framework handles commands differently than other messages, and you can use more kinds of object processing commands.
Windows messages and control notification messages are processed by Windows (the window is an object of a class derived from the CWnd class). Includes CFrameWnd, CMDIFrameWnd, CMDIChildWnd, CView, CDialog, and your own classes derived from these base classes. These objects encapsulate the handle of the Hwnd--windows window.
command messages can be processed by a broader range of objects (documents, document templates, and application objects themselves), not just windows and views. When a command directly affects a particular object, you should let the object handle the command. For example, the Open command on the File menu is logically associated with an application: When the application receives this command, the specified document opens. The handler for the Open command is therefore a member function of the application class.
Command message We are more common is the menu item and the tool bar, you can see his message Map Macro and window message is not the same, the general form is like this
On_command (ID,MEMBERFXN)
The first parameter is the command ID, an ID number corresponds to a message processing, and of course you can have multiple IDs to share a handler function. Common applications such as: Menu items open the ID of the document and the toolbar button to open the ID of the document using either a handler function, or simply set their ID to the same.
There is also a message called a notification message. For example, some complex controls, such as a tree control, need to pass more information when clicked, such as the position of the cursor and a structure of the current item, so MFC defines a macro for each notification message for the control, which grows like this:
On_control (EN_CHANGE,ID,MEMBERFXN)
There are many kinds of messages exist in MFC, macro definitions are different, we can comprehend by analogy.
There are hundreds of window messages. You can look at the beginning of wm_ from MSDN or look at the member functions of CWnd, which will list you a lot, and don't forget that there are many non-window messages. Thor cannot list it, nor is it necessary. Let's check it out. However, for some common, new control messages and special notification messages I'll put them in a few tables, let's make a reference.
The order in which messages are processed in MFC
1. AfxWndProc () receives the message, looks for the CWnd object to which the message belongs, and then calls Afxcallwndproc ().
2. Afxcallwndproc () stores messages (message identifiers and message parameters) for future reference, and then calls WindowProc ().
3. WindowProc () sends a message to ONWNDMSG (), and if the message is not processed, it is sent to DefWindowProc ().
4. Onwndmsg () First sorts the messages by byte, calls the OnCommand () message response function for the WM_COMMAND message, and calls the OnNotify () message response function for the WM_NOTIFY message. Any missed messages will be standard messages. The onwndmsg () function searches the message image of the class to find a handler function that can handle any window message. If the onwndmsg () function cannot find such a handler function, it returns the message to the WindowProc () function, which sends the message to the DefWindowProc () function.
5. OnCommand () View this is not a control notification (the LPARAM parameter is not NULL), if it is, the OnCommand () function tries to map the message to the control that manufactures the notification, if it is not a control notification, or if the control rejects the mapped message, OnCommand () the OnCmdMsg () function is called.
6. OnNotify () also attempts to map the message to a control that manufactures notifications, and if the mapping is unsuccessful, onnotify () invokes the same oncmdmsg () function.
7. Depending on the class that receives the message, the ONCMDMSG () function will potentially pass command messages and control notifications during a process called command Routing. For example, if the class that owns the window is a framework class, command and control notification messages are also passed to the view and document classes, and a message handler function is found for the class.
The order in which windows are created in MFC
1. PreCreateWindow () is an overloaded function that can change the creation parameters in the overloaded function before the window is created (you can set the window style, and so on).
2. Presubclasswindow () is also an overloaded function that allows the first sub-classification of a window OnGetMinMaxInfo () as a message response function, in response to a WM_GETMINMAXINFO message, allowing the setting of the maximum or minimum size of the window.
3. Onnccreate () is also a message response function that responds to the Wm_nccreate message and sends a message to tell the window that the client area is about to be created.
4. Onnccalcsize () is also a message response function that responds to the wm_nccalcsize message, which is allowed to change the window client area size.
5. OnCreate () is also a message response function that responds to a WM_CREATE message and sends a message telling a window has been created.
6. OnSize () is also a message response function that responds to the WM_SIZE message and sends the message to tell the window that the size has changed.
7. OnMove () is also a message response function that responds to the Wm_move message and sends this message stating that the window is moving.
8. OnChildNotify () is an overloaded function that is called as a partial message map, telling the parent that the window is about to be told that a window has just been created.
The order in which the modal dialog box is opened in MFC
1. DoModal () is an overloaded function that overloads the DoModal () member function.
2. Presubclasswindow () is also an overloaded function that allows a window to be classified first.
3. OnCreate () is a message response function that responds to a WM_CREATE message and sends this message to tell a window that it has been created.
4. OnSize () is also a message response function that responds to the WM_SIZE message and sends this message to tell the window that the size of the change is changed.
5. OnMove () is also a message response function that responds to the Wm_move message and sends this message to tell the window that it is moving.
6. Onsetfont () is also a message response function that responds to the WM_SETFONT message and sends this message to allow changes to the font of the control in the dialog box.
7. OnInitDialog () is also a message response function that responds to a WM_INITDIALOG message, sends this message to allow the control to initialize the dialog box, or creates a new control.
8. Onshowwindow () is also a message response function that responds to the Wm_showwindow message, which is called by the ShowWindow () function.
9. OnCtlColor () is also a message response function that responds to a WM_CTLCOLOR message and is sent by a parent window that has changed the color of the control on the dialog box or dialog box.
OnChildNotify () is an overloaded function that is sent as a result of a WM_CTLCOLOR message.
The order in which the modal dialog box is closed in MFC
1. OnClose () is a message response function that responds to the WM_CLOSE message and is called when the Close button is clicked.
2. OnKillFocus () is also a message response function that responds to the Wm_killfocus message when a window is about to lose keyboard input focus before it is sent.
3. OnDestroy () is also a message response function that responds to WM_DESTROY messages and is sent when a window is about to be destroyed.
4. OnNcDestroy () is also a message response function that responds to the Wm_ncdestroy message when a window is destroyed after being sent.
5. PostNcDestroy () is also an overloaded function, which is called by CWnd as the last action to handle the OnNcDestroy () function.
The order in which the non-modal dialog box is opened in MFC
1. Presubclasswindow () is an overloaded function that allows the user to first sub-categorize a window.
2. OnCreate () is a message response function that responds to a WM_CREATE message and sends this message to tell a window that it has been created.
3. OnSize () is also a message response function that responds to the WM_SIZE message and sends this message to tell the window that the size of the change is changed.
4. OnMove () is also a message response function that responds to the Wm_move message and sends this message to tell the window that it is moving.
5. Onsetfont () is also a message response function that responds to the WM_SETFONT message and sends this message to allow changes to the font of the control in the dialog box.
The order in which the non-modal dialog boxes are closed in MFC
1. OnClose () is a message response function that responds to a window's wm_close message and sends this message when the Close button is clicked.
2. OnDestroy () is also a message response function that responds to a window's Wm_destroy message and sends this message when a window is destroyed.
3. OnNcDestroy () is also a message response function that responds to a window's Wm_ncdestroy message and sends this message when a window is destroyed.
4. PostNcDestroy () is an overloaded function that is called by CWnd as the last action to handle the OnNcDestroy () function.
MFC message Mechanism