Mouse Hook

参考文献:http://www.jb51.net/article/37365.htm

谈一下我对mouse Hook的理解。主要是

SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
这个是设置钩子的。IntPtr hInstance这个是回调函数,当钩子勾到消息后会进入到这个函数中。完成setWindowsHookEx各个参数就差不多了。
网上解释很多,但是感觉不好理解。还是这样做比较好理解一些。最后再调用CallNextHookEx。到最后不用的时候要释放钩子
UnhookWindowsHookEx。
回调函数格式固定:
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
完成这个参数的填写就差不多完成了。
下面的两个类是例子可以参考一下,已经实现了对鼠标的捕捉。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
 
namespace TestHook
{
    class Win32Api
    {
        #region Normal Data Struct

        public const int WM_KEYDOWN = 0x100;

        public const int WM_KEYUP = 0x101;

        public const int WM_SYSKEYDOWN = 0x104;

        public const int WM_SYSKEYUP = 0x105;

        public const int WH_KEYBOARD_LL = 13;

        public const int WH_MOUSE_LL = 14;

        public const int WM_MOUSEMOVE = 0x200;

        public const int WM_LBUTTONDOWN = 0x201;

        public const int WM_RBUTTONDOWN = 0x204;

        public const int WM_MBUTTONDOWN = 0x207;

        public const int WM_LBUTTONUP = 0x202;

        public const int WM_RBUTTONUP = 0x205;

        public const int WM_MBUTTONUP = 0x208;

        public const int WM_LBUTTONDBLCLK = 0x203;

        public const int WM_RBUTTONDBLCLK = 0x206;

        public const int WM_MBUTTONDBLCLK = 0x209;

        //define keyboard meesage struct
        [StructLayout(LayoutKind.Sequential)]
        public class KeyboardHookStruct
        {
            //Represents a virtual keyboard codes between 1 and 254
            public int vkCode;
            //Indicate a hardware scan code
            public int scanCode;
 
            public int flags;

            public int time;

            public int dwExtraInfo;

        }

        //Declares a Point type is marshaled
        [StructLayout(LayoutKind.Sequential)]
        public class POINT
        {
            public int x;
            public int y;
        }

        //Declaring a mouse hook marshaled structure types
        [StructLayout(LayoutKind.Sequential)]
        public class MouseHookStruct
        {
            public POINT pt;
            public int hWnd;
            public int wHitTestCode;
            public int dwExtraInfo;
        }
        #endregion
 
        #region Api
 
        public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);

        //install hook 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        //uninstall hook
        [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, Int32 wParam, IntPtr lParam);
 
