In-depth analysis of WINDOWS Message Mechanism in MFC

Source: Internet
Author: User

Recently, when I learned about the self-painting control, I found that Windows messages involve many aspects. If I do not learn it well, it is estimated that self-painting is hard to continue. so I read some articles and reprinted them if I felt good.

The reprinted content is as follows:

I do not have a deep understanding of windows and MFC, but I am very interested in the mechanism of MFC packaging API, especially after reading "let's get started with MFC, I feel that the application framework of Visual C ++ is very refined. In the past, I had some knowledge about the message processing mechanism of the SDI structure, but I did not know about the message mechanism of the mode dialog box. I have not been able to solve this problem after reading the in-depth book. Recently, I think I have learned about it through the help of netizens and reading msdn. At the rise of the moment, writing these words has no other purpose. I just hope that the latencies will be avoided, and I also hope that people who like me will share the opportunity to discuss and learn. If you are a cool man, you need to carefully consider whether you have enough time to read these childish texts.

Body:

One of the main differences between Windows programs and DOS programs is that Windows programs are based on event-driven and message mechanisms. How to Understand?

For example, why does a menu pop up when you click "start" button in windows?

When you click the left mouse button, the mouse-related driver in the operating system gets this signal [lbuttondown] immediately, and then it notifies the operating system-"Hi, the left mouse button is clicked! ", After the operating system receives this signal, it will be determined immediately-which window does the user target when the user clicks the left mouse button? How to judge? This is simple! In the current status, the window with focus [or control] is [this is of course the "Start" button]. Then the operating system immediately sends a message to the window to the Message Queue of the process in which the window is located. The message content should be the message code, additional parameters, window handle... Wait. Is only the operating system eligible to send messages to a message queue in a window? Otherwise, other programs are eligible. You can call sendmessage in your program
And postmessage. In this way, the clicked window gets a message containing the click sent by the operating system. The operating system no longer cares about the window because it is busy with other transactions. What should you do after your program gets a message? Windows displays the following information about the click event on the Start button: A menu is displayed. However, how is the process of getting a message to reflect it? This is the main content discussed in this article [of course only for MFC].

First, let me briefly talk about SDI, and then I will spend more on the text description mode dialog box.

For the SDI window, the initinstance () of your application class is about as follows:

Bool cex06aapp: initinstance ()
{
...............
Csingledoctemplate * pdoctemplate;
Pdoctemplate = new csingledoctemplate (
Idr_mainframe,
Runtime_class (cex06adoc ),
Runtime_class (cmainframe), // main SDI frame window
Runtime_class (cex06aview ));
Adddoctemplate (pdoctemplate );
Ccommandlineinfo using info;
Parsecommandline (partition info );
If (! Processshellcommand (cmdinfo ))
Return false;
M_pmainwnd-> showwindow (sw_show );
M_pmainwnd-> updatewindow ();
Return true;
}

Complete some work, such as dynamically generating relevant documents and views, displaying the main frame window, and processing parameter line information. These are all "Clear codes" displayed in your project ". Now let's set the breakpoint to return true; a sentence, followed by the source code of the MFC to see what has been done inside the MFC.

The program enters SRC \ winmain. cpp. the next major action should be:

Nreturncode = pthread-> Run ();

Note that the focus is on. Enter F11

Int cwinapp: Run ()
{
If (m_pmainwnd = NULL & afxolegetuserctrl ())
{
// Not launched/embedding or/automation, but has no main window!
Trace0 ("Warning: m_pmainwnd is null in cwinapp: Run-quitting application. \ n ");
Afxpostquitmessage (0 );
}
Return cwinthread: Run ();
}

Enter again F11:

Int cwinthread: Run ()
{
Assert_valid (this );

// For tracking the idle time state
Bool bidle = true;
Long lidlecount = 0;

// Acquire and dispatch messages until a wm_quit message is wrongly ed.
For (;;)
{
// Phase1: Check to see if we can do Idle Work
While (bidle &&! : Peekmessage (& m_msgcur, null, pm_noremove ))
{
// Call onidle while in bidle state
If (! Onidle (lidlecount ++ ))
Bidle = false; // assume "no idle" state
}

// Phase2: pump messages while available
Do
{
// Pump message, but quit on wm_quit
If (! Pumpmessage ())
Return exitinstance ();

// RESET "no idle" state after pumping "normal" Message
If (isidlemessage (& m_msgcur ))
{
Bidle = true;
Lelecount = 0;
}

} While (: peekmessage (& m_msgcur, null, pm_noremove ));
}

Assert (false); // not reachable
}

