Windows message Programming

Source: Internet
Author: User

This article includes the following content:

1. A simple understanding of Windows messages
2. Understand Windows messages through a simple Win32 Program
3. Further understanding of Windows messages through several Win32 program instances
4. Queue messages and non-queue messages
5. wm_command and wm_notify
6. Message ing of MFC
7. Message reflection mechanism

1. A simple understanding of Windows messages

A message is a notification sent by windows to tell the application that something has happened.
For example, click a button of an application. In this case, Windows (operating system) sends this message to the application, notifying the application that this button is clicked, and the application will respond accordingly.
A message is generally identified by a 32-bit number, which uniquely identifies the message. The identifiers of these messages are generally defined in the header file winuser. H, for example:

# Define wm_paint 0x000f
# Define wm_quit 0x0012

In fact, the message itself is a MSG structure. The MSG structure is defined as follows:

Typedef struct tagmsg {
Hwnd; // window handle for receiving messages
Uint message; // message identifier
Wparam; // 32-bit Additional information
Lparam; // 32-bit Additional information
DWORD time; // message creation time
Point pt; // The cursor position in the screen coordinate system when the message is created
} MSG;

That is to say, for any message, there is a MSG variable corresponding to it, which contains information about the message. In general, we only use the message identifier of the message, which uniquely represents the message.
For example, when we receive a character message, the value of the message member variable is wm_char, But what character is entered by the user, it is explained by wparam and lparam. The information represented by wparam and lparam varies with the message.
Windows has defined a large number of messages, which are called system messages. In addition to system messages, we can also define messages by ourselves, that is, custom messages.
Messages with a value less than 0x0400 are system messages, and custom messages are generally greater than 0x0400.
System message values generally follow the following rules, as shown in table 1:

Range Meaning
0x0001 -- 0x0087 Mainly window messages
0x00a0 -- 0x00a9 Non-customer zone message
0x0100 -- 0x0108 Keyboard Message
0x0111 -- Zero X 0126 Menu message
0x0132 -- 0x0138 Color Control Message
0x0200 -- 0x020a Mouse message
0x0211 -- 0x0213 Menu cyclic message
0x0220 -- 0x0230 Multi-document message
0x03e0 -- 0x03e8 DDE message
Zero X 0400 Wm_user
0x0400 -- 0x7fff Custom message

Table 1

In winuser. H, we have the following definitions:

# Define wm_user 0x0400

For custom messages, we generally use wm_user and an integer to define custom messages, such:

# Define wm_recvdata wm_user + 1

If you contact windows programming for the first time, or contact windows for the first time, you may not understand the above explanation, so do not worry, the subsequent instances will gradually give you an understanding of message programming in windows.

2. Understand Windows messages through a simple Win32 Program
Example 1: A simple Win32 program code (see the source code project M1)
Open VC ++ 6.0 and create a Win32 application named M1. In this project, add the C ++ source file named M1. Add the following code to the file:

