在C#编程中,经常会遇到一些场景,如禁止鼠标拖动窗体,启用某些快捷键,禁止鼠标移动等。遇到这些需求,可以通过窗体的MouseMove事件,OnDragDrop,OnMove等事件来解决问题,

但是该方法有个缺点是,只能在当前窗体或控件上起作用,如果窗体或控件被覆盖,就不起作用了。而我们在开发时经常会碰到一个Form上有很多控件的情形,本节将讲述如何通过捕捉windows消息的方式来实现这个功能。

一般来讲,实现该功能有两种方法,

1. 通过重写WndProc(ref Message m)来实现,方法签名如下:

protected override void WndProc(ref Message m)
{
      base.WndProc(ref m);
}

其中的Message中包含了以下几个字段信息,是和windows消息相关的,

public IntPtr LParam { get; set; }

public int Msg { get; set; }  // 获取或设置消息的 ID 号。

public IntPtr WParam { get; set; }

如:

如果我们要禁用窗体的拖拽,代码如下:

      const int WM_NCLBUTTONDOWN = 0x00A1;
      const int HTCAPTION = 2;
      protected override void WndProc(ref Message m)
      {
              if (m.Msg == WM_NCLBUTTONDOWN && m.WParam.ToInt32() == HTCAPTION)
                     return; 
              base.WndProc(ref m);
      }

2. 通过继承接口来实现System.Windows.Forms.IMessageFilter接口实现,接口声明如下:

public interface IMessageFilter
{
     // 摘要:
    // 在调度消息之前将其筛选出来。
    //
    // 参数:
    // m:
    // 要调度的消息。无法修改此消息。
    //
   // 返回结果:
   // 如果筛选消息并禁止消息被调度,则为 true;如果允许消息继续到达下一个筛选器或控件,则为 false。
   bool PreFilterMessage(ref Message m);
}

还以禁止拖动窗体为例,实现MessageFilter类如下:

public class MessageFilter : System.Windows.Forms.IMessageFilter
    {
        const int WM_NCLBUTTONDOWN = 0x00A1;//当光标在窗口的非客户区并按下鼠标左键时发送此消息
        const int HTCAPTION = 2;
 
        public bool PreFilterMessage(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_NCLBUTTONDOWN && m.WParam.ToInt32() == HTCAPTION)
                return true;
            return false;
        }
    }
 创建完这个类后,创建一个对象,并把该对象添加到应用程序里边,如下列代码,下列代码是Program文件当中的入口方法
  static class Program
    {
        private static MessageFilter filter = new MessageFilter();
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.AddMessageFilter(filter);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainFrm());
        }
    }  

注意:实现IMessageFilter接口时,一定要注意其返回值, [如果筛选消息并禁止消息被调度,则为 true;如果允许消息继续到达下一个筛选器或控件,则为 false。] ,对拦截的消息处理之后,一定要注意对返回值进行处理,如果对不处理的消息,一定要返回为false,让其他的控件去处理消息。

关于Windows消息,请参考文章 http://www.cnblogs.com/lenmom/p/3730179.html

Windows消息过滤的更多相关文章

  1. Windows消息机制详解

    消息是指什么?      消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用 ...

  2. 【转】windows消息和消息队列详解

    转载出处:http://blog.csdn.net/bichenggui/article/details/4677494  windows消息和消息队列 与基于MS - DOS的应用程序不同,Wind ...

  3. Windows消息机制概述

    消息是指什么?     消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用程 ...

  4. windows消息和消息队列

    windows消息和消息队列 转自:http://blog.163.com/zhangjie_0303/blog/static/990827062010113062446767/ 与基于MS - DO ...

  5. Windows 消息机制详解

    总的来说: MSG包括: 窗口句柄,指示MSG发送的目的窗口 消息标识 lPARAM.wParam 发送时间 发送时的鼠标位置   关于消息队列: Windows系统有一个系统消息队列 每个线程都有一 ...

  6. 【Qt】Qt之进程间通信(Windows消息)【转】

    简述 通过上一节的了解,我们可以看出进程通信的方式很多,今天分享下如何利用Windows消息机制来进行不同进程间的通信. 简述 效果 发送消息 自定义类型与接收窗体 发送数据 接收消息 设置标题 重写 ...

  7. Qt之进程间通信(Windows消息)

    简述 通过上一节的了解,我们可以看出进程通信的方式很多,今天分享下如何利用Windows消息机制来进行不同进程间的通信. 简述 效果 发送消息 自定义类型与接收窗体 发送数据 接收消息 设置标题 重写 ...

  8. windows消息钩子

    1.消息钩子的概念: Windows应用程序是基于消息驱动的,不论什么线程仅仅要注冊窗体类都会有一个消息队列用于接收用户输入的消息和系统消息.为了拦截消息,Windows提出了钩子的概念.钩子(Hoo ...

  9. Windows消息编程(写的不错,有前因后果)

    本文主要包括以下内容: 1.简单理解Windows的消息2.通过一个简单的Win32程序理解Windows消息3.通过几个Win32程序实例进一步深入理解Windows消息4.队列消息和非队列消息5. ...

随机推荐

  1. js实现图片实时预览

    注: 此博客转自 http://www.cnblogs.com/goody9807/p/6064582.html  转载请注明出处 <body> 上传图片: <input type= ...

  2. C++开发ArcGis

    以下这段时间将主要记录如何使用C++开发ArcGis,包括1.C++的学习:2.GIS的基础知识:3.如何开发三部分,9-3后开始后将持续更新

  3. 【 D3.js 入门系列 --- 5.1 】 做一个带坐标轴和标签的图表

    前面几节讲解了图标.坐标轴.比例等等,这一节整合这些内容做一个实用的图表.结果图如下: 代码如下所示: <html> <head> <meta charset=" ...

  4. netezza 数据库 取 季初 季末 时间

    -- 取季初那一天 select date_trunc( 'quarter',cast('20150820' as date)) -- 取季末那一天 select add_months(date_tr ...

  5. UVA213 信息解码

    对于lrj的想法,真是太清晰.自己真的是很难去做到.贴此代码,加以练习,加以感悟. #include<cstdio> #include<cstring> ][<<] ...

  6. NOIP2016日记

    今天下午2:30~4:30考NOIP2016..我4:00前久出来了,没仔细检查.. 错了两道基础题..(T_T)  >_< 至少能过..就这样吧..努力复赛!!

  7. 从返回值未报错得到的对于java finally理解

    不多说了,直接看图 这个代码来自<深入理解java虚拟机(第二版)>,我在eclipse中编辑的,但是没有报错,一般来说,没有返回值,eclipse都会有个提示或者报错啥的,但是这个没有, ...

  8. PHP文件和目录操作-----复制、移动、重命名、删除文件

    PHP通过copy()函数来复制一个文件.用法如下: bool copy(string $source, string $dest) 其中$source是源文件的路径,$dest是目的文件的路径.函数 ...

  9. 关于android R.layout.没有出现自己写的布局解决方法

    直接上解决方法 1.若import了androi.R直接删除,导入自己包下的R文件,例如com.example.my.R 2.若上面的做了后还有错误,应该是包名不一致导致的,即com.example. ...

  10. Atom编辑器添加eclipse快捷键

    Settings - Keybindings - 点击"your keymap file" 'atom-text-editor':  'alt-/': 'autocomplete- ...