Bool cwinthread: isidlemessage (MSG * PMSG)
{
// Return false if the message just dispatched shold _ not _
// Cause onidle to be run. messages which do not usually
// Affect the state of the user interface and happen very
// Often are checked.

// Redundant wm_mousemove and wm_ncmousemove
If (PMSG-> message = wm_mousemove | PMSG-> message = wm_ncmousemove)
{
// Mouse move at same position as last mouse move?
If (m_ptcursorlast = PMSG-> PT & PMSG-> message = m_nmsglast)
Return false;

M_ptcursorlast = PMSG-> pt; // remember for next time
M_nmsglast = PMSG-> message;
Return true;
}

// Wm_paint and wm_#imer (caret blink)
Return PMSG-> message! = Wm_paint & PMSG-> message! = 0x0118;
}

This is the central mechanism for SDI to process messages, but note that it is not the core!

After analysis, a while loop occurs inside the infinite loop.

While (bidle &&
! : Peekmessage (& m_msgcur, null, pm_noremove ))
{
// Call onidle while in bidle state
If (! Onidle (lidlecount ++ ))
Bidle = false; // assume "no idle" state
}

This Code calls onidle to do some backup work when there is no message in the message queue of your program process. The temporary object is deleted here. Of course, it is a virtual function. Here, peekmessage is used to view the message queue. If a message is returned, true is returned. If no message is returned, false is returned, after the message is viewed, it does not remove the message that has just been viewed in the message queue. That is to say, the peekmessage serves only one detection function. Obviously, when false is returned, [no message] is returned. will enter the loop and execute onidle. Of course, if your onidle returns flase, the program will no longer execute onidle. You may want to ask:

Message Mechanism and drawing mechanism are inherent in Microsoft Windows and other products around it, and are the two main pillars and features of the Windows operating system as an operating system for internal implementation of the microcomputer, the message system is a channel for interaction and communication between all applications in windows, including windows, it is a solution for Windows to control any application running under it and the application responds to Windows. Therefore, for Windows Programming, no matter which language specification or IDE, message Processing is inevitable. Although some programming languages such as VB use the event-driven programming mechanism to encapsulate the complexity of messages to a large extent, to go deep into Win32 programming, you must learn the Windows message system. Just as game programming needs to control the Drawing Mechanism of win, as long as you have mastered these two pillars and basics, you have control over the fundamentals of Win32 programming ..
Messages are generated from system events (including timer events) and user events. In Windows, messages are used to call and close applications (for example, to draw a window, A typical manifestation is that during the shutdown operation, Windows sends a shutdown message to any running application and notifies them to exit the memory. At this time, the application responds to the OS by responding to messages. Therefore, messages are the means for applications to interact with winos ..
The message body is between applications and OS (this is a common saying, in fact, within an application, there is also a flow of messages between the "window" components. The window components and their parent and upper windows also have a message transmission process (such as "Command Transmission ", we will discuss it in detail later in tracking a message path). In Windows, the number of messages that flows in real time is so huge that manual analysis outside of program implementation is a very self-defeating task) the final body of a message is between the window and the window, and between the window and the OS. In the technical specifications of MFC, only the window process can send and receive a message and process it, of course, some non-interface window classes such as document classes can also process a message. The final destination of a message is a member function of a window class, that is, the function that enters the message processing function is processed, or a non-interface class, that is, the internal processing class, such as the document class, has a process for the default window class in the system and the window class registered by the user, you can create real window objects in the memory, receive and process window objects and window classes (10 million Note: receiving a message is a very different process from processing a message, later, we will talk about redirecting a message technology.) messages sent to him or from him to another window process or OS, modify the message processing process of the window process interference Window Process (instead of the receiving process, for detailed explanations of this distinction, refer to the following section from"
Note that the message pump is not .. "text) is possible (the window process is only a function), but if the window process belongs to someone else, such as the System window class, you will not modify the source process, however, it can interfere with the message reset technology, such as the user-defined window class. After the user completes the omnipotent ability to customize his window process, he can write his own message pump, to achieve message redirection, writing your own message pump is one of the seven major technologies for redirecting a message in Win32 programming.
There are seven techniques in MFC that can be used to redirect a message: 1, subcategory 2, super classification 3, on1_msg (), 4, setcapture5, write your own message pump, 6, setwindowshookex () is one of the hook functions that people often call.
After talking about the concept of message pump, We will track the path of a message in the system step by step before discussing its redirection.
The message pump is not a window process. Although they are all functions, they also work on messages injected into the window process, instead of processing the message itself (the reason mentioned above), the message pump is a popular saying, it is only related to the receiving work after the message is sent to the window process and not to the processing process (as mentioned above, message receiving and processing are two different processes ), on the contrary, the window process is only detailed in the following section about the non-reception mechanism ..
The message pump is included in the member function run () of the cwinapp ..

Windows Message Mechanism

The biggest feature of Windows is its graphical operation interface, which is based on its message processing mechanism. If you do not understand the WINDOWS Message Processing Mechanism, you cannot fully understand windows programming. It is a pity that many programmers only have heard about Windows messages, but do not know much about their usage or their internal implementation principles. This article attempts to disclose the Windows message mechanism that I understand step by step. It can be said that mastering this part of knowledge is a powerful weapon in Windows programming. Using it flexibly will greatly improve our programming capabilities.

1. Message Overview

How does a Windows form appear on the screen? As we all know, it is implemented through API plotting. The Windows operating system provides a series of API functions to draw the interface, such:

2. Draw text using drawtext

2. Draw a border using drawedge

2. drawicon

2. bitblt

2. rectangle: Draw a rectangle

2...

The complex program interface is implemented through this function.

So when will these functions be called? Obviously, we need a control center for "issuing orders". We also need a command communication mechanism to instantly deliver commands to the destination. This control center is a power source, like a heart, which continuously sends blood everywhere. This command transmission mechanism is a Windows message mechanism. A Windows message is like the blood in the body. It is the messenger of command communication.

Windows message control center is generally a three-tier structure with the Windows Kernel at the top. The Windows Kernel maintains a message queue. The second-level control center obtains messages under its jurisdiction from the message queue and then processes them. Some messages are directly processed, some of them also need to be sent to the next level form (window) or control ). The second-level control center is generally the application objects of various Windows applications. The third-level control center is a Windows form object. Each form has a default form process, which processes various received messages. As shown in:


(Note: Windows refers to the Windows operating system; Windows refers to Windows; forms: including windows and controls with handles; control refers to controls, which may also be a window, or not; application is an application, and the application may not use the Windows message mechanism. Here we will discuss the applications with message loops)

Figure 1 contains most of the content of the windows mechanism. All the content described below is actually an explanation or extension of the graph.

A message is sent to an application in a fixed structure. The structure is as follows:

Public type msg

Hwnd as long

Message as long

Wparam as long

Lparam as long

Time as long

Pt as pointapi

End type

Hwnd is the form handle, and message is a message constant used to indicate the type of the message. wparam and lparam are both 32-bit additional information, it depends on the message type. Time is the time when the message is sent, and PT is the cursor position when the message is sent.

Windows OS includes the following messages:

1. Standard Windows messages:

This type of message starts with WM.

2. Notification Message

Notification messages are messages for standard Windows controls. These controls include buttons, ComboBox, Textbox, ListBox, listview, Treeview, and toolbar), menu, etc. Each type of message starts with a different string.

3. Custom messages

Programmers can also customize messages.

Ii. Windows handle

Not every control can receive messages, forward messages, and draw itself. Only a control with a handle can do this. Controls with handles are essentially a window. They can exist independently and can be used as containers of other controls. controls without handles, such as labels, cannot exist independently, it can only be used as a child control of the window control. It cannot draw itself, but can only be drawn by the parent form.

The handle is essentially a 32-bit value automatically maintained by the system. This value is unique at any time of the operating system. However, after the form indicated by the handle is released, the handle is released, which may be used by other forms. That is to say, the value of the handle is dynamic, and it is only a unique identifier. The operating system uses the handle to identify and find the objects it represents.