// A simple Win32 application // This simple example explains how Windows messages are transmitted # include <windows. h> // declare the window process function lresult callback wndproc (hwnd, uint, wparam, lparam); // define a global variable, as the window class name tchar szclassname [] = text ("simplewin32"); // application main function int winapi winmain (hinstance, hinstance hprevinstance, lpstr szcmdline, int icmdshow) {// wndclass window class; // when the width of the horizontal direction of the window and the height of the vertical direction change, redraw the entire wndclass window. style = cs_hredraw | cs_vredraw; // associate the window procedure function wndcl Ass. lpfnwndproc = wndproc; wndclass. cbclsextra = 0; wndclass. cbwndextra = 0; wndclass. hinstance = hinstance; // instance handle wndclass. hicon = loadicon (null, idi_application); // wndclass icon. hcursor = loadcursor (null, idc_arrow); // wndclass cursor. hbrbackground = (hbrush) getstockobject (white_brush); // wndclass. lpszmenuname = NULL; // menu wndclass. lpszclassname = szclassname; // class name // register the window class if (! Registerclass (& wndclass) {MessageBox (null, text ("registerclass fail! "), Szclassname, mb_iconerror); Return 0 ;}// create the window hwnd; hwnd = createwindow (szclassname, // The window class name text (" the simple Win32 application "), // window title ws_overlappedwindow, // window style, that is, the Windows window style cw_usedefault we usually use, // specify the initial horizontal position of the window, that is, the X coordinate cw_usedefault in the upper left corner of the window in the screen coordinate system, // specifies the Initial vertical position of the window, that is, the Y coordinate cw_usedefault in the upper left corner of the window in the screen coordinate system, // The width of the window cw_usedefault, // The window height is null, // The parent window handle is null, // The Window menu handle hinstance, // The instance handle is null); showwindow (hwnd, icmdshow ); // display window updatewindow (hwnd); // display the window now // message loop MSG; while (getmessage (& MSG, null )) // retrieve message {translatemessage (& MSG) from Message Queue; // convert message dispatchmessage (& MSG); // send message} return MSG. wparam;} // message processing function // parameter: Window handle, message, Message Parameter, Message Parameter lresult callback wndproc (hwnd, uint message, wparam, lparam) {// process the message switch (Message) {Case wm_destroy: // when the user closes the window, the window is destroyed, the program needs to end, and the quit message is sent, to exit the message loop postquitmessage (0); Return 0 ;}// other messages are delivered to the default processing function provided by the system: Return: defwindowproc (hwnd, message, wparam, lparam );}

This is a very simple Win32 applet. A window is displayed during compilation and running, and closing the window program ends. Simple annotations have been made in the code, and we will not explain much here. Here I will focus on the message loop section.

// Message loop MSG; while (getmessage (& MSG, null,) // obtain the message from the Message Queue {translatemessage (& MSG ); // convert the message dispatchmessage (& MSG); // send the message}

