zoukankan      html  css  js  c++  java
  • 为应用程序添加消息过滤器

    前几天,在一QQ群上,有一网友提问:如何得到鼠标按下时,点中的是哪个控件。(不能在每个控件的事件中添加 OnMouseDown,因为这样太麻烦,而且控件可能是动态产生的)

    当时我的第一反应是:这还不简单,直接重载 Form 的 WndProc 事件就行了

            const int WM_LBUTTONDOWN = 0x0201;
            
    protected override void WndProc(ref Message m)
            {
                
    if (m.Msg == WM_LBUTTONDOWN)
                {
                    Console.WriteLine(Control.FromHandle(m.HWnd).Name);
                }
                
    base.WndProc(ref m);
            }
    实际运行才发现根本不是那么回事,当我在一个 TextBox 上按下鼠标时,Form的WndProc根本不会执行。
    静下来好好想想,才发现自已错在对 WndProc 的理解上, Control.WndProc接收的消息仅仅是发送给该 Control 的,已经被操作系统过滤过的,所以当鼠标点在 TextBox 上时,Form 当然收不到 WM_LBUTTONDOWN 消息.

    那假如要实现该功能,要怎么办呢,经查, 用Application.AddMessageFilter 方法可实现,具体代码为:
    1.先定义一个消息过滤器
        /// <summary>
        
    /// 自定义的消息过滤器,必须实现 IMessageFilter 接口
        
    /// </summary>
        class myFilter : IMessageFilter
        {
            
    const int WM_LBUTTONDOWN = 0x0201;
            
    public bool PreFilterMessage(ref Message m)
            {
                
    if (m.Msg == WM_LBUTTONDOWN)
                {
                    Console.WriteLine(Control.FromHandle(m.HWnd).Name);
                }
                
    return false;
            }
        }
    2.在Form中添加该过滤器
            private void Form1_Load(object sender, EventArgs e)
            {
                
    //为窗体添加消息过滤器
                Application.AddMessageFilter(new myFilter());
            }
    经过这两步后,任何消息都会先发送到 myFilter 中, 用户可处理其中自已感兴趣的消息,OK!

    注:msdn 上明确注明,AddMessageFilter 会让系统性能下降,估计其低层是用 SetWindowsHook之类的API.
  • 相关阅读:
    《构建之法》阅读有疑 与 个人Week1作业
    版本管理和项目管理软件浅谈
    [2019BUAA软工助教]第0次个人作业
    [2017BUAA软工助教]博客格式的详细说明
    [2017BUAA软工助教]收集个人信息
    最长英文单词串题目分析
    蓝桥杯PREV-11:横向打印二叉树
    day2
    冯如杯day1
    个人阅读作业
  • 原文地址:https://www.cnblogs.com/michaelhuwei/p/784266.html
Copyright © 2011-2022 走看看