DefWndProc/WndProc/IMessageFilter的区别
談到Winform的消息處理,多數時候是通過事件處理程序進行的,但當沒有對應的事件時通常的做法是聲明DefWndProc或者WndProc或者IMessageFilter,經常在網上看見有文章將三者并列,那么它們有什么區別呢?
DefWndProc和WndProc都是繼承自Control類中的虛方法,原型如下:
1: protected override void DefWndProc(ref Message m) 2: { 3: .... 4: base.DefWndProc(m); 5: } 6: ? 7: protected override void WndProc(ref Message m); 8: { 9: ..... 10: base.WndProc(m); 11: }所有的有用戶界面的控件都繼承自Control,這種方式需要創建對應控件的派生類,不能統一對各個窗口的消息進行攔截處理,因為從根本上說這兩者都是Windows的窗口過程,只有收到針對本窗口自身的消息。
通過復習Windows的消息處理機制,對這三者的關系可以有更好的理解。應用程序的消息來自于系統消息隊列,被應用程序的主程序中的消息循環所處理。這個消息循環從應用程序的消息隊列中取出消息,進行預處理,然后派發到消息對應的窗口過程,窗口過程在被調用后根據消息的類型進行相應的處理,有些可以由Windows默認處理的消息就調用Windows的DefWindowProc。
這里的WndProc就是對應控件窗口的窗口過程,而DefWndProc會被WndProc調用,處理那些WndProc中未處理的消息(包括WndProc未吞掉的),因此DefWndProc收到的消息會比WndProc少。
IMessageFilter的調用發生在應用程序的消息循環中,是消息預處理的一部分,所以它收到的消息是更全的(除了直接發送到窗口過程不進入消息隊列的那些消息)。使用方式如下:
1: public class MessageFilter : IMessageFilter 2: { 3: public bool PreFilterMessage(ref Message msg) 4: { 5: //識別消息并處理 6: //return true;//吞掉消息,不派發 7: return false;//進入下一步派發到對應窗口過程 8: } 9: } 10: ? 11: //在應用程序消息循環中加入消息過濾器 12: MessageFilter f = new MessageFilter(this.lbMsg); 13: Application.AddMessageFilter(f); 14: ?三者都有一個共同的參數類型Message,它封裝了Windows消息。同時還包括一個很方便的ToString方法,可以將Message對象轉換成包括消息名稱(WM_XXX)在內的字符串,通過Reflector可以看到實現是通過一個內部類MessageDecoder,使用一個很長的switch語句將消息ID轉換成消息名稱。
Message的定義如下:
1: [StructLayout(LayoutKind.Sequential), SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 2: public struct Message 3: { 4: private IntPtr hWnd; 5: private int msg; 6: private IntPtr wparam; 7: private IntPtr lparam; 8: private IntPtr result; 9: public IntPtr HWnd { get; set; } 10: public int Msg { get; set; } 11: public IntPtr WParam { get; set; } 12: public IntPtr LParam { get; set; } 13: public IntPtr Result { get; set; } 14: public object GetLParam(Type cls); 15: public static Message Create(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam); 16: public override bool Equals(object o); 17: public static bool operator !=(Message a, Message b); 18: public static bool operator ==(Message a, Message b); 19: public override int GetHashCode(); 20: public override string ToString(); 21: } 22: ?其中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的輸出窗口監視到的調試輸出: P.S.腦子里一直想著好像還有種定義消息處理過程的方式,而且是可以直接指定處理哪個消息,好像使用的關鍵字是“message”。。。 在MSDN上搜索N久后反應過來,哦,好象是Delphi中的方法;-) 原文地址:http://ymail2000.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&_c=BlogPart&partqs=cat%3dWinform轉載于:https://www.cnblogs.com/08shiyan/archive/2012/01/06/2313864.html
總結
以上是生活随笔為你收集整理的DefWndProc/WndProc/IMessageFilter的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大别山区域医疗中心暨市中心医院(二期)项
- 下一篇: 中金汇财是什么