This code is part of the message loop. It is used to cyclically detect message queues (do not understand message queues? It doesn't matter, it will be detailed later) in the message and process it. This Code involves the getmessage, translatemessage, and dispatchmessage functions. The related functions include peekmessage and waitmessage. Here, we will briefly explain these five functions.

1. getmessage

Function prototype:

Bool getmessage (lpmsg, hwnd, uint wmsgfiltermin, uint wmsgfiltermax );

Parameters:

Lpmsg: a pointer to the MSG structure used to store messages taken from the message queue.
Hwnd: Window handle. If this parameter is a non-zero value, getmessage only retrieves messages in this window (including its subwindows). If it is zero, getmessage retrieves messages in the entire process.
Wmsgfiltermin: specify the minimum message value to be retrieved, that is, the downstream boundary parameter of the message range.
Wmsgfiltermax: the upper limit parameter. If both wmsgfiltermin and wmsgfiltermax are zero, no message filtering is performed. getmessage Retrieves all valid messages.

Return Value

Getmessage: wm_quit message retrieved. The returned value is zero. In other cases, a non-zero value is returned.

Function:

This API function is used to extract a message from the message queue and put it in the variable referred to by lpmsg. (Note: If there is no message in the message queue of the retrieved window, the program will pause in getmessage (...) Function .)
Let's talk about the getmessage function in a more general sense:
When the program executes getmessage (), it checks the message queue. If a message is in the message queue, It retrieves the message and fills the message in the MSG structure specified by lpmsg, returns true. If there is no message in the message queue at this time (the message queue is empty), it will block the thread, that is, hand over the control to the system until there is content in the message queue, the thread will be awakened to continue the execution.
For the getmessage () function, another note is that when the message retrieved from the message queue is wm_quit, the return value of the function is 0. We usually use this to exit the message loop and end the program.

Statement:

while(GetMessage(&msg,NULL,0,0))……

2. peekmessage

Function prototype:

Bool peekmessage (lpmsg, hwnd, uint wmsgfiltermin, uint wmsgfiltermax, uint wremovemsg );

Parameters:

The four parameters lpmsg, hwnd, wmsgfiltermin, and wmsgfiltermax have the same meanings as the parameters corresponding to getmessage.
Wremovemsg: this parameter determines whether to delete a message when reading the message. Optional values include pm_noremove and pm_remove. If you select pm_noremove, after the function is executed, the message remains in the Message Queue (read message); if you select pm_remove, after this function is executed, the message will be removed from the Message Queue (same as getmessage ()).

Return Value:

If there is a message in the message queue, the return value is true. If there is no message in the message queue, the return value is false.

Function:

Peekmessage () is also used to retrieve messages from the message queue, but it is getmessage (), mainly in the following two points:

(1) getmessage () can only remove messages from the message queue. That is, after getmessage () is executed, the message will be removed from the message queue.
Peekmessage () can be used to remove messages from a message queue. You can also read messages to keep them in the message queue.

(2) When there is no message in the message queue, getmessage () will block the thread and wait for the message. If peekmessage () is different from getmessage (), it will return immediately after execution, if a message exists in a message queue, the return value is true. If no message exists in the message queue, the return value is false.

3. waitmessage

Function prototype:

Bool waitmessage (void );

Function:

This function is used to give control to other threads when there is no message in the message queue. This function will suspend the thread until there are new messages in the message queue.
This function is specially used with peekmessage. When no message exists in the message queue, the thread is suspended, waiting for the arrival of new messages in the message queue, which can reduce the computing burden on the CPU.

4. translatemessage

Function prototype:

Bool translatemessage (const MSG * lpmsg );

Parameters:

Ipmsg: pointer to the MSG structure, which is the message obtained from the message queue by the function getmessage or peekmessage.
Function: converts a virtual key message to a character message. The character message is sent to the Message Queue of the calling thread and is read when the current thread calls the getmessage or peekmessage function.
What is a virtual key code? To facilitate input management and reduce program dependencies on devices, Windows maps all the buttons on the keyboard with a two-digit hexadecimal number, which is called a virtual key code. Generally, the virtual key code starts with VK _. For example, the virtual key code corresponding to the ESC key is vk_escape, the virtual key code corresponding to the Space key is vk_space, And the vk_lwin corresponds to the Windows logo key on the left.
When a key is pressed, The wm_keydown message is triggered. The wparam parameter value of the wm_keydown message is the virtual key value. This value can be used to determine which key is pressed.
Why do we need to convert a virtual key code into a verification code?
For example, if we press the 'A' key, the character we get may be 'A' or 'A' in lower case, which is determined by Caps Lock) and whether shift is pressed at the same time. The function of the translatemessage () function is to automatically return an ascii code value based on these situations without considering these issues.
Not all the virtual key values will be translated into the escape code. Letter, number keys are relative to the primary code, and such as the direction of the arrow keys, F1-F12 function keys these buttons do not have the primary code corresponding. When the virtual key code needs to be converted to an ascii code, the translatemessage () function places a wm_char message in the message queue. The wparam parameter value of the wm_char message is the converted ASCII code value.

5. dispatchmessage

Function prototype:

Long dispatchmessage (const MSG * lpmsg );

Function:
The function is simple, that is, the message processing function that distributes messages to the window is executed.
After learning about these five functions, the message loop code is not hard to understand:

Getmessage () retrieves a message from the message queue and converts the acquired message into a secret code, A wm_char message is put in the message queue, and the message is sent to the corresponding message processing function for processing. This process is executed cyclically until the wm_quit message is received.

3. Further understanding of Windows messages through several Win32 program instances

Example 2: Use getmessage and peekmessage to process the message loop (see the source code project m2)
Same as project M1, create project m2, copy all source code of Project M1 to M2, and change the code of the message loop part:

// Message loop MSG; while (true) {If (peekmessage (& MSG, null, pm_remove) // obtain the message from the Message Queue {If (MSG. message = wm_quit) break; translatemessage (& MSG); // convert the message dispatchmessage (& MSG); // send a message} else waitmessage ();} // end of while (true)

