这个消息循环从应用程序的消息队列中取出消息

时间:2022-04-03 08:39:41

一般来说,Winform的动静措置惩罚惩罚机制大都时候是通过事件措置惩罚惩罚措施进行的,但当没有对应的事件时凡是的做法是声明DefWndProc或者WndProc或者IMessageFilter,经常在网上看见有文章将三者并列,那么它们有什么区别呢?本文对此做一简单分析如下:

DefWndProc和WndProc都是担任自Control类中的虚要领,其原型如下:

protected override void DefWndProc(ref Message m) { .... base.DefWndProc(m); } protected override void WndProc(ref Message m); { ..... base.WndProc(m); }

所有的有用户界面的控件都担任自Control,这种方法需要创建对应控件的派生类,不能统一对各个窗口的动静进行拦截措置惩罚惩罚,因为从根柢上说这两者都是Windows的窗口过程,只有收到针对本窗口自身的动静。

通过温习Windows的动静措置惩罚惩罚机制,对这三者的关系可以有更好的理解。

应用措施的动静来自于系统动静行列队伍,被应用措施的主措施中的动静循环所措置惩罚惩罚。这个动静循环从应用措施的动静行列队伍中取出动静,进行预措置惩罚惩罚,然后派发到动静对应的窗口过程,窗口过程在被挪用后按照动静的类型进行相应的措置惩罚惩罚,有些可以由Windows默认措置惩罚惩罚的动静就挪用Windows的DefWindowProc


这里的WndProc就是对应控件窗口的窗口过程,而DefWndProc会被WndProc挪用,措置惩罚惩罚那些WndProc中未措置惩罚惩罚的动静(包孕WndProc未吞失的),因此DefWndProc收到的动静会比WndProc少。


IMessageFilter的挪用产生在应用措施的动静循环中,是动静预措置惩罚惩罚的一部分,所以它收到的动静是更全的(除了直接发送到窗口过程不进入动静行列队伍的那些动静)。

使用方法如下:

public class MessageFilter : IMessageFilter { public bool PreFilterMessage(ref Message msg) { //识别动静并措置惩罚惩罚 //return true;//吞失动静,不派发 return false;//进入下一步派发到对应窗口过程 } } //在应用措施动静循环中插手动静过滤器 MessageFilter f = new MessageFilter(this.lbMsg); Application.AddMessageFilter(f);

三者都有一个配合的参数类型Message,它封装了Windows动静。同时还包孕一个很便利的ToString要领,,可以将Message东西转换成包孕动静名称(WM_XXX)在内的字符串,通过Reflector可以看到实现是通过一个内部类MessageDecoder,使用一个很长的switch语句将动静ID转换成动静名称。

Message的界说如下:

[StructLayout(LayoutKind.Sequential), SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public struct Message { private IntPtr hWnd; private int msg; private IntPtr wparam; private IntPtr lparam; private IntPtr result; public IntPtr HWnd { get; set; } public int Msg { get; set; } public IntPtr WParam { get; set; } public IntPtr LParam { get; set; } public IntPtr Result { get; set; } public object GetLParam(Type cls); public static Message Create(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam); public override bool Equals(object o); public static bool operator !=(Message a, Message b); public static bool operator ==(Message a, Message b); public override int GetHashCode(); public override string ToString(); }

此中hWnd是动静对应的窗口句柄,按照上面的分析可以知道在窗口过程(DefWndProc,WndProc)中收到的窗口句柄都是该窗口的句柄,而在PreFilterMessage中收到的动静的窗口句柄则按照触动员静的窗口差别而差别。

在PreFilterMessage中收到动静时,可以使用Control.FromHandle得到窗口对应的控件东西,原型如下:

//Declaring Type: System.Windows.Forms.Control //Assembly: System.Windows.Forms, Version=2.0.0.0 public static Control FromHandle(IntPtr handle);通过这种方法可以监测各动静的信息来自哪个控件。 public bool PreFilterMessage(ref Message msg) { Control c = Control.FromHandle(msg.HWnd); if (c == null) System.Diagnostics.Debug.WriteLine("Filter:NULL" +"-" + msg.ToString()); else System.Diagnostics.Debug.WriteLine("Filter:" +c.Name+"-"+ msg.ToString()); return false; }

从Visual Studio的输出窗口监视到的调试输出如下图所示:

这个消息循环从应用程序的消息队列中取出消息