However, not all handles are form handles. in windows, there are many other types of handles, such as the HDC handle, paint brush handle, and paint brush handle, application handle (hinstance. Such a handle cannot receive messages. No matter which handle is used, it is the unique identifier of an object in the system. This article only discusses the form handle.

So why does the handle make the window so unique? It is actually because of the message. With a handle, the form can receive messages, so it knows when to draw itself, draw the child control, and know when to click the part of the window, and then proceed accordingly. A handle is like a person's ID card. With it, You can engage in various social activities. Otherwise, you will either be a hacker invisible to the society or be behind others, prove your existence by others.

Iii. message transmission

1. Get a message from the message queue:

You can use the peekmessage or getmessage function to retrieve messages from the Windows message queue. Message Queues stored in windows are grouped by threads, that is, each thread has its own message queue.

2. Send messages

The following two functions are used to send messages to a specified form: sendmessage and postmessage. The difference between the two functions is that the postmessage function only adds a message to the thread message queue. if the message is successfully added, true is returned. Otherwise, false is returned, whether the message is processed, or whether the message is processed, I don't know. Sendmessage is somewhat different. Instead of adding a message to a queue, sendmessage directly translates the message and calls the message for processing until the message is processed. Therefore, if we want to send a message to be executed immediately, we should call sendmessage.

Another point is that because the message sent by sendmessage is not added to the message queue, the message sent by sendmessage cannot be obtained through peekmessage or getmessage.

In addition, some messages won't succeed with postmessage, such as wm_settext. Therefore, not all messages can use postmessage.

There are other message sending API functions, such as postthreadmessage, sendmessagecallback, sendmessagetimeout, and sendpolicymessage.

Iv. Message loop and Form Process

Message loops are the root cause for the persistence of applications. If the application exits cyclically, the application ends.

Let's take a look at the encapsulated message loop in Delphi:

Step 1: run the program)

Application. initialize; // Initialization

Application. createform (tform1, form1); // create the main form

Application. Run; // start running and prepare for message loop

If you do not create a main form, the application can also exist and run.

Step 2: Start to call the handlemessage)

Procedure tapplication. Run;

Begin

Frunning: = true;

Try

Addexitproc (doneapplication );

If fmainform <> nil then

Begin

Case cmdshow

Sw_showminnoactive: fmainform. fwindowstate: = wsminimized;

Sw_showmaximized: mainform. windowstate: = wsmaximized;

End;

If fshowmainform then

If fmainform. fwindowstate = wsminimized then

Minimize else

Fmainform. Visible: = true;

Repeat // note: the cycle starts.

Try

Handlemessage;

Except

Handleexception (Self );

End;

Until terminated; // The condition for loop end

End;

Finally

Frunning: = false;

End;

End;

Step 3: process messages in a message loop.

Procedure tapplication. handlemessage;

VaR

MSG: tmsg;

Begin

If not processmessage (MSG) Then idle (MSG );

End;

Function tapplication. processmessage (var msg: tmsg): Boolean;

VaR

Handled: Boolean;

Begin

Result: = false;

If peekmessage (MSG, 0, 0, 0, pm_remove) then

Begin

Result: = true;

If MSG. Message <> wm_quit then

Begin

Handled: = false;

If assigned (fonmessage) Then fonmessage (MSG, handled );

If not ishintmsg (MSG) and not handled and not ismdimsg (MSG) and

Not iskeymsg (MSG) and not isdlgmsg (MSG) then

Begin

Translatemessage (MSG );

Dispatchmessage (MSG );

End;

End

Else

Fterminate: = true;

End;

End;

The form process is actually a callback function. The so-called callback function is actually a function called by a Windows operating system or an external program. Callback functions generally have a specified parameter format, which is passed to the caller in address mode. The window is called by the Windows operating system. When creating a window, you need to input the callback function address when allocating the form handle. Why can't we see this callback function during programming? This is because our programming tool has generated a default form process for us. The only thing we need to do in this process is to judge different message types and then make different processing. For example, an event can be generated for keyboard or mouse input.

5. Messages and events

Events are essentially message encapsulation and are a useful tool provided by the IDE programming environment to simplify programming. This encapsulation is implemented in the form process. Each ide encapsulates many Windows messages, such:

Event

Message

Onactivate

Wm_activate

Onclick

Wm_xbuttondown

Oncreate

Wm_create

Ondblclick

Wm_xbuttondblclick

Onkeydown

Wm_keydown

Onkeypress

Wm_char

Onkeyup

Win_keyup

Onpaint

Wm_paint

Onresize

Wm_size

Ontimer

Wm_timer

After understanding this, We can encapsulate our own events.

Based on the above introduction, I believe you have understood the Windows message mechanism. Through message programming in windows, we can not only implement many common functions, but also implement functions not provided by many ide class libraries. In addition, we can intercept messages through message hooks, change its default processing functions to break through the restrictions of platform or software functions and greatly extend the functions of the program. We can also modify the default form process to respond to messages as required; or customize messages to implement instant communication between programs. Through more in-depth study, we will also be exposed to more basic Windows-related information about the windows messaging mechanism, you will find yourself not far from the "master.

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.