Compile and run project m2 and observe the running effect. It can be seen that the same effect can be achieved by processing the message loop with peekmessage.
Peekmessage is more flexible in processing message loops than getmessage, especially in game programming. Game programmers do not want players to remain static when there is no keyboard or mouse input. They want monsters to rush out from the back, target players, and hunt down players. To achieve this, a message loop is required: when a message needs to be processed is processed, the program code will automatically generate a fierce scene for the rest of the time.
The following example 3 simulates the message loop.
Example 3: Simulate and demonstrate how game programming processes messages (see the source code project m3 ).
For detailed code, see project m3. Compile and execute the code. You will find that the program keeps drawing circles by yourself, which simulates the game's automatic fierce scenes. When you press the top, bottom, left, and right arrow keys, you will find that you draw lines in the corresponding direction, which simulates the game program to process player messages in a timely manner.

4. Queue messages and non-queue messages
In Windows, messages are divided into two types: one is the messages that need to be processed immediately, and the other is the messages that do not need to be processed immediately.
For messages that need to be processed immediately, Windows directly sends them to the message processing function of the window for processing. Such messages are called non-queue messages;
For messages that do not need to be processed immediately, Windows will send them to the application's message queue for queuing, and the application will process them one by one. We call such messages queue messages.
For a clearer explanation of this problem, see Figure 1:

Figure 1

Figure 1:

1. Windows operating system has a message queue, which stores messages received by the operating system. For example, when a key is pressed, the keyboard sends a message to the Message Queue of the operating system.
2. The operating system distributes messages in the system message queue to the Message Queue of each application. If it is a message of 1st applications, the operating system sends it to 1st applications and places it in the message queue of 1st applications; if it is a message of 2nd applications, it is sent to the Message Queue of 2nd programs.
3. the application's message loop retrieves messages from its own message queue, and the retrieved messages are called window functions for processing.
4. postmessage is a message that is sent immediately after the function is executed. The sent message is a queue message, which is placed in the queue of the Program for processing. Generally, the newly sent messages are placed at the end of the message queue. This ensures that the window processes the messages in the FIFO order.
Sendmessage is a non-queue message sent by sendmessage. It directly calls the window function for processing. The sendmessage function is returned until the message processing is complete.

We need to learn about the sendmessage and postmessage functions.

Function prototype of sendmessage:

Lresult sendmessage (hwnd, uint MSG, wparam, lparam );

This function sends a message to the window until the message is processed. That is to say, the window function of the window receiving the message is called immediately. The Return Value of the function is returned by the window function of the window that receives the message.

Postmessage function prototype:

Bool postmessage (hwnd, uint MSG, wparam, lparam );

This function places a message in the message queue of the thread that creates the hwnd window. This function controls the returned message without waiting for the message to be processed.
From the above two functions, we can see the difference between the message sending method and the sending method: The sent message will be processed immediately, and the function will return after the processing is complete; the sent message will not be processed immediately. It is placed in a first-in-first-out queue, waiting for processing in order, and the function will return immediately after the message is placed.
Messages sent in sending mode usually correspond to user input events, because these events are not very urgent and can be buffered. For example, the mouse and keyboard messages are sent messages. Applications call system functions. Generally, the system sends non-queue messages. For example, when the program calls setwindowpos, the system will send the wm_windowposchanged message.
Routine M4 to test the capacity of the Message Queue (see the source code M4)
The Code has been annotated to compile and run the program, and you will find that the maximum capacity of the message queue is 10000.
M5. use NotePad to view messages processed by message queues and window process functions.
The starting point of this routine is to use NotePad to capture messages in the message queue and messages processed by window function.
This routine also demonstrates the differences between postmessage and sendmessage.
Because the routine is relatively complex, there are more annotations in the routine. Compile and run the program. The following window is displayed:

Messages that have been processed by the M5 window procedure function recorded in callback.
Open the messagequeue.txt file, for example:

The file records each message in the message queue and the idnumber of the message. One of the messages is wm_postmessage, which indicates that the wm_postmessage sent by postmessage is indeed placed in the message queue.
Open the messagewndproc.txt file, for example:

The file records the message and Message ID processed in the window process. Two messages, wm_postmessage and wm_sendmessage, indicate two problems: wm_postmessage is taken out of the message queue, function processing is performed when the message is distributed to the window again. The wm_sendmessage message sent by sendmessage is directly sent to the window process function for processing without passing through the message queue.

5. wm_command and wm_notify

A control notification message refers to a message in which the control in a window has something to notify the parent window. When the user interacts with the control window, the control notification message is sent from the control window to its main window. This message is generally not used to process user commands, but to enable the control to be changed in the main window.
Both wm_command and wm_notify are control notification messages.
In the original windows 3. X, wm_policy is not available, and only the wm_command message exists. The wparam parameter contains a notification code and Control ID, and the lparam parameter contains the control handle. In this way, both wparam and lparam are filled with no additional space to transmit other information, such as the position and time of the mouse.
To solve this problem, Windows 3. X puts forward a solution, that is, to add some additional messages to some messages, such as the drawitemstruct used in the control self-painting. In this way, the additional content of different messages is different, the results are very confusing.
In Win32, Microsoft proposed a better solution and introduced the nmhdr structure. The introduction of this structure unifies messages and uses it to transmit various complex messages.
The content of the nmhdr structure is as follows:

Nmhdr
{
Hwnd hwndfrom; // equivalent to the lparam of the original wm_command message
Uint idfrom; // equivalent to the wparam (loword) of the original wm_command message)
Uint code; // The wparam (hiword) Notification code equivalent to the original wm_command message
}

With this structure, wm_notify can also include more information. You can define a larger structure. The first element of this structure is the nmhdr structure, you can add additional information after this element. In this large structure, the first member is nmhdr, so that we can use the pointer to nmhdr to point to this structure, no matter whether there is anything else.
It can be seen that wm_notify is a more flexible Message format than wm_command. lparam contains a pointer called nmhdr structure. The Control ID is put in wparam. Windows 3. X has some controls, such as edit, combo, list, button, etc. The format of the notification message sent by the control is wm_command, while the later Win32 general controls, such as List View, image list, IP address, Tree View, toolbar, etc. All notifications sent by the wm_notify control are sent.
In addition, when you select a command item in the menu, the wm_command message is also sent.
When you select a command item or control in the menu to send a notification message to the parent window, you can use wm_command message. To distinguish these two cases, it is stipulated that they have the following differences, such as table 2:

Message Source
Wparam (high word)
Wparam (low word)
Lparam

Menu
0
Menu identifier (IDM _*)
0

Widget
Notification Code defined by the Control
Control ID
Control Window handle

Table 2

The routine M6 demonstrates the difference between the wm_command message from the menu and the wm_command message sent by the sub-control (see the source code M6 with the command)
Open VC ++ 6.0, create a Win32 Application Project M6, and then create a C ++ source file in the project. For details about the file content in the file named M6 and M6, see the routine M6.
Open the M6 folder in the path where the routine M6 is located and create a new text document, such:


Rename the newly created document .txt to "m6.rc", for example:

Right-click m6.rc and choose "WordPad" from the shortcut menu, as shown in:

For more information, see m6.rc. Save and exit. Compile and run the project M6. The following window is displayed:

Click "firstbutton" and "menu1" respectively. A message box is displayed.
For wm_command Message Processing in M6, the source code is as follows:

