WinForm中DefWndProc、WndProc与IMessageFilter的区别

摘要:
Windows消息传递系统由三部分组成:1.消息队列。Windows应用程序的消息由Windows在统一的消息队列中管理。一般来说,Winform的消息处理机制大多通过事件处理程序实现,但当没有相应的事件时,通常的做法是声明DefWndProc或WndProc或IMessageFilter。我经常在网上看到文章将这三者并列,那么它们之间有什么区别呢?这里,WndProc是相应控制窗口的窗口过程,WndProc将调用DefWndProc,以处理WndProc中未处理的消息,因此DefWndProc将接收比WndProc更少的消息。

Windows消息系统由3部分组成:

    1.消息队列。Windows应用程序的消息是由Windows统一在一个消息队列中管理的。
    2.消息循环。应用程序从Windows消息队列中获得自己的消息,并将其分配给窗口过程进行处理。
    3.窗口过程。负责处理接收到的消息,每个窗口都有对应的窗口过程,负责截获消息并响应。WndProc是窗口过程函数,负责处理接收到的消息,在我们写代码时,不会注意到有这个函数,这是因为开发环境自动为我们生成了。WndProc函数通过switch...case...判断并处理消息,对于在case中没有遇到的情况,会调用DefWndProc函数进行处理,所以,在C#中用户自定义消息,可以重载DefWndProc函数使用switch...case...判断并处理。
    C#中的事件就是对Windows消息的封装,窗口过程中定义了窗体的事件,一定程度就是为了让程序员避免过多的考虑消息等底层的东西,所以能避免消息机制解决的问题最好能避免。
 

一般来说,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);

免责声明:文章转载自《WinForm中DefWndProc、WndProc与IMessageFilter的区别》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇家谱树(信息学奥赛一本通 1351)金盾视频加密器V2014视频加密原理分析下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

c# Winform PropertyGrid 实现下拉框 多选

1 usingPropertyGridHelpers.Controls; 2 usingSystem; 3 usingSystem.Collections.Generic; 4 usingSystem.ComponentModel; 5 usingSystem.Drawing.Design; 6 usingSystem.Windows.Forms;...

window.open()不同源页面通信

父页面 运行端口:8080 <template> <div> <el-button @click="open()">发送消息给子页面</el-button> </div> </template> <script> export default{ na...

uni-app 基本配置pages,json

{ // 打开页面的路径 "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages // 在第一位的事默认打开的页面 { "path": "pages/message/messa...

WinForm控件之【PictureBox】

基本介绍 图片控件,用于显示各种格式图像。 常设置属性 Image:在控件中显示的图像,绑定需要显示的Image类型对象; ErrorImage:当加载图像失败时显示的图像对象; InitialImage:正在加载另一图像时显示的图像对象; SizeMode:控件如何展示图片的类型; Enabled:指示是否启用该控件,true为启用状态用户可编辑,fal...

SAP系统中发送公告的几种办法

      刚刚在闪存里看到朋友在闪存里提到:如何在SAP系统发送公告的T-CODE,觉得今后可能会用到,所以顺便在网上搜索了一下相关资料。由于时间关系,太晚了,得休息了,在此我就不再一个个抠图了,直接借用一下别人的文章,将此方法记录了下来,希望今后有用得到的地方……     1、SM02创建消息,并设定有效期。当用户刷新窗口或打开窗口时会显示。这个消息对...

在HTTP通讯过程中,是客户端还是服务端主动断开连接?

比如说:IE访问IIS,获取文件,肯定是要建立一个连接,这个连接在完成通讯后,是客户端Close了连接,还是服务端Close了连接。我用程序测模拟IE和IIS,都没有收到断开连接的消息,也就是都没有触发OnClose事件。我是用Socket建立的连接。如果两方面都没有主动断开连接,那么我猜测可能是传输的数据中有结束的标志,请问这个标志是怎样的?谢谢各位。...