国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

WinForm中DefWndProc、WndProc與IMessageFilter的區別

2020-01-24 02:28:15
字體:
來源:轉載
供稿:網友

一般來說,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的輸出窗口監視到的調試輸出如下圖所示:

希望本文所述分析對大家深入理解WinForm的消息處理機制有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 怀化市| 滦平县| 普陀区| 海淀区| 翼城县| 普兰县| 万宁市| 新河县| 古交市| 施秉县| 涿鹿县| 依兰县| 泰安市| 盐津县| 璧山县| 炎陵县| 东乡县| 沿河| 灵武市| 宜州市| 搜索| 常州市| 丰都县| 石阡县| 故城县| 大石桥市| 渝北区| 武功县| 雷山县| 蓝山县| 阳谷县| 远安县| 邓州市| 鄂托克旗| 乌恰县| 瓦房店市| 灌南县| 东莞市| 卓尼县| 右玉县| 聊城市|