C# to write mouse hook

Little knowledge, big challenge! This article is participating in the creation of " Tips for Programmers ".

With this encapsulated class, first register the hook, and then add the corresponding mouse events. The parameters when the mouse event is called and passed are all completed in the mouse processing function MouseHookProc(int nCode, Int32 wParam, IntPtr lParam). In this example, since the mouse processing does not require parameters, it is only necessary to obtain whether the left button or the left button is pressed. Right-click, so the other properties of the originally defined MouseEventArg parameter class are assigned to 0. The mouse processing function MouseHookProc is called in the mouse hook registration method.

    class MouseHook
    {
        //枚举定义
        public enum WH_Codes : int
        {
            /// <summary>
            /// 底层鼠标钩子
            /// </summary>
            WH_MOUSE_LL = 14
        }
 
        public enum WM_MOUSE : int
        {
            /// <summary>
            /// 鼠标开始
            /// </summary>
            WM_MOUSEFIRST = 0x200,
 
            /// <summary>
            /// 鼠标移动
            /// </summary>
            WM_MOUSEMOVE = 0x200,
 
            /// <summary>
            /// 左键按下
            /// </summary>
            WM_LBUTTONDOWN = 0x201,
 
            /// <summary>
            /// 左键释放
            /// </summary>
            WM_LBUTTONUP = 0x202,
 
            /// <summary>
            /// 左键双击
            /// </summary>
            WM_LBUTTONDBLCLK = 0x203,
 
            /// <summary>
            /// 右键按下
            /// </summary>
            WM_RBUTTONDOWN = 0x204,
 
            /// <summary>
            /// 右键释放
            /// </summary>
            WM_RBUTTONUP = 0x205,
 
            /// <summary>
            /// 右键双击
            /// </summary>
            WM_RBUTTONDBLCLK = 0x206,
 
            /// <summary>
            /// 中键按下
            /// </summary>
            WM_MBUTTONDOWN = 0x207,
 
            /// <summary>
            /// 中键释放
            /// </summary>
            WM_MBUTTONUP = 0x208,
 
            /// <summary>
            /// 中键双击
            /// </summary>
            WM_MBUTTONDBLCLK = 0x209,
 
            /// <summary>
            /// 滚轮滚动
            /// </summary>
            /// <remarks>WINNT4.0以上才支持此消息</remarks>
            WM_MOUSEWHEEL = 0x020A
        }
 
        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int X;
            public int Y;
        }
        /// <summary>
        /// 鼠标钩子事件结构定义
        /// </summary>
        /// <remarks>详细说明请参考MSDN中关于 MSLLHOOKSTRUCT 的说明</remarks>
        [StructLayout(LayoutKind.Sequential)]
        public struct MouseHookStruct
        {
            public POINT Point;
            public UInt32 MouseData;
            public UInt32 Flags;
            public UInt32 Time;
            public UInt32 ExtraInfo;
        }
 
        #region DLL导入
        /// <summary>
        /// 安装钩子
        /// </summary>
        /// <param name="idHook"></param>
        /// <param name="lpfn"></param>
        /// <param name="hInstance"></param>
        /// <param name="threadId"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr SetWindowsHookEx(WH_Codes idHook, HookProc lpfn,
            IntPtr pInstance, int threadId);
 
        /// <summary>
        /// 卸载钩子
        /// </summary>
        /// <param name="idHook"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(IntPtr pHookHandle);
 
        /// <summary>
        /// 传递钩子
        /// </summary>
        /// <param name="idHook"></param>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(IntPtr pHookHandle, int nCode,
            Int32 wParam, IntPtr lParam);
 
        #endregion DLL导入
 
        //鼠标钩子句柄
        private IntPtr m_pMouseHook = IntPtr.Zero;
        /// <summary>
        /// 钩子委托声明
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
        /// <summary>
        /// 鼠标钩子委托实例
        /// </summary>
        /// <remarks>
        /// 不要试图省略此变量,否则将会导致
        /// 激活 CallbackOnCollectedDelegate 托管调试助手 (MDA)。 
        /// 详细请参见MSDN中关于 CallbackOnCollectedDelegate 的描述
        /// </remarks>
        private HookProc m_MouseHookProcedure;
 
 
        #region 事件定义
 
        /// <summary>
        /// 鼠标移动事件
        /// </summary>
        /// <remarks>当鼠标移动或者滚轮滚动时触发</remarks>
        public event MouseEventHandler OnMouseMove;
 
        /// <summary>
        /// 鼠标按下事件
        /// </summary>
        public event MouseEventHandler OnMouseDown;
 
         
        /// <summary>
        /// 按键释放事件
        /// </summary>
        public event MouseEventHandler OnMouseUp;
 
        #endregion
 
        #region 私有方法
        /// <summary>
        /// 鼠标钩子处理函数
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {
            if ((nCode >= 0) && (this.OnMouseMove != null)
                && (wParam == (int)WM_MOUSE.WM_MOUSEMOVE ||wParam == (int)WM_MOUSE.WM_MOUSEWHEEL))
            {
                //MouseHookStruct MouseInfo = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
                this.OnMouseMove(null,null);
            }
            if ((nCode >= 0) && (this.OnMouseDown != null)&&(wParam==(int)WM_MOUSE.WM_LBUTTONDOWN||wParam==(int)WM_MOUSE.WM_RBUTTONDOWN)) 
            {
                MouseButtons button = MouseButtons.None;
                switch (wParam)
                {
                    case (int)WM_MOUSE.WM_LBUTTONDOWN:
                        //case WM_LBUTTONUP: 
                        //case WM_LBUTTONDBLCLK: 
                        button = MouseButtons.Left;
                        break;
                    case (int)WM_MOUSE.WM_RBUTTONDOWN:
                        //case WM_RBUTTONUP: 
                        //case WM_RBUTTONDBLCLK: 
                        button = MouseButtons.Right;
                        break;
                }
                MouseEventArgs e = new MouseEventArgs(
                                                   button,
                                                   0, 
                                                   0,
                                                   0,
                                                   0
                                                   );
                this.OnMouseDown(null, e);
            }
            if ((nCode >= 0) && (this.OnMouseDown != null)
                && (wParam == (int)WM_MOUSE.WM_LBUTTONUP || wParam == (int)WM_MOUSE.WM_RBUTTONUP))
            {
                MouseButtons button = MouseButtons.None;
                switch (wParam)
                {
                    case (int)WM_MOUSE.WM_LBUTTONUP:
                        //case WM_LBUTTONUP: 
                        //case WM_LBUTTONDBLCLK: 
                        button = MouseButtons.Left;
                        break;
                    case (int)WM_MOUSE.WM_RBUTTONUP:
                        //case WM_RBUTTONUP: 
                        //case WM_RBUTTONDBLCLK: 
                        button = MouseButtons.Right;
                        break;
                }
                MouseEventArgs e = new MouseEventArgs(
                                                   button,
                                                   0,
                                                   0,
                                                   0,
                                                   0
                                                   );
                this.OnMouseUp(null, e);
            }
            return CallNextHookEx(this.m_pMouseHook, nCode, wParam, lParam);
        }
        #endregion
 
        #region 公共方法
        /// <summary>
        /// 安装钩子
        /// </summary>
        /// <returns></returns>
        public bool InstallHook()
        {
 
            IntPtr pInstance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().ManifestModule);
            //pInstance = (IntPtr)4194304;
            // IntPtr pInstanc2 = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly());
            // Assembly.GetExecutingAssembly().GetModules()[0]
            // 假如没有安装鼠标钩子
            if (this.m_pMouseHook == IntPtr.Zero)
            {
                this.m_MouseHookProcedure = new HookProc(this.MouseHookProc);
                this.m_pMouseHook = SetWindowsHookEx(WH_Codes.WH_MOUSE_LL, this.m_MouseHookProcedure, pInstance, 0);
                if (this.m_pMouseHook == IntPtr.Zero)
                {
                    this.UnInstallHook();
                    return false;
                }
            }
            return true;
        }
 
        /// <summary>
        /// 卸载钩子
        /// </summary>
        /// <returns></returns>
        public bool UnInstallHook()
        {
            bool result = true;
            if (this.m_pMouseHook != IntPtr.Zero)
            {
                result = (UnhookWindowsHookEx(this.m_pMouseHook) && result);
                this.m_pMouseHook = IntPtr.Zero;
            }
            return result;
        }
 
 
        #endregion
 
    }
复制代码

Guess you like

Origin juejin.im/post/7020222550735061023