现在的位置: 首页 > 综合 > 正文

Winform中在Form上截取消息的两种方法比较

2018年04月05日 ⁄ 综合 ⁄ 共 3072字 ⁄ 字号 评论关闭

比较常用的是重载Form的DefWndProc方法,例如截取鼠标按下的消息:

protected override void DefWndProc(ref Message m)
        
{
            
if ( m.Msg ==  0x0201 )
            
{
                MessageBox.Show(m.Msg.ToString());
            }

            
else
            
{
                
base.DefWndProc (ref m);
            }

        }

还可以通过另一种办法,使用IMessageFilter 接口:

public class MessageFilter : IMessageFilter 
    {
                
public bool PreFilterMessage(ref Message m) 
               {
                        
if (m.Msg == 0x0201
                       {
                                MessageBox.Show(
"WM_LBUTTONDOWN is: " + m.Msg);
                              
return true;
                       }
                      
return false;
        }

    }

然后使用Application.AddMessageFilter方法,例如:
private static MessageFilter msgFliter = new MessageFilter();
在Main方法中注册消息筛选器:
Application.AddMessageFilter(msgFliter);
如果要取消注册,可以调用Application.RemoveMessageFilter方法

 

实际上我们简单的区分这两者的不同:

 

DefWndProc : (From MSDN)

通常,仅在截获窗口消息并需要默认窗口过程来处理该消息时,才调用 DefWndProc 方法。不应调用 DefWndProc 将窗口消息发送到窗口,而应调用 Win32 SendMessage 函数。

Handle 属性为 0 时,调用 DefWndProc 是错误的。

给继承者的说明 在派生类中重写此方法可实现特定本机窗口或 .NET Windows 窗体 Control 的通用自定义消息处理。可以在调用此方法的基类实现(执行标准消息处理)之前或之后执行自定义处理,也可以使用自定义处理而不调用此方法的基类实现。 为应用程序添加自定义消息处理则可以通过 Application 类的 AddMessageFilter 方法来实现。

 

Application.AddMessageFilter() : (From MSDN)

使用消息筛选器来防止引发特定事件,或在将某事件传递给事件处理程序之前使用消息筛选器对其执行特殊操作。消息筛选器对特定线程是唯一的。

若要防止调度某消息,传递给该方法的 value 参数实例必须用处理该消息的代码重写 PreFilterMessage 方法。该方法必须返回 false

 

简单的说明下:

两者的功能实际上是不一样的:

有一个简单的例子来说明:

 我们新建一个Form,添加两种方法的消息处理Wm_Lbutton=0x021;另外在Form上添加一个Button,响应函数是MessageBox.Show();

代码如下:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            MessageDo();
        }
        private const int WM_Lbutton = 0x201;  
        protected override void DefWndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_Lbutton:
                    {
                        MessageBox.Show(" DefWndProc ");
                    }
                    break;
                case WM_ShowString:
                    {
                        MessageBox.Show("Show Stinrg Message have happened and Params are "+m.WParam.ToString()+":"+m.LParam.ToString());
                    }
                    break;
                default:
                    base.DefWndProc(ref m);
                    break;
            }
           
            //base.DefWndProc(ref m);
        }      
        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Button 1 was clicked just now !");
        }    
        private MessageFilter myfilter = new MessageFilter();
        private void MessageDo()
        {
            Application.AddMessageFilter(myfilter);
        }   
     
    }
    public class MessageFilter:IMessageFilter
    {
        public bool PreFilterMessage(ref Message m)
        {
            if (m.Msg == 0x201)
            {
                MessageBox.Show(" PreFilter ");
                return true;
            }
            return false;

        }
    }

运行后的结果是这样的:

 一直显示的  MessageBox() : PrefilTer,就算是Button按键也不能响应,整个UI的LButton都被他过滤了。

如果删除MessageFilter,结果就是: 当LButton发生的时候,只要不是在Button上面,就会MessageBox():DefWndProc

 

这个例子就可以看出最大的不同。

明天把这个东西补充下,有时间查查资料。

【上篇】
【下篇】

抱歉!评论已关闭.