Window捕获消息机制-C#

C#捕获鼠标消息

在C#中怎样禁用鼠标按键,我们可以通过ImessageFilter接口下的PreFilterMessage方法、Application类的AddMessageFilter方法,RemoveMessageFilter方法和Message结构的Msg属性来禁用鼠标左键。Message结构包装Windows发送的消息,可使用该结构包装消息,并将其分配给窗口过程以进行调度,还可以使用该结构获取系统向应用程序或控件发送的关于某个消息的信息。

使用PreFilterMessage方法在调度消息之前将其筛选出来。语法格式如下: 

Bool PreFilterMessage(ref Message m)

参数说明:

m:要调度的消息,无法修改此消息。

返回值:如果筛选消息并禁止消息被调度,则为True;如果允许消息继续到达下一个筛选器或控件,则为False。使用AddMessageFilter方法添加消息筛选器以便在向目标传送Windows消息时监视这些消息。使RemoveMessageFilter 从应用程序的消息泵移除一个消息筛选器。

示例一:在ComboBox选择值的时候,选择的值会随鼠标滚轮的滑动而改变,有时候不小心滑动了滑轮,导致选择的值改变,在下面的示例中,通过禁用鼠标滚轮,防止鼠标滚轮的滑动改变ComboBox选择的值。

界面:

代码实现:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Threading.Tasks;
 9 using System.Windows.Forms;
10 
11 namespace MouseDemo
12 {
13     public partial class FrmMain : Form,IMessageFilter
14     {
15         public FrmMain()
16         {
17             InitializeComponent();
18         }
19 
20         public bool PreFilterMessage(ref Message m)
21         {
22             if (m.Msg == 522)
23             {
24                 return true;
25             }
26             else
27             {
28                 return false;
29             }
30         }
31 
32         /// <summary>
33         /// 窗体加载
34         /// </summary>
35         /// <param name="sender"></param>
36         /// <param name="e"></param>
37         private void FrmMain_Load(object sender, EventArgs e)
38         {
39             InitComboBox();
40         }
41 
42         /// <summary>
43         /// 初始化ComboBox
44         /// </summary>
45         private void InitComboBox()
46         {
47             Dictionary<int, string> dictGrade = new Dictionary<int, string>();
48             dictGrade.Add(1, "一年级");
49             dictGrade.Add(2, "二年级");
50             dictGrade.Add(3, "三年级");
51             dictGrade.Add(4, "四年级");
52             dictGrade.Add(5, "五年级");
53             dictGrade.Add(6, "六年级");
54 
55             BindingSource dataSource = new BindingSource();
56             dataSource.DataSource = dictGrade;
57             cmb_Grade.DataSource = dataSource;
58             cmb_Grade.DisplayMember = "Value";
59             cmb_Grade.ValueMember = "Key";
60         }
61 
62         /// <summary>
63         /// 索引改变事件
64         /// </summary>
65         /// <param name="sender"></param>
66         /// <param name="e"></param>
67         private void cmb_Grade_SelectedIndexChanged(object sender, EventArgs e)
68         {
69               //添加消息过滤
70             Application.AddMessageFilter(this);
71         }
72 
73 
74     }
75 }

示例二:窗体设置右键控件,演示禁用和解除禁用右键功能,右键菜单只有复制、剪切、粘贴三项

界面:

代码:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Threading.Tasks;
 9 using System.Windows.Forms;
