Talking about message mapping in MFC

xiaoxiao2021-04-10  361

As we all know, Windows is based on messaging, and the work processing is one of the key tasks of Windows programming, and the Windows program is also insensicable with the WINDOWS. Although the VC 6 class wizard can complete most of the work, unfortunately, it does not complete all work. This requires us to have a relatively clear understanding of the processing of messages in VC. Only in this way can do some complex message mapping processing when necessary.

The message in the MFC is processed by a so-called message mapping mechanism. It is a member of the message and its processing function and some of the program processing to handle some of the program code inside the application framework of this table. This benefit is to avoid a lot of CASE statement like a lot of SDK programming like early SDK. To handle various messages. Different kinds of messages have different methods of processing, so we must first understand the type of Windows message.

background:

Types of Windows Messages

There are three types of messages in Windows:

1. Standard Windows Message: This type of message is a prefix with WM_, but WM_Command exceptions. For example: WM_MOVE, WM_QUIT, etc.

2, command message: Command message is a message name in WM_COMMAND. In the message contains the flag ID of commands to distinguish between specific commands. Generated by command interface objects such as menu, toolbar.

3, control notification message: The control notification message is also a message name with WM_COMMAND. By the edit box, the list box, the sub-window is sent to the parent window notification message. In the message, the control notification code is included. To distinguish the notification message of the specific control.

The standard Windows message and control notification messages are mainly derived by the window class directly or indirectly by the CWND class. Relative to the standard Windows message and control notification message, the processing object of the command message is much wide. It can not only Window processing, can also be processed by document classes, document template classes, and application classes.

method:

Map method of different kinds of messages.

In the above three messages, the standard Windows message mapping is quite simple. Map processing of different messages can be done directly through class wizards, so it is not discussed in this article.

Any class that is derived from the CCMDTARGET class can have a message map. Message mapping includes the following two aspects:

Add a macro call in the definition file of the class:

Declare_message_map ()

Usually, the class definition in this statement.

Add a message mapping table in the implementation file (.cpp) of the class:

Begin_MESSAGE_MAP (class name, parent class)

........

Message mapping entry.

........

END_MESSAGE_MAP ()

Fortunately, in addition to certain classes (such as classes without base classes or class derived directly from the COBJECTO class). Other classes can be generated by class wizards. Although the generated class is just a frame, we need to add content. But message mapping The table has been adding us. Just the entrance item is waiting for us to join.

The command message mapping entry is an on_command macro. For example, the "Open ..." menu (ID value ID_File_Open) under the file menu is:

ON_COMMAND (ID_FILE_NEW, ONFILEOPEN)

After adding a message mapping entry, you need to complete the message processing function. The message processing function in the class is a member function of the class. To respond to a message, you must define a message processing function. Defining a message processing function includes the following three aspects content.

1. Add the function prototype of the message processing function in the class definition (function declaration)

2. Add a corresponding message mapping entry item in the message mapping table of the class.

3. Add a function body of the message processing function in the implementation of the class.

It should be noted that the prototype of the message processing function must be taken with AFX_MSG. For example:

AFX_MSG ONFILEOPEN (); // Function prototype

As a convention. Message handles are generally on ON

But sometimes we might want to use a message handler to handle a batch of messages. At this time, the class wizard is powerless. We must manually join the message mapping to complete this work. Available as follows:

First, the message mapping entry added to the implementation file (ie .cpp) in which the message is located is processed:

...

Begin_MESSAGE_MAP (CMYAPP, CWINAPP)

File: // {{AFX_MSG_MAP (CMYAPP)

...

File: //}} AFX_MSG_MAP

ON_COMMAND_RANGE (ID_MYCMD_ONE, ID_MYCMD_TEN, ONDOSMETHING)

END_MESSAGE_MAP ()

...

The statement of the bold mark is the statement we join (after agreed by the statement we join the statement). Where we use the macro ON_COMMAND_RANGE to implement from the command message ID_MYCMD_ONE to ID_MYCMD_TEN is handled by the onDosomthing function. Note .id_mycmd_one ID_mycmd_ten 's ID value must be continuous. And the ID_mycmd_one value is generally small.

After completing the above work, we also need to join the message processing function in this class (ie .h):

// generated message-map functions

protected:

File: // {{AFX_MSG (CMYAPP)

...

File: //}} AFX_MSG

AFX_MSG Void OnDoSomething (uint NID);

Declare_message_map ()

Since this is not a function of the VC wizard added, it is placed outside //}} AFX_MSG.

Note that this message handler has a UINT type parameter. The message processing function for handling a single command is generally no parameters (in addition to updating the user interface object status command message processing function). The main role of this parameter is the ID value of the commands selected by the user. .

The last thing to do is to implement the message processing function in the implementation file of this class. Similarly, sometimes we also want to use a message processing function to process a group of updated user interface object status command messages. Methods to:

First add the statement in the .cpp file, as follows:

...

Begin_MESSAGE_MAP (CMYAPP, CWINAPP)

File: // {{AFX_MSG_MAP (CMYAPP)

...

File: //}} AFX_MSG_MAP

ON_UPDATE_COMMAND_UI_RANGE (ID_MYCMD_ONE, ID_MYCMD_TEN, ONUPDATESMETHING)

END_MESSAGE_MAP ()

...

Adding a message processing function in the header file (ie .h) of this class:

// generated message-map functions

protected:

File: // {{AFX_MSG (CMYAPP)

...

File: //}} AFX_MSG

AFX_MSG Void Onupdatesomething (CCMDUI * PCMDUI);

Declare_message_map ()

Please pay attention, careful readers have noticed that the message processing function here is not as an additional UINT type parameter like the command message processing function. The reason is that this information has been included in PCMDUI. So no longer need this parameter. Finally don't forget to complete the function!

This place discussed this place for the command message. Next, the control notification message is discussed.

The control notification message is relatively complicated. Limited to the space cannot be involved. Here we only discuss the processing of the WM_NOTIFY message.

The reason for WM_NOTFY is as follows.

In Windows3.x, control notify them parent windows, such as mouse click, control background drawing events, by sending a message to the parent window. Simple notification only sends a WM_COMMAND message. Contains a notification code (such as bn_clicked) and one in WPARAM Control ID and a control handle in LPraram. Because WPARAM and LPARAM are used. There is no way to transfer other additional information. For example, in the BN_Clicked Notification message. There is no way to send a position information about the time the time of the mouse. In this case, some special messages can only be used. Includes: WM_CTLCOLOR, WM_VSCROLL, WM_HSCROLL, and more. It is worth mentioning that these messages can be reflected back to send their controls. It is called message reflection. Interested readers See the relevant monograph.

In Win32, those notification messages used in Windows 32 can also be used. But unlike the past by adding special purpose messages to send additional data for new notifications. But use a message called WM_NOTIFY, it can be in one The standard style transmits a large amount of additional data.

The WM_NOTIFY message contains an ID of the send message control in WPARAM and a pointer to a structure in the LPARAM. This structure may be an NMHDR structure. It may be the first member of NMHDR's larger structure. Because NMHDR is the first member, so pointers that point to this structure can also point to NMHDR. In many cases, this pointer will point to a larger structure, and it is necessary to convert it when you use it. For example, universal The notification message (its name is headed in NM_), the TTN_SHOW and TTN_POP of the Tool Tips Control are actually use the NMHDR structure.

The NMHDR structure contains handles, IDs, and notification codes (such as TTN_SHOW) that send message controls, and its formats are as follows:

Typedef sturct tagnmhdr {

HWND HWNDFROM;

Uint IDFrom;

Uint code;

NmHDR;

For TTN_SHOW, the value of the Code member will be set to TTN_SHOW.

The class wizard can create an ON_NOTIFY message mapping entry and provides a framework for handling a function. To handle the WM_NOTIFY type message .on_notify message mapping macro has the following syntax.

ON_NOTIFY (WNOTIFYCODE, ID, Memberfxn)

The meanings are as follows:

WNOTIFYCODE: The notification message notification code to be processed. For example: LVN_KeyDown.

ID: Control Identification ID.

MEMBERFXN: Handle member functions for this message.

This member function must have the following prototype declaration:

AFX_MSG Void Memberfxn (NMHDR * PNOTIFYSTRUCT, LRESULT * RESULT);

For example: assuming that you want the member function onkeyDownList1 to process the LVN_KeyDown message of ClistCtrl (Id Id = IDC_LIST1), you can use the class wizard to add the following message mapping:

ON_NOTIFY (lvn_keydown, idc_list1, onkeydownload1)

In the above example, the class wizard provides the following functions:

Void CMessageReflectiondlg :: onkeyDownloadList1 (NmHDR * PNMHDR, LRESULT * PRESULT)

{

LV_KEYDOWN * PLVKEYDOW = (lv_keydown *) PNMHDR;

// Todo: Add Your Control Notification Handler

// Code Here

* PRESULT = 0;

}

At this time, the class wizard provides an appropriate type of pointer. You can access this notification structure through PNMHDR, or through PLVKeyDow.

As mentioned earlier, sometimes we may need to handle the same WM_NOTIFY message for a set of controls. At this time, I need to use ON_NOTIFY_RANGE instead of ON_NOTIFY. When you use on_notify_range, you need to specify the ID range of the control. The message mapping portal and function prototypes are as follows :

ON_NOTIFY_RANGE (WNOTIFYCODE, ID, IDLAST, MEMBERFXN)

Parameter Description:

WNOTIFYCODE: Message Notification Code. For example: lvn_keydown,

ID: Id identification ID of the first control.

IDLAST: The identifier ID of the last control. (The identification value must be continuous)

MemberfxN: Message handler.

The member function must have the following prototype:

AFX_MSG Void MemberfxN (UINT ID, NMHDR * PNOTIFYSTRUCT, LRESULT * RESULT);

Where ID represents the control identification ID of the notification message

Conclusion:

There is little information on the MFC message map. This part of the content is quite important to programming. This paper briefly introduces several important message mapping processing in the MFC. But based on the limited discussion .

转载请注明原文地址:https://www.9cbs.com/read-133472.html

New Post(0)