I. Overview of the message
The execution of applications under Windows is message-driven. The message is the entire application's working engine, and we need to understand how the programming language we use encapsulates the message.
1. What are messages (message)
Messages are notifications and commands. In the System.Windows.Forms namespace in the. NET Framework class library, Microsoft redefined the message in a way that faces the object. The public part property of the new message structure is basically the same as the earlier one, but it is facing the object.
Public properties:
p Ublic IntPtr HWnd {get; set;} |
Gets or sets the window handle of the message |
public int Msg {get; set;} |
Gets or sets the ID number of the message |
public IntPtr Result {get; set;} |
Specifies the value returned to Windows for Response message processing |
public IntPtr LParam {get; set;} |
Specifies the System.Windows.Forms.Message.LParam field of the message |
public IntPtr WParam {get; set;} |
Gets or sets the System.Windows.Forms.Message.WParam field of the message |
2. Message-driven processes
All external events, such as keyboard input, mouse movement, and mouse clicks, are converted by the OS system to the corresponding message queue that is sent to the application. Each application has a corresponding program code to retrieve, distribute, and process the message to the corresponding form, which is then handled by the form's handler function.
Ii. encapsulation of messages in C #
C # re-encapsulates the message in the face of the object, and in C # The message is encapsulated as an event. The System.Windows.Forms.Application class has methods for starting and stopping applications and threads, and for processing Windows messages.
Call run to start the application message loop on the current thread, and optionally make its form visible.
Call exit or ExitThread to stop the message loop.
C # uses the application class to handle receiving and sending messages. The loop of the message is responsible for it.
Essentially, each form typically corresponds to a form procedure handler function. So, how does a C # form instance (the equivalent of a form) handle a message after it receives a message? In fact, the analysis of this problem shows the message encapsulation principle of C #.
To implement the response of the left mouse button press message (WM_LBUTTONDOWN)
Class Form1:form
{
Public Form1 ()
{
InitializeComponent ();
New System.Windows.Forms.MouseEventHandler (This. FORM1_MOUSEDOWN1);
New System.Windows.Forms.MouseEventHandler (This. FORM1_MOUSEDOWN2);
}
void Form1_mousedown1 (object sender, System.Windows.Forms.MouseEventArgs e)
{
if (E.button = = System.Windows.Forms.MouseButtons.Left)
System.Windows.Forms.MessageBox.Show ("message is FORM1_MOUSEDOWN1 function response");
}
void Form1_mousedown2 (object sender, System.Windows.Forms.MouseEventArgs e)
{
if (E.button = = System.Windows.Forms.MouseButtons.Left)
System.Windows.Forms.MessageBox.Show ("message is FORM1_MOUSEDOWN2 function response");
}
}
Above this. MouseDown is an event in C #. It is defined as follows:
//
Summary:
occurs when the mouse pointer is over the control and the mouse button is pressed.
Event MouseEventHandler MouseDown;
Summary:
represents a method that will handle the MouseDown, MouseUp, or MouseMove events of a form, control, or other component.
//
Parameters:
Sender:
The event source.
//
e:
the System.Windows.Forms.MouseEventArgs that contains the event data.
void MouseEventHandler (object sender, MouseEventArgs e);
In fact, a delegate type of MouseEventHandler is defined above. A solution is delegated that enables function pointers in other programming languages. Unlike the C + + function pointers, delegates are fully object-oriented and encapsulate object instances and methods. Essentially, a delegate encapsulates an instance and a method function on that instance into a callable entity, which is secure for the object.
We can put this. MouseDown + = new System.Windows.Forms.MouseEventHandler (this. FORM1_MOUSEDOWN1); This statement is considered to this. MouseDown adds a function pointer.
An event is a message sent by an object to signal the occurrence of a notification operation. The object that raises (triggers) the event is called the event sender. The object that captures the event and responds to the event is called the event receiver. In event traffic, the event sender class does not know which object or method will receive (process) the event it raises. What is needed is a medium (a pointer-like mechanism) between the sender and the receiver. The NET Framework defines a special type (delegate delegate) that provides the function of a function pointer. Thus, the delegate is equivalent to a type-safe function pointer or a callback function.
In front of us to this. The MouseDown event added two delegates.
This. MouseDown + = new System.Windows.Forms.MouseEventHandler (this. FORM1_MOUSEDOWN1);
This. MouseDown + = new System.Windows.Forms.MouseEventHandler (this. FORM1_MOUSEDOWN2);
As a result, our two functions, FORM1_MOUSEDOWN1, FORM1_MOUSEDOWN2, are called when we click the left mouse button, and the order of the calls is the same as the order in which we added the delegates.
The WM_LBUTTONDOWN message is first taken out of the application message queue by the application class and then distributed to the appropriate form. The form uses the function pointer in the MouseDown event to invoke the response function that has been added. Therefore, the event field in C # is essentially a list of function pointers to maintain the address of some response functions when a message arrives.
Iii. Conclusion
Workflow for messages in C #:
Messages in C # are removed from the application message queue by the application class and then distributed to the corresponding form of the message, and the first response function of the form object is the protected override void WndProc in the object (ref System.Windows.Forms.Message e) method.
It then invokes the default message response function (such as onmousedown) based on the type of message, and the default response function is then based on the object's event field (such as this. MouseDown) a list of function pointers in a call to the user's joined response functions (such as FORM1_MOUSEDOWN1 and FORM1_MOUSEDOWN2), and the order of invocation is consistent with the user addition sequence.
Four, again looking back application class
The application class has a static method of Addmessagefilter, through which we can add message filters to view these messages when a Windows message is passed to the destination. Use message filters to prevent specific events from being raised, or to use message filters to perform special operations on an event before it is passed to an event handler. We must provide an implementation of the IMessageFilter interface before the message filter can be used. The following sample code demonstrates how we intercept a message before it is sent to the form. We intercepted the same wm_lbuttondown message.
Using System;
Using System.Collections.Generic;
Using System.ComponentModel;
Using System.Data;
Using System.Drawing;
Using System.Linq;
Using System.Text;
Using System.Windows.Forms;
Using System.Threading;
Namespace WindowsFormsApplication1
{
<summary>
Implementing the Message Filter interface
</summary>
Class Clbuttondownfilter:imessagefilter
{
BOOL Prefiltermessage (ref Message m)
{
Wm_lbuttondown
{
System.Windows.Forms.MessageBox.Show ("left mouse button pressed" in the app);
A return value of TRUE indicates that the message has been processed and not passed back, so the message is intercepted
The return value is False, indicating that the message was not processed and needed to be passed back so that the message was not intercepted
True
}
False
}
}
Class Form1:form
{
Public Form1 ()
{
InitializeComponent ();
Installing custom message Filters
New Clbuttondownfilter ();
Application.addmessagefilter (Myfilter);
New System.Windows.Forms.MouseEventHandler (This. FORM1_MOUSEDOWN1);
New System.Windows.Forms.MouseEventHandler (This. FORM1_MOUSEDOWN2);
}
void Form1_mousedown1 (object sender, System.Windows.Forms.MouseEventArgs e)
{
if (E.button = = System.Windows.Forms.MouseButtons.Left)
System.Windows.Forms.MessageBox.Show ("message is FORM1_MOUSEDOWN1 function response");
}
void Form1_mousedown2 (object sender, System.Windows.Forms.MouseEventArgs e)
{
if (E.button = = System.Windows.Forms.MouseButtons.Left)
System.Windows.Forms.MessageBox.Show ("message is FORM1_MOUSEDOWN2 function response");
}
<summary>
Intercepting messages by overriding the form function of the base class
</summary>
<param name= "E" ></param>
void WndProc (ref System.Windows.Forms.Message E)
{
If you need to intercept a message,
if (e.msg==0x0201)//Wm_lbuttondown
System.Windows.Forms.MessageBox.Show ("message is WndProc function response");
Else
Base. WndProc (ref e);
does not need to intercept the message;
if (e.msg = = 0x0201)//Wm_lbuttondown
System.Windows.Forms.MessageBox.Show ("message is WndProc function response");
Base. WndProc (ref e);
}
<summary>
Raising a function to intercept a message by overriding the base class's event
</summary>
<param name= "E" ></param>
void OnMouseDown (MouseEventArgs e)
{
if (E.button = = System.Windows.Forms.MouseButtons.Left)
System.Windows.Forms.MessageBox.Show ("message is onmousedown function response");
If you need to intercept a message, you can base it. OnMouseDown (e); statement comment out
Base. OnMouseDown (e);
}
}
}
The above code we first implemented the IMessageFilter interface with Class Clbuttondownfilter, and we installed the message filter when the WinForm was initialized. When the program is actually executed, when the left mouse button is clicked, the program simply pops up a message box with the left mouse button pressed in the app. Because we intercepted the message before it was sent to the form, the form will not receive the WM_LBUTTONDOWN message.
If we change this code block to return False,
Then, after we have processed the message in the application class, the message continues to be sent to the form. The function of the form will be able to handle this message. The program execution effect is a sequential pop-up of 5 message boxes.
1:<<app left mouse button pressed >>
2:<< message is WndProc function response >>
3:<< message is onmousedown function response >>
4:<< message is form1_mousedown1 function response >>
5:<< message is FORM1_MOUSEDOWN2 function response >>
In fact, this article has been described in quite detailed. The popup dialog is just for you to see the resulting results more intuitively.
C # Message processing mechanism and custom filtering methods