10 
11 namespace MouseRightDemo
12 {
13     public partial class FrmMouseRight : Form   ,IMessageFilter
14     {
15         public FrmMouseRight()
16         {
17             InitializeComponent();
18         }
19 
20         /// <summary>
21         /// 实现方法
22         /// </summary>
23         /// <param name="m"></param>
24         /// <returns></returns>
25         public bool PreFilterMessage(ref Message m)
26         {
27             //不响应鼠标右键
28             if (m.Msg >= 516 && m.Msg <= 517)
29             {
30                 return true;
31             }
32             else
33             {
34                 return false;
35             }
36         }
37 
38         /// <summary>
39         /// 禁用鼠标右键
40         /// </summary>
41         /// <param name="sender"></param>
42         /// <param name="e"></param>
43         private void button1_Click(object sender, EventArgs e)
44         {
45                //添加消息
46             Application.AddMessageFilter(this);
47             MessageBox.Show("鼠标右键已被禁止使用", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
48         }
49 
50         /// <summary>
51         /// 解决禁用鼠标右键
52         /// </summary>
53         /// <param name="sender"></param>
54         /// <param name="e"></param>
55         private void button2_Click(object sender, EventArgs e)
56         {
57                 //移除消息
58             Application.RemoveMessageFilter(this);
59             MessageBox.Show("鼠标右键已被解除禁止使用,可以使用鼠标右键", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
60         }
61     }
62 }

鼠标动作常见参数:

鼠标移动:512

鼠标左键:

down:513 up:514

double click:515

鼠标右键:

down:516 up:517

鼠标滚轮:522

//**************************

利用windows消息机制截获特定应用程序里鼠标、键盘的消息事件

通过学习知道钩子机制可以帮助我们截获处理windows消息或特定事件,现将本人所掌握的知识内容总结如下:

1.调用windows底层API,定义winAPI类

  using System.Runtime.InteropServices;


    public class WinApi
    {
        [StructLayout(LayoutKind.Sequential)]
        public class POINT
        {
            public int x;
            public int y;
        }
        [StructLayout(LayoutKind.Sequential)]
        public class MouseHookStruct
        {
            public POINT pt;
            public int hwnd;
            public int wHitTestCode;
            public int dwExtraInfo;
        }
        [StructLayout(LayoutKind.Sequential)]
        public class KeyboardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
        //安装钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        //卸载钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        //调用下一个钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam); 
        //获得系统当前窗体句柄
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();
        //获得窗体名称
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowText();
   }
2.定义鼠标钩子和键盘钩子
    public class MouseHook
    {        
        private Point point;
        private Point Point
        {
            get { return point; }
            set
            {
                if (point != value)
                {
                    point = value;
                }
            }
        }
        private int hHook;
        public const int WH_MOUSE_LL = 14;
        public WinApi.HookProc hProc;
        public MouseHook()
        {
            this.Point = new Point(); 
        }
        public int SetHook()
        {
            hProc = new WinApi.HookProc(MouseHookProc);
            hHook = WinApi.SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero,0);
            return hHook;
        }
        public void UnHook()
        {
            WinApi.UnhookWindowsHookEx(hHook);
        }
        private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {            
            if (nCode < 0)
            {
                return WinApi.CallNextHookEx(hHook, nCode, wParam, lParam);
            }
            else
            {
               WinApi.MouseHookStruct MyMouseHookStruct = (WinApi.MouseHookStruct)Marshal.PtrToStructure
                      (lParam, typeof(WinApi.MouseHookStruct));
               MouseButtons button = MouseButtons.None;
               int clickCount = 0;
               switch ((Int32)wParam)
               {
                   case WM_LBUTTONDOWN: 
                        button = MouseButtons.Left;
                        clickCount = 1;
                        var e = new MouseEventArgs(button, clickCount, point.X, point.Y, 0);
                        MouseClick(this, e);
                        break;
                   case WM_MOUSEMOVE: 
                        var e = new MouseEventArgs(button, clickCount, point.X, point.Y, 0);
                        MouseMove(this, e);
                        break;
                    }
               this.Point = new Point(MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y);
               return WinApi.CallNextHookEx(hHook, nCode, wParam, lParam);
            }
        }
        //委托+事件(把钩到的消息封装为事件,由调用者处理)
        public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
        public event MouseMoveHandler MouseMove;
 
        public delegate void MouseClickHandler(object sender, MouseEventArgs e);
        public event MouseClickHandler MouseClick;
    }    
    public class KeyboardHook
    {        
        private int hHook;
        public WinApi.HookProc hProc;
 
        public int SetHook()
        {
            hProc = new WinApi.HookProc(KeyboardHookProc);
            hHook = WinApi.SetWindowsHookEx(WH_KEYBOARD_LL, hProc, IntPtr.Zero,0);
            return hHook;
        }
        public void UnHook()
        {
            WinApi.UnhookWindowsHookEx(hHook);
        }
        private int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {            
            if (nCode >= 0)
            {
               WinApi.KeyboardHookStruct kbhs= (WinApi.KeyboardHookStruct)Marshal.PtrToStructure(lParam,
                      typeof(WinApi.KeyboardHookStruct));
              Keys key = (Keys)kbhs.vkCode;
               switch ((Int32)wParam)
               {
                   case WM_KEYDOWN:                         
                        var e = new KeyEventArgs(key);
                        KeyDown(this, e);
                        break;
                   case WM_KEYUP: 
                        var e1 = new KeyEventArgs(key);
                        KeyUp(this, e1);
                        break;
                }               
            }
            return WinApi.CallNextHookEx(hHook, nCode, wParam, lParam);
      }
      //委托+事件(把钩到的消息封装为事件,由调用者处理) 
      public delegate void KeyDownEventHandler(object sender, KeyEventArgs e); 
      public delegate void KeyUpEventHandler(object sender, KeyEventArgs e); 
 
      public event KeyDownEventHandler KeyDown; 
      public event KeyUpEventHandler KeyUp; 
   }
3.应用程序调用
MouseHook mh;
KeyboardHook kh;
public Form1()
{
      InitializeComponent();
      //启动程序自动隐藏窗体
     this.WindowState = FormWindowState.Minimized;
     this.ShowInTaskbar = false;
     SetVisibleCore(false);
}
private void Form1_Load(object sender, EventArgs e)
{
      mh = new MouseHook();
      mh.SetHook();
      mh.MouseMove += mh_MouseMove;
      mh.MouseClick += mh_MouseClick;
      kh = new KeyboardHook();
      kh.SetHook();
      kh.KeyDown += kh_KeyDown;
      kh.KeyUp += kh_KeyUp;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
       mh.UnHook();
       kh.UnHook();
}
private void mh_MouseMove(object sender, MouseEventArgs e)
{
}
private void mh_MouseClick(object sender, MouseEventArgs e)
{
}
private void kh_KeyDown(object sender, KeyEventArgs e)
{
}
private void kh_KeyUp(object sender, KeyEventArgs e)
{
}
 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值