C# 复习笔记 消息与事件处理

C# 复习笔记 消息与事件处理

学习Windows编程后,有时候需要对系统消息或者事件做出自己的响应或者说自己拦截一些消息,实现某个事件或者函数的触发,这时就需要对系统消息进行处理.
大多数直接开始学习C#没有对C++有太多了解的猿们(包括我在内),都不太了解消息机制,还是看看百度百科的解释吧:百度百科对Windows消息机制的解释
简单的说,我个人理解,Windows是建立在消息机制上的.消息机制大致就是,Windows内核维护了一个消息列队,消息则是通过外部或者系统程序产生的一系列动作,比如鼠标点了窗体,而这些消息进入了消息队列,系统将不同的消息派发给不同的程序,程序会对消息进行处理,就是窗体过程,有些消息需要回调给系统,有些则不需要,取决于发送消息的方法.而C#的事件则是对消息的进一步封装.理解不太透彻,可以研究这篇博http://www.cnblogs.com/skyofbitbit/p/3649104.html 讲得很透彻

现在说一下C#中对消息的操作:
方法一,实现IMessageFilter接口来获取消息.IMessageFilter接口用来定义消息筛选器接口,该接口的PreFilterMessage方法用来在调度消息之前将其筛选出来。可以在VS中的对象浏览器看到.
他的实现如下:

namespace MessageDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Application.AddMessageFilter(new msgFilter());
        }
    }

    public class msgFilter:IMessageFilter
    {
        public bool PreFilterMessage(ref Message m)
        {
            switch (m.Msg)
            {
                case 0x201:
                    MessageBox.Show("Left Click");
                    return true;
                case 0x205:
                    MessageBox.Show("Right Click");
                    return true;
                default:
                    return false;
            }
        }
    }
}

程序中继承了接口IMessageFilter并实现了PreFilterMessage方法.获得了该窗口句柄了消息,实现了对消息的截取.

方法二 使用Control类的虚方法WndProc来截取Windows消息,基类为Control类的所有控件都有一个protected virtual void WndProc(ref Message m) 的虚方法。只要重载该虚方法,那么这个控件聚焦后就可以扑捉windows消息,并触发该方法了

namespace MessageDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        protected override void WndProc(ref Message m)
        {
           switch (m.Msg)
           {
               case 0x201:
                   MessageBox.Show("Left Click");
                   break;
               case 0x205:
                   MessageBox.Show("Right Click");
                   break;
               default:
                   break;
           }
            base.WndProc(ref m);
        }
    }
}

方法三 通过重载C#事件实现:

namespace MessageDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            switch (e.Button)
            {
                case MouseButtons.Left:
                    MessageBox.Show("Left Click");
                    break;
                case MouseButtons.Right:
                    MessageBox.Show("Right Click");
                    break;
                default:
                    break;
            }
            base.OnMouseDown(e);
        }
    }
}

以上三种方法都实现了对windows消息的截获,但是方法一和方法二可以认为是原生的消息机制的处理方法,而方法三则是C#封装了之后的消息,就是事件来变像实现对消息的截获.方法一二可以实现自定义消息的截获而方法三不行,但是方法三更简单,不需去查询系统的消息ID,而且不需要自己去实现,我认为可以减少bug的存在…

最后自定义消息的收发:
这段程序实现了,button1按下后,通过系统API发送了一个自定义的消息,并自己接收.

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        public const int myMessage = 0x0400;//自定义消息ID,注意不要和系统消息冲突

        [DllImport("user32.dll")]
        public static extern void PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);

        public Form1()
        {
            InitializeComponent();
        }

        private void GetMessage()
        {
            MessageBox.Show("Got Message From Myself");
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case myMessage:
                    GetMessage();
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            PostMessage(this.Handle, myMessage, 168, 51898);
            Thread.Sleep(2000);
        }
    }
}

系统API除了PostMessage,还有SendMessage,上面的博中已经有了,就不多说了.
最后需要说一句,一定在自己接收了消息后,一定要我们重载基类的方法,要不然,消息就到程序这就不会再继续转发(除非这是自定义消息),又是一个坑,不要跳哟….
大致就这样,有错的请大神指正.

你可能感兴趣的:(桌面应用)