Case wm_command: {If (lparam = 0) {Switch (loword (wparam) {Case idm_menu1: MessageBox (null, "menu1 menu clicked", "M6 ", mb_ OK); break; Case idm_exit: destroywindow (hwnd); break ;}} else // process the wm_command control notification message triggered by the Child control {// (loword (wparam )) yescontrol ID switch (loword (wparam) {Case buttonid1: If (hiword (wparam) = bn_clicked) {MessageBox (null, "button clicked", "M6 ", mb_ OK) ;}break ;}} break;

 

For wm_command messages, both menus and child controls can be triggered. We first determine lparam. If lparam is 0, it is the wm_command message triggered by the menu; If lparam is not 0, it is the wm_command control notification message triggered by the sub-control. For the wm_command message triggered by the menu, we can use (loword (wparam) (menu ID) to determine which menu triggered the message. For the wm_command message triggered by the control, we know which control triggers the message through (loword (wparam) (Control ID), and pass (hiword (wparam) (Control-defined notification code) know the message triggered by the control.
In this example, we manually add and edit the resource file m6.rc, so that you can understand the essence of the resource file. In actual programming, you can use the resource editor to add and edit resource files more conveniently. The subsequent routines will demonstrate the instructions.
The M7 routine demonstrates the wm_notify control notification message (see M7 with source code)
A wm_notify message is a message sent by a universal control to its parent window. The wparam parameter is the ID of the universal control that sends messages, and the lparam parameter is a pointer, which points to a nmhdr structure, this structure contains the notification code and other additional information.

The following shows the structure of nmhdr:

Typedef struct tagnmhdr {
// Handle of the control for sending messages, which is equivalent to the lparam of the original wm_command message
Hwnd hwndfrom;
// The ID of the control for sending messages, which is equivalent to the wparam (loword) of the original wm_command message)
Uint idfrom;
// The Notification code, that is, the specific message sent, which is equivalent to the wparam (hiword) Notification code of the original wm_command message
Uint code;
} Nmhdr;

Open VC ++ 6.0, create a Win32 Application Project M7, and create a C ++ source file in this project. The file name is M7. For details about the content of the M7 file, see the routine m7.
Next, we use the resource editor to add resources. Click "file"-> "new". In the "new" dialog box, select "resource script" with the file name "M7", for example:

Click OK to add the M7 resource file.
Right-click the "m7.rc" folder and select "insert ..." Menu items, such:

The "insert resource" dialog box is displayed,

Select "dialog" and click "new" to create a dialog box resource.
Right-click the new "idd_dialog1" and change the ID to "idc_dig1" in the attribute dialog box to close the attribute box.

Double-click "idc_dialog" to open this dialog box and adjust it to the appropriate size. In the dialog box, add a list control and set the ID of the list control to idc_list, for example:

Change the list control type to "Report", for example:

Edit and run the program. The following dialog box is displayed:

Double-click the first line or the second line, and a message box is displayed.
The program code has detailed comments. You can read the code and carefully understand the wm_notify control notification message.

6. Message ing of MFC

When using MFC programming, message sending and processing are essentially the same as Win32. However, it encapsulates message processing and simplifies the complexity of Message Processing during programming, it processes messages through message ing. programmers do not have to design and implement their own window processes.
To put it bluntly, the message ing mechanism in MFC is essentially a huge table for messages and their processing functions. Message ing is basically divided into two parts:
In the header file (. h) There is a macro declare_message_map (), which is placed at the end of the class and is a public attribute. What corresponds to it is in the implementation part (. CPP) added a message ing table with the following content:

Begin_massage_map (current class, base class of the current class)
// {Afx_msg_map (cmainframe)

Message entry

//} Afx_msg_map

End_message_map ()

However, only these two items are not enough to complete a message. If a message works, there must be three parts to collaborate:
1. Add the corresponding function declaration to the class definition;
2. Add the corresponding message ing entry in the message ing table of the class;
3. Add the corresponding function body to the class implementation;

Message Addition

(1) Use Class Wizard to automatically add
Select View> Class Wizard from the menu to activate Class Wizard, select the message map tag, and select the class from the class name combo box that we want to add the message. In the object IDs list box, select the class name. The messages list box displays the reload member functions and window messages of this class. The reload member function is displayed in the upper part of the list, which is represented by uppercase and lowercase letters of the fictional member function. Others are window messages, which appear with uppercase letters. Select the message to be added and click Add funtion. Class Wizard automatically adds the message.
Sometimes, the message we want to add cannot be found in the message list. We can use the class info label on the Class Wizard to extend the message list. On this page, find the message filter combo box and use it to change the options in the messages list box on the homepage.

(2) manually add messages
If the messages list box does not contain the message we want, we need to manually add it:
1) Add the declaration of processing functions in the. h file of the class, and then add the declaration after the //} afx_msg line. Note that it must start with afx_msg.
Generally, the best place to add a processing function declaration is under the table maintained by Class Wizard in the source code, which marks the {} arc of its field. Everything in the arc may be destroyed by Class Wizard.
2) then, find the //} afx_msg_map row in the. cpp file of the user class, and add the message entry item immediately after it. Also, it is placed outside.
3) Finally, add the entity of the message processing function to the file.

For messages that can be added using Class Wizard, try to use Class Wizard to reduce our workload. For messages and custom messages that cannot be added using Class Wizard, manually add them. In general, message programming of MFC is relatively simple for users, so instances are no longer used here.

7. Message reflection mechanism
What Is Message reflection?
The parent window refers to the notification message sent to the control, which is reflected back to the control for processing (that is, the control is allowed to process the message). This notification message allows the control to process the message by itself.
Through the previous learning, we know that normally, the control sends notification messages to the parent window, and the parent window processes these notification messages. In this way, the parent window (usually a dialog box) processes these messages. In other words, the messages in the control must be processed in the parent window class. When we add child controls, copy the code in the parent window class. Obviously, this is inconvenient for code maintenance and porting, and significantly deviated from the object programming principles of C ++.
Since version 4.0, MFC provides a message reflection mechanism to reflect the notification message back to the control. Specifically, for a reflected message, if the control has a message processing function, the control itself processes the message. If the control does not process the message, the framework sends the message to the parent window, so that the parent window continues to process the message. It can be seen that the new message reflection mechanism does not undermine the original notification message processing mechanism.

The message reflection mechanism provides the control with the opportunity to process notification messages, which is very useful. If the message is processed by the parent window in the traditional method, the dependency of the control object on the parent window is increased. This obviously violates the object-oriented principle. If the message is processed by the control, the control object is more independent, which greatly facilitates code maintenance and transplantation.
Instance M8: a simple demonstration of the Message reflection mechanism of MFC. (See the source code engineering M8)
Open VC ++ 6.0 and create a dialog box-based project M8.
In this project, create a cmyedit class with the base class cedit. Then, add three variables to the class as follows:

PRIVATE:
Cbrush m_brbkgnd;
Colorref m_clrbkgnd;
Colorref m_clrtext;

In cmyedit: cmyedit (), assign the initial values to the three variables:

{
M_clrbkgnd = RGB (255,255, 0 );
M_clrtext = RGB (0, 0, 0 );
M_brbkgnd.createsolidbrush (RGB (150,150,150 ));
}

Open classwizard, the class name is cmyedit, and select "= wm_ctlcolor" in messages. Do you find that the wm_ctlcolor message has an equal sign before it, which indicates that the message is a reflection message, that is, messages with equal signs can be reflected.

The message reflection function code is as follows:

Hbrush cmyedit: ctlcolor (CDC * PDC, uint nctlcolor) {// todo: change any attributes of the DC here PDC-> settextcolor (m_clrtext ); // set the text color PDC-> setbkcolor (m_clrbkgnd); // set the background color // note that the function returns NULL (return NULL) before rewriting the function content; // if the function returns NULL, The ctlcolor function of the parent window is executed without the ctlcolor function of the control, the purpose is to implement Message reflection return m_brbkgnd; // return background brush}

Add an edit control in the idd_m8_dialog dialog box, use classwizard to add a cmyedit-type variable m_edit1 to the Edit Control, and associate the Edit Control with cmyedit.

Compile and run the program to observe the running effect.
Let's write this. The level is limited. I hope it will help you.

Related Article

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.