        [DllImport("user32")]
        public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);

        [DllImport("user32")]
        public static extern int GetKeyboardState(byte[] pbKeyState);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
        #endregion
 
        #region Copied from Prism Management Studio Common
        [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();
        #endregion
 
        #region GetMessageExtraInfo
        [DllImport("user32.dll", EntryPoint = "GetMessageExtraInfo", SetLastError = true)]
        public static extern IntPtr GetMessageExtraInfo();
        #endregion
 
        #region MapVirtualKey
        [DllImport("user32.dll")]
        public static extern UInt32 MapVirtualKey(UInt32 uCode, UInt32 uMapType);
        #endregion
    }
}
类:MouseHOOk
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace TestHook
{
    class MouseHook
    {
        //use to judge doubleClick
 
        private int doubleClickcount = 0;
        private DateTime lastClickTime;
        private int pointx = -1;
        private int pointy = -1;
 
 
        int hHook;
        public bool IsHooking = false;
 
        Win32Api.HookProc MouseHookDelegate;
 
        /// <summary>
        /// mouse down event
        /// </summary>
        public event MouseEventHandler OnMouseDownEvents;
        /// <summary>
        /// mouse doubleclick event
        /// </summary>
        public event MouseEventHandler OnDoubleClickEvents;
        /// <summary>
        /// mouse up event
        /// </summary>
        public event MouseEventHandler OnMouseUpEvents;
        /// <summary>
        /// mouse move event
        /// </summary>
        public event MouseEventHandler OnMouseMove;
 
        [DllImport("user32.dll")]
        public static extern int GetDoubleClickTime();
        public MouseHook() { }
        ~MouseHook()
        {
            if (IsHooking)
            {
                Win32Api.UnhookWindowsHookEx(hHook);
            }
        }
 
        public bool SetHook()
        {

            MouseHookDelegate = new Win32Api.HookProc(MouseHookProc);

            Process cProcess = Process.GetCurrentProcess();

            ProcessModule cModule = cProcess.MainModule;

            var mh = Win32Api.GetModuleHandle(cModule.ModuleName);

            hHook = Win32Api.SetWindowsHookEx(Win32Api.WH_MOUSE_LL, MouseHookDelegate, mh, 0);

            if (hHook == 0)
                return false;
            IsHooking = true;
            return true;
        }
 
        public void UnHook()
        {
            if (IsHooking)
            {
                if (Win32Api.UnhookWindowsHookEx(hHook))
                {
                    IsHooking = false;
                }
            }
        }
 
        private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {
            //if (nCode != 0)
            //{
 
            //}
            MouseButtons button = MouseButtons.None;
            int delta = 0;
            int clickCount = 0;
            switch (wParam)
            {
                case Win32Api.WM_LBUTTONDOWN:
                    button = MouseButtons.Left;
                    clickCount = 1;
                    delta = 1;
                    break;
                case Win32Api.WM_LBUTTONUP:
                    button = MouseButtons.Left;
                    clickCount = 1;
                    delta = 2;
                    break;
                case Win32Api.WM_LBUTTONDBLCLK:
                    button = MouseButtons.Left;
                    clickCount = 2;
                    delta = 1;
                    break;
                case Win32Api.WM_RBUTTONDOWN:
                    button = MouseButtons.Right;
                    clickCount = 1;
                    delta = 1;
                    break;
                case Win32Api.WM_RBUTTONUP:
                    button = MouseButtons.Right;
                    clickCount = 1;
                    delta = 2;
                    break;
                case Win32Api.WM_RBUTTONDBLCLK:
                    button = MouseButtons.Right;
                    clickCount = 2;
                    delta = 1;
                    break;
                case Win32Api.WM_MBUTTONDOWN:
                    button = MouseButtons.Middle;
                    clickCount = 1;
                    delta = 1;
                    break;
                case Win32Api.WM_MBUTTONUP:
                    clickCount = 1;
                    delta = 2;
                    break;
                case Win32Api.WM_MBUTTONDBLCLK:
                    button = MouseButtons.Middle;
                    clickCount = 2;
                    delta = 1;
                    break;
            }

            //delta = 1 when mouse down ,delta = 2 when mouse up

            //Do MouseDown Events
            if (wParam == Win32Api.WM_LBUTTONDOWN || wParam == Win32Api.WM_RBUTTONDOWN || wParam == Win32Api.WM_MBUTTONDOWN)
            {
                //get mouse callback info
                Win32Api.MouseHookStruct MyMouseHookStruct = (Win32Api.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.MouseHookStruct));
                MouseEventArgs e;
                System.TimeSpan clickTimeSpan = DateTime.Now - lastClickTime;
                lastClickTime = DateTime.Now;
                if (clickTimeSpan.TotalMilliseconds <= GetDoubleClickTime() && wParam == Win32Api.WM_LBUTTONDOWN && MyMouseHookStruct.pt.x == pointx && MyMouseHookStruct.pt.y == pointy)
                {
                    doubleClickcount++;
                }
                else
                {
                    doubleClickcount = 1;
                }
                pointx = MyMouseHookStruct.pt.x;
                pointy = MyMouseHookStruct.pt.y;
                if (doubleClickcount == 1)
                {
                    if (OnMouseDownEvents != null)
                    {
                        e = new MouseEventArgs(button, clickCount, MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y, delta);
                        OnMouseDownEvents(this, e);
                    }
                }

                if (doubleClickcount == 2)
                {
                    if (OnDoubleClickEvents != null)
                    {
                        e = new MouseEventArgs(button, doubleClickcount, MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y, delta);
                        doubleClickcount = 0;
                        OnDoubleClickEvents(this, e);
                    }
                }
            }

            //Do MouseUp Events
            if (wParam == Win32Api.WM_LBUTTONUP || wParam == Win32Api.WM_MBUTTONUP || wParam == Win32Api.WM_RBUTTONUP)
            {
                //get mouse callback info
                Win32Api.MouseHookStruct MyMouseHookStruct = (Win32Api.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.MouseHookStruct));
                MouseEventArgs e = new MouseEventArgs(button, clickCount, MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y, delta);
                //check is registed events
                if (OnMouseUpEvents != null)
                {
                    OnMouseUpEvents(this, e);
                }
            }

            if (wParam == Win32Api.WM_MOUSEMOVE)
            {
                //get mouse callback info
                Win32Api.MouseHookStruct MyMouseHookStruct = (Win32Api.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.MouseHookStruct));

                MouseEventArgs e = new MouseEventArgs(button, clickCount, MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y, delta);

                if (OnMouseMove != null)
                {
                    OnMouseMove(this, e);
                }
            }


            return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
        }
    }
}
接下来对鼠标事件进行注册就行了。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace TestHook
{
    public partial class Form1 : Form
    {
        MouseHook mouseHook = new MouseHook();
        TestDelegate s;
        public Form1()
        {
            InitializeComponent();
        }
 
        private void btnName_Click(object sender, EventArgs e)
        {
 
            //mouseHook.OnMouseDownEvents += new MouseEventHandler(mouseDown);
            mouseHook.OnMouseDownEvents += mouseDown;
            mouseHook.SetHook();
        }
 
        private void mouseDown(Object sender, MouseEventArgs e)
        {
            //this.Text = "X: " + e.X + " Y: " + e.Y;
            //s = (int x,int y) => { MessageBox.Show("X: " + x + " Y: " + y); };
            s = new TestDelegate(showXY);
            s.BeginInvoke(e.X, e.Y, nullnull);//开辟一个新线程,否则可能造成MainForm的卡顿。
        }
 
        private void showXY(int x, int y)
        {
            Thread.Sleep(5000);
            UIDelegate UIDelegate = delegate () { this.Text = ("X: " + x + " Y: " + y); };
            this.Invoke(UIDelegate);//使用Invoke调用可以解决跨线程访问控件的问题。
        }
 
        private void btnCancel_Click(object sender, EventArgs e)
        {
            mouseHook.OnMouseDownEvents -= mouseDown;
            mouseHook.UnHook();
//string status = e.Delta == 1 ? "Down" : "Up";
//string leftOrMiddleOrRight = e.Button.ToString();
//string ClickStatus=e.Clicks==1? "Click" : "DoubleClick";
//MessageBox.Show("status: "+status+" leftorMiddleorRight: "+leftOrMiddleOrRight+" ClickStatus: "+ClickStatus);
        }    }    public delegate void TestDelegate(int x, int y);    public delegate void UIDelegate();}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值