“This is the 10th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Under the MFC framework, there are many system-defined messages, such as ON_WM_LBUTTONDOWN(), ON_WM_MBUTTONDOWN(), and so on. When we use it, we just need to declare and call it, the simplest way to use it.

A bit more difficult to use is to set up their own custom messages, and a bit more difficult is how to simulate the system messages, under normal circumstances just do ordinary project development functions are not used.

Here, I first explain how to achieve a custom message, and then in-depth on how to simulate the system message, there is a need to understand the yo ~

Custom message

In some cases, the message defined by the system can not fully meet the application of the program, at this time, the message needs to be customized, so how to achieve the custom message?

Step 1: Define a custom message name and ID

Under the MFC framework, messages after WM_USER is assigned are message ids that developers can customize.

Suppose we define a selected trigger message:

#define WM_USER_CLICKED WM_USER+1
Copy the code

This means a custom message is defined. The message name is WM_USER_CLICKED and the message ID is WM_USER+1

In order to facilitate the management of custom messages in large drawing development programs, it is generally not used to increment the number of WM_USER directly. Instead, it is used to replace WM_USER with a custom macro. For subsequent management, the format is as follows:

#define UIXML_WM_BASE WM_USER + 20000 #define WM_USER_CLICKED1 UIXML_WM_BASE +0 #define WM_USER_CLICKED2 UIXML_WM_BASE+1  #define WM_USER_CLICKED3 UIXML_WM_BASE+2 #define WM_USER_CLICKED4 UIXML_WM_BASE+3Copy the code

If you only have one or two custom messages in your application, there is no need to write them in this format.

Benefits of this format:

Custom message areas can be divided based on functionality. Suppose you are currently developing a framework class for internal use in your company. When customizing messages, you need to distinguish between those for your own development and those for external developers. Clear division of labor, not easy to misinformation.

Step 2: Send a custom message

Where you want to trigger a custom message, you need to send the message.

In the MFC framework, there are two message sending mechanisms: SendMessage and PostMessage.

::SendMessage(GetParent()->GetSafeHwnd(), WM_USER_CLICKED, 2, 1);Copy the code

Just take examples to illustrate, specific according to the actual function to determine ~

Step 3: Customize the message mapping

ON_MESSAGE(WM_USER_CLICKED1, OnCustomClicked1)
Copy the code

Parameter 1: Custom message defined

Parameter two: The mapping message of the response in the actual window

Step 4: Customize the message implementation

afx_msg LRESULT OnCustomClicked1(WPARAM  wParam , LPARAM lParam); 
Copy the code

Specific operation application can be written in OnCustomClicked1, this should be based on the actual needs of the application, here no longer do too much description, here, should know how to apply it ~

Analog system message

The simple custom message approach is already covered in custom messages, so let’s take it a step further! How to simulate system messages, for easy to understand explanation, here we simulate ComboBox control CBN_SELCHANGE messages.

People who have used MFC framework control development know that the message is sent by the system, usually we just apply it, if you write such a trigger message, how to achieve it?

Preconditions: Inherit the CWnd class to simulate the ComboBox control. In this case, all control messages need to be simulated internally, so that external developers can call the same message in the system ComboBox.

Suppose we use SendMessage to send a message, we also need to send a message, but we need to send a command message: WM_COMMAND

When is WM_COMMAND triggered?

1: when the user selects a command item from the menu

2: when the control sends a message to its parent window

3: When acceleration keystrokes are translated

In fact, Windows 9X above all send WM_NOTIFY, but to make it compatible with base classes, so the WM_COMMAND message is still used.

Once WM_COMMAND is specified to send messages, what data should wParam and lParam send?

WParam parameter

In sending custom messages, the wParam parameters are divided into high and low bytes and need to be sent using the MAKEWPARAM macro.

This macro creates a 32-bit unsigned value that is used as the wParam parameter in the message, and this macro concatenates two specified 16-bit values.

When passing parameters, the high position is the ID number sent by the current simulation. Each window or even each control has its own number, which is not difficult to obtain.

CBN_SELCHANGE is the system message that needs to be triggered, so the wParam parameter is written as follows:

MAKEWPARAM( GetDlgCtrlID(),CBN_SELCHANGE)
Copy the code

LPARAM parameters

For this parameter, it is as simple as passing the HWND of the current window into the LPARAM parameter.

Overall analog system sending format:

::SendMessage(pwnd->GetSafeHwnd(), WM_COMMAND, MAKEWPARAM( GetDlgCtrlID(),CBN_SELCHANGE), (LPARAM)GetSafeHwnd());
Copy the code

The second and third parameters of SendMessage are the most important for the simulated system to send messages. For the same reason, you can send it as a PostMessage.

Once the message is sent, how is it used in the outside world?

Since we are emulating system messages, the external window calls are consistent with the MFC’s own control message methods

Message mapping:

ON_CBN_SELCHANGE(ID_CUSTOMCOMBOBOXID, &CTestComboboxDlg::OnCbnSelchangeComboSd)
Copy the code

Does this look familiar to you? Is it the same as ComboBox? The subsequent use of the way are consistent!

I am a Chinese good citizen st, a C++ program ape ~