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
DefWndProc/WndProc/IMessageFilter的区别的更多相关文章
- WinForm中DefWndProc、WndProc与IMessageFilter的区别
这篇文章主要介绍了WinForm中DefWndProc.WndProc与IMessageFilter的区别,较为详细的分析了WinForm的消息处理机制,需要的朋友可以参考下 一般来说,Win ...
- WndProc和hook区别
1)WndProc函数作用:主要在程序中拦截并处理系统消息和自定义消息 比如:windows程序会产生很多消息,比如你单击鼠标,移动窗口都会产生消息.这个函数就是默认的消息处理函数.你可以重载这个函数 ...
- 结合windows消息系统理解C#中WndProc函数和DefWndProc函数
Windows消息系统由3部分组成: 1.消息队列.Windows应用程序的消息是由Windows统一在一个消息队列中管理的. 2.消息循环.应用程序从Windows消息队列中获得自己 ...
- C# 重写WndProc 拦截 发送 系统消息 + windows消息常量值
接收拦截+发送消息 对于处理所有消息.net 提供了wndproc进行重写 WndProc(ref Message m)protected override void WndProc(ref Mess ...
- C# 重写WndProc
重写WndProc方法来处理 Windows 消息 处理 Windows 消息. 在开发winForm时,常常要处理Windows消息,可以重写WndProc来实现.常见代码如下: using Sys ...
- What exactly is the difference between WndProc and DefaultWndProc?
Control.DefWndProc Sends the specified message to the default window procedure. 参数说明:m:The Windows M ...
- c#委托与事件、消息、WndProc用法(转)
c#委托与事件 心得 c#用委托来实现事件通知机制.委托相当与c++函数指针.整个过程涉及一个呼叫者,一个被呼叫者,还有就是这个委托. - 实现步骤有以下几步: 1. 申明委托, 2.定义呼叫者和调用 ...
- 【C++】DDX_Control、SubclassWindow和SubclassDlgItem的区别
在自绘窗口的时候,子类化是MFC最常用的窗体技术之一.什么是子类化?窗口子类化就是创建一个新的窗口函数代替原来的窗口函数. Subclass(子类化)是MFC中最常用的窗体技术之一.子类化完成两个工作 ...
- (转)KeyDown、KeyUp、KeyPress区别
Windows窗体通过引发键盘事件来处理键盘输入以响应Windows消息,大多数Windows窗体应用程序都通过处理键盘事件来以独占方式处理键盘输入. 1.按键的类型 Windows窗体将键盘输入标 ...
随机推荐
- shockwave flash has crashed(Flash 插件崩溃导致页面中的flash不显示)怎么办
1.原理: 应该电脑里最近装了chorme或者基于chorme内核的浏览器.越来越多的人开始使用chrome的浏览器,很多用户都遇到过flash崩溃的问题,有时候重启chrome可以解决,有时候会导致 ...
- [转] 判断html页是否滚动停止
原文链接:http://www.phpernote.com/javascript-function/754.html 最近有个项目中遇到这样一个问题: 有一个用于展示数据的带滚动条的DIV块,业务需求 ...
- Java RGB数组图像合成 ImageCombining (整理)
/** * Java RGB数组图像合成 ImageCombinning (整理) * * 2016-1-2 深圳 南山平山村 曾剑锋 * * 注意事项: * 1.本程序为java程序,同时感谢您花费 ...
- 【Android】SDK工具学习 - Traceview 和 dmtracedump
dmtracedump官方文档 Traceview 根据程序的log,形成图形 dmtracedump [-ho] [-s sortable] [-d trace-base-name] [-g out ...
- 警惕VPS服务商常用的超售手段
任何商业企业都希望将利益最大化,这是可以理解的.但如果做的过火最终损害的还是自己的利益.VPS服务提供商也一样,为了将利益最大化,他们往往会实用技术手段对所出售的VPS进行“超售”. 那么何谓“超售” ...
- 关于RF 315MHz
1.https://www.pjrc.com/teensy/td_libs_VirtualWire.html These modules worked very reliably when sitti ...
- Java正确转换html编码
Java 中能將 html 編碼正確轉換的套件: org.apache.commons.lang.StringEscapeUtils. String source = "The less t ...
- Android 中像素px和dp的转化
在Android的布局文件中,往往使用dp作为控件的宽度和高度尺寸,但是在Java代码中,调用getWidth()方法获得的尺寸单位却是像素px,这两个单位有明显的区别:dp和屏幕的密度有关,而px与 ...
- border透明
最近在写一表项目,需要边框透明,起初我以为没有办法实现,最近看一本书中找到办法,就是通过rgba实现,代码如下: border: 1px solid rgba(0, 0, 0, 0.7); 关于rgb ...
- C++11 现代C++风格的新元素--简介
C++11标准推出了很多有用的新特性,本文特别关注那些相比C++98更像是一门新语言的特性,理由是: 这些特性改变了编写C++程序使用的代码风格和习语[译注 1],通常也包括你设计C++函数库的方式. ...