最近几天做项目的时候,遇到了一个截取窗口消息的问题,从网上搜了一些资料后,也有了些自己的理解,随后又忽然想起了Winform的事件模型。于是便写下来与大家分享。

 
首先,我们先回忆一下VC++的Windows编程。我不说细节,只说大概的交互过程。比如窗口上有一个按钮,当我们单机这个按钮的时候,操作系统会向应用程序发一个鼠标单击的消息,当按钮这个对象捕捉到这个消息的时候,就会进行相应的处理。操作系统中定义了非常多的消息关于操作系统消息的知识,请参见 http://bbs.cfan.com.cn/thread-555997-1-1.html   。
 
下面,介绍一下在 .net 环境下如果截取窗口消息。
首先,新建一个Winform应用程序,在Form1.cs中,加入下列代码

//截取消息,进行处理 
protected override void WndProc(ref Message m) 
{
  switch(m.Msg)
  {
    case 17:
      MessageBox.Show("哈哈,你不能关闭计算机!");
      m.Result=(IntPtr)0;
      break;
    case 513:
      MessageBox.Show("哈哈,你不能点击左键!"); 
      m.Result=(IntPtr)0;
      break;
    case 516:
      MessageBox.Show("哈哈,你不能点击右键!"); 
      m.Result=(IntPtr)0;
      break;
    default:
      base.WndProc(ref m);
      break;
  }

其中,WndProc方法是Form类中的方法(其实,它是Control类中定义的虚方法,在Form类中给出了实现)

它的作用是接收来自操作系统的消息,然后进行相应的处理。

我们复写了它,就可以优先以我们的方式来获取窗口消息。但是,不能忘记调用base.WndProc(ref m),否则,程序出错的可能性比较大。

 

下面,我们说一下事件模型。

我相信有一大批入门级的程序员,包括我之前在内,都会WinForm的事件模型特别好奇,因为的确微软把他封装的非常好,非常简单,双击控件触发一个事件,然后再在自动生成的代码中写逻辑。现在我们来想一想,这是怎么实现的呢?为什么你单机一下按钮,对应的按钮事件的逻辑就会执行呢?也许你会说,因为有这一句代码,

this.button1.Click += new System.EventHandler(this.button1_Click);

不错,这句代码是注册了一个Click事件,但是,事件也是需要调用的啊,那么,到底是谁,在什么时候调用的呢?我本人的感觉,应该是Form对象在截取窗口消息的时候,如果捕获到了某消息,就会查看是否注册了与该消息对应的事件,如果该事件被注册了,那么,就会调用该事件的对象来执行委托链。