• VSTO Office二次开发键盘鼠标钩子使用整理


    可能通过程序控制键盘的操作和控制鼠标的一些操作,网上提供比较多的也是比较好的就是通过钩子(Hook)的方式实现。
    简单整理了一下,没有找到很好的程序示例,做了个简单的Hook测试。(对于Hook的原理和调用细则,这里不涉及了,只是简单的Hook小测试,感兴趣的查一下吧)
    1.Win32API函数:(简单封装对于API函数的调用)

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace TestHook.MyHook
    {
        class Win32API
        {
            #region DLL导入
            /// <summary>
            /// 用于设置窗口
            /// </summary>
            /// <param name="hWnd"></param>
            /// <param name="hWndInsertAfter"></param>
            /// <param name="X"></param>
            /// <param name="Y"></param>
            /// <param name="cx"></param>
            /// <param name="cy"></param>
            /// <param name="uFlags"></param>
            /// <returns></returns>
            [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter,int X, int Y, int cx, int cy, int uFlags);
    
            /// <summary>
            /// 安装钩子
            /// </summary>
            /// <param name="idHook">钩子类型,鼠标\键盘\巨集等10几种</param>
            /// <param name="lpfn">挂钩的函数,用来处理拦截消息的函数,全局函数</param>
            /// <param name="hInstance">当前进程的句柄,
            /// 为NULL:当前进程创建的一个线程,子程位于当前进程;
            /// 为0(IntPtr.Zero):钩子子程与所有的线程关联,即为全局钩子</param>
            /// <param name="threadId">设置要挂接的线程ID.为NULL则为全局钩子</param>
            /// <returns></returns>
            [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr SetWindowsHookEx(IntPtr idHook, HookProc lpfn,IntPtr pInstance, uint 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,IntPtr wParam, IntPtr lParam);
    
            /// <summary>
            /// 转换当前按键信息
            /// </summary>
            /// <param name="uVirtKey"></param>
            /// <param name="uScanCode"></param>
            /// <param name="lpbKeyState"></param>
            /// <param name="lpwTransKey"></param>
            /// <param name="fuState"></param>
            /// <returns></returns>
            [DllImport("user32.dll")]
            public static extern int ToAscii(UInt32 uVirtKey, UInt32 uScanCode,byte[] lpbKeyState, byte[] lpwTransKey, UInt32 fuState);
    
            /// <summary>
            /// 获取按键状态
            /// </summary>
            /// <param name="pbKeyState"></param>
            /// <returns>非0表示成功</returns>
            [DllImport("user32.dll")]
            public static extern int GetKeyboardState(byte[] pbKeyState);
    
            [DllImport("user32.dll")]
            public static extern short GetKeyStates(int vKey);
    
            /// <summary>
            /// 获取当前线程Id
            /// </summary>
            /// <returns></returns>
            [DllImport("kernel32.dll")]
            public static extern uint GetCurrentThreadId();
    
            /// <summary>
            /// 截屏位置
            /// </summary>
            /// <param name="hdcDest">目标设备的句柄 </param>
            /// <param name="nXDest">目标对象的左上角的X坐标</param>
            /// <param name="nYDest">目标对象的左上角的Y坐标</param>
            /// <param name="nWidth">目标对象的矩形的宽度</param>
            /// <param name="nHeight">目标对象的矩形的高度 </param>
            /// <param name="hdcSrc">源设备的句柄 </param>
            /// <param name="nXSrc">源对象的左上角的X坐标 </param>
            /// <param name="nYSrc">源对象的左上角的Y坐标 </param>
            /// <param name="dwRop">光栅的操作值 </param>
            /// <returns></returns>
            [DllImportAttribute("gdi32.dll")]
            private static extern bool BitBlt(IntPtr hdcDest, int nXDest,int nYDest,int nWidth,int nHeight,
                IntPtr hdcSrc,int nXSrc,int nYSrc,System.Int32 dwRop);
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="lpszDriver">驱动名称</param>
            /// <param name="lpszDevice">设备名称</param>
            /// <param name="lpszOutput">无用,可以设定为"NULL"</param>
            /// <param name="lpInitData">任意的打印机数据</param>
            /// <returns></returns>
            [DllImportAttribute("gdi32.dll")]
            private static extern IntPtr CreateDC(string lpszDriver,string lpszDevice,string lpszOutput,IntPtr lpInitData);
            #endregion DLL导入
    
            /// <summary>
            /// 钩子委托声明
            /// </summary>
            /// <param name="nCode"></param>
            /// <param name="wParam"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
        }
    }

    2.HookHelper.cs:(对于一些标识的定义,特别注意鼠标和键盘的标识参数)

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace TestHook.MyHook
    {
        public class HookHelper
        {
            #region 枚举定义
            /// <summary>
            /// 操作类型
            /// </summary>
            public enum HookType
            {
                KeyOperation,//键盘操作
                MouseOperation//鼠标操作
            }
    
            /// <summary>
            /// 底层钩子标识
            /// </summary>
            public enum WH_Codes : int
            {
                //底层键盘钩子
                WH_KEYBOARD_LL = 2,//2:监听键盘消息并且是线程钩子;13:全局鼠标钩子监听
    
                //底层鼠标钩子
                WH_MOUSE_LL = 7, //7:监听鼠标钩子;14:全局键盘钩子监听鼠标信息
    
                //nCode为0
                HC_ACTION = 0
            }
    
            /// <summary>
            /// 鼠标按钮标识
            /// </summary>
            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
            }
    
            /// <summary>
            /// 键盘按键标识
            /// </summary>
            public enum WM_KEYBOARD : int
            {
                /// <summary>
                /// 非系统按键按下
                /// </summary>
                WM_KEYDOWN = 0x100,
    
                /// <summary>
                /// 非系统按键释放
                /// </summary>
                WM_KEYUP = 0x101,
    
                /// <summary>
                /// 系统按键按下
                /// </summary>
                WM_SYSKEYDOWN = 0x104,
    
                /// <summary>
                /// 系统按键释放
                /// </summary>
                WM_SYSKEYUP = 0x105
            }
    
            /// <summary>
            /// SetWindowPos标志位枚举
            /// </summary>
            /// <remarks>详细说明,请参见MSDN中关于SetWindowPos函数的描述</remarks>
            public enum SetWindowPosFlags : int
            {
                /// <summary>
                /// 
                /// </summary>
                SWP_NOSIZE = 0x0001,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_NOMOVE = 0x0002,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_NOZORDER = 0x0004,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_NOREDRAW = 0x0008,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_NOACTIVATE = 0x0010,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_FRAMECHANGED = 0x0020,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_SHOWWINDOW = 0x0040,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_HIDEWINDOW = 0x0080,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_NOCOPYBITS = 0x0100,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_NOOWNERZORDER = 0x0200,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_NOSENDCHANGING = 0x0400,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_DRAWFRAME = 0x0020,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_NOREPOSITION = 0x0200,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_DEFERERASE = 0x2000,
    
                /// <summary>
                /// 
                /// </summary>
                SWP_ASYNCWINDOWPOS = 0x4000
    
            }
    
            #endregion 枚举定义
    
            #region 结构定义
    
            [StructLayout(LayoutKind.Sequential)]
            public struct POINT
            {
                public int X;
                public int Y;
            }
    
            /// <summary>
            /// 鼠标钩子事件结构定义
            /// </summary>
            /// <remarks>详细说明请参考MSDN中关于 MSLLHOOKSTRUCT 的说明</remarks>
            [StructLayout(LayoutKind.Sequential)]
            public struct MouseHookStruct
            {
                /// <summary>
                /// Specifies a POINT structure that contains the x- and y-coordinates of the cursor, in screen coordinates.
                /// </summary>
                public POINT Point;
    
                public UInt32 MouseData;
                public UInt32 Flags;
                public UInt32 Time;
                public UInt32 ExtraInfo;
            }
    
            /// <summary>
            /// 键盘钩子事件结构定义
            /// </summary>
            /// <remarks>详细说明请参考MSDN中关于 KBDLLHOOKSTRUCT 的说明</remarks>
            [StructLayout(LayoutKind.Sequential)]
            public struct KeyboardHookStruct
            {
                /// <summary>
                /// Specifies a virtual-key code. The code must be a value in the range 1 to 254. 
                /// </summary>
                public UInt32 VKCode;
    
                /// <summary>
                /// Specifies a hardware scan code for the key.
                /// </summary>
                public UInt32 ScanCode;
    
                /// <summary>
                /// Specifies the extended-key flag, event-injected flag, context code, 
                /// and transition-state flag. This member is specified as follows. 
                /// An application can use the following values to test the keystroke flags. 
                /// </summary>
                public UInt32 Flags;
    
                /// <summary>
                /// Specifies the time stamp for this message. 
                /// </summary>
                public UInt32 Time;
    
                /// <summary>
                /// Specifies extra information associated with the message. 
                /// </summary>
                public UInt32 ExtraInfo;
            }
    
            #endregion 结构定义
        }
    }

    3.Hook.cs:(简单对于键盘、鼠标的操作进行监控)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace TestHook.MyHook
    {
        public class Hook
        {
            #region 定义变量
            //定义鼠标钩子处理函数
            private Win32API.HookProc MouseHookProcedure = null;
            //定义键盘钩子处理函数
            private Win32API.HookProc KeyboardProcDelegate = null;
    
            //定义键盘钩子句柄
            private IntPtr khook;
            //定义鼠标钩子句柄
            private IntPtr hHook = IntPtr.Zero;
    
            //定义鼠标事件
            public event MouseEventHandler OnMouseActivity;
            #endregion
    
            /// <summary>
            /// 安装钩子
            /// </summary>
            public void InstallHook(HookHelper.HookType hookType)
            {
                if (hookType == HookHelper.HookType.KeyOperation)
                {
                    if (khook == IntPtr.Zero)//键盘钩子
                    {
                        uint id = Win32API.GetCurrentThreadId();
                        this.KeyboardProcDelegate = new Win32API.HookProc(this.KeyboardProc);
                        khook = Win32API.SetWindowsHookEx((IntPtr)HookHelper.WH_Codes.WH_KEYBOARD_LL, this.KeyboardProcDelegate, IntPtr.Zero, id);
                    }
                }
                else
                {
                    if (hHook == IntPtr.Zero)//鼠标钩子
                    {
                        uint id = Win32API.GetCurrentThreadId();
                        this.MouseHookProcedure = new Win32API.HookProc(this.MouseHookProc);
                        //这里挂节钩子
                        hHook = Win32API.SetWindowsHookEx((IntPtr)HookHelper.WH_Codes.WH_MOUSE_LL, MouseHookProcedure, IntPtr.Zero, id);
                    }
                }
            }
    
            /// <summary>
            /// 卸载鼠标钩子
            /// </summary>
            public void UnInstallHook(HookHelper.HookType hookType)
            {
                bool isSuccess = false;
                if (hookType == HookHelper.HookType.KeyOperation)//键盘钩子
                {
                    if (khook != IntPtr.Zero)
                    {
                        isSuccess = Win32API.UnhookWindowsHookEx(khook);
                        this.khook = IntPtr.Zero;
                    }
                }
                else
                {
                    if (this.hHook != IntPtr.Zero)//鼠标钩子
                    {
                        isSuccess = Win32API.UnhookWindowsHookEx(hHook);
                        this.hHook = IntPtr.Zero;
                    }
                }
                if (isSuccess)
                {
                    MessageBox.Show("卸载成功!");
                }
                else
                {
                    MessageBox.Show("卸载失败!");
                }
            }
    
            /// <summary>
            /// 鼠标钩子处理函数
            /// </summary>
            /// <param name="nCode"></param>
            /// <param name="wParam"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
            {
                if (nCode < (int)HookHelper.WH_Codes.HC_ACTION)
                {
                    return Win32API.CallNextHookEx(hHook, nCode, wParam, lParam);
                }
    
                if (OnMouseActivity != null)
                {
                    //Marshall the data from callback.
                    HookHelper.MouseHookStruct mouseHookStruct = (HookHelper.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(HookHelper.MouseHookStruct));
                    MouseButtons button = MouseButtons.None;
                    short mouseDelta = 0;
                    switch ((int)wParam)
                    {
                        case (int)HookHelper.WM_MOUSE.WM_LBUTTONDOWN:
                            //case WM_LBUTTONUP: 
                            //case WM_LBUTTONDBLCLK:
                            button = MouseButtons.Left;
                            break;
                        case (int)HookHelper.WM_MOUSE.WM_RBUTTONDOWN:
                            //case WM_RBUTTONUP: 
                            //case WM_RBUTTONDBLCLK: 
                            button = MouseButtons.Right;
                            break;
                        case (int)HookHelper.WM_MOUSE.WM_MOUSEWHEEL:
                            //button = MouseButtons.Middle;//滚动轮
                            //(value >> 16) & 0xffff; retrieves the high-order word from the given 32-bit value
                            mouseDelta = (short)((mouseHookStruct.MouseData >> 16) & 0xffff);
                            break;
                    }
    
                    int clickCount = 0;//点击数
                    if (button != MouseButtons.None)
                    {
                        if ((int)wParam == (int)HookHelper.WM_MOUSE.WM_LBUTTONDBLCLK || (int)wParam == (int)HookHelper.WM_MOUSE.WM_RBUTTONDBLCLK)
                        {
                            clickCount = 2;//双击
                        }
                        else
                        {
                            clickCount = 1;//单击
                        }
                    }
    
                    //鼠标事件传递数据
                    MouseEventArgs e = new MouseEventArgs(button, clickCount, mouseHookStruct.Point.X, mouseHookStruct.Point.Y, mouseDelta);
    
                    //重写事件
                    OnMouseActivity(this, e);
                }
    
                return Win32API.CallNextHookEx(hHook, nCode, wParam, lParam);
            }
    
            /// <summary>
            /// 键盘钩子处理函数
            /// </summary>
            /// <param name="code"></param>
            /// <param name="wParam"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            private int KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
            {
                try
                {
                    if (nCode < (int)HookHelper.WH_Codes.HC_ACTION)
                    {
                        return Win32API.CallNextHookEx((IntPtr)khook, nCode, wParam, lParam);
                    }
    
                    HookHelper.KeyboardHookStruct keyHookStruct = (HookHelper.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(HookHelper.KeyboardHookStruct));
    
                    #region
                    //if ((int)wParam == (int)Keys.C && ((int)lParam & (int)Keys.ControlKey) != 0 ||//Ctrl+C
                    //    (int)wParam == (int)Keys.X && ((int)lParam & (int)Keys.ControlKey) != 0)//Ctrl+V
                    //{
                    //    MessageBox.Show("C||V");
                    //}
    
                    //if (lParam.ToInt32() > 0)//捕获键盘按下
                    //{
                    //    Keys keys = (Keys)wParam;
                    //    MessageBox.Show("键盘按下");
                    //}
                    //if (lParam.ToInt32() < 0)//捕获键盘抬起
                    //{
                    //    MessageBox.Show("键盘抬起");
                    //}
                    /**************** 
                     //全局键盘钩子判断是否按下键 
                     wParam = = 0x100 // 键盘按下 
                     wParam = = 0x101 // 键盘抬起 
                    ****************/
                    //return 0;//如果返回1,则结束消息,消息截止,不再传递。如果返回0或调用CallNextHookEx函数,消息出这个钩子继续往下传递。
                    #endregion
    
                }
                catch
                {
    
                }
    
                return Win32API.CallNextHookEx(khook, nCode, wParam, lParam);
            }
        }
    }

    如果不好理解,将键盘、鼠标操作分离为两个文件分别封装:KeyHook.cs和MouseHook.cs
    KeyHook.cs文件:

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace TestHook.MyHook
    {
        class KeyHook
        {
            //定义钩子处理函数
            private Win32API.HookProc KeyboardProcDelegate = null;
            //定义钩子句柄
            private IntPtr khook;
            //定义键盘事件
            public event KeyEventHandler OnKeyDown;
    
            /// <summary>
            /// 安装钩子
            /// </summary>
            public void InstallHook()
            {
                if (khook == IntPtr.Zero)
                {
                    uint id = Win32API.GetCurrentThreadId();
                    this.KeyboardProcDelegate = new Win32API.HookProc(this.KeyboardProc);
                    khook = Win32API.SetWindowsHookEx((IntPtr)HookHelper.WH_Codes.WH_KEYBOARD_LL, this.KeyboardProcDelegate, IntPtr.Zero, id);
                }
            }
    
            /// <summary>
            /// 卸载钩子
            /// </summary>
            public void UnInstallHook()
            {
                bool isSuccess = false;
                if (khook != IntPtr.Zero)
                {
                    isSuccess=Win32API.UnhookWindowsHookEx(khook);
                    this.khook = IntPtr.Zero;
                }
                if (isSuccess)
                {
                    MessageBox.Show("卸载成功!");
                }
                else
                {
                    MessageBox.Show("卸载失败!");
                }
            }
    
            /// <summary>
            /// 键盘钩子处理函数
            /// </summary>
            /// <param name="code"></param>
            /// <param name="wParam"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            private int KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
            {
                try
                {
                    if (nCode < (int)HookHelper.WH_Codes.HC_ACTION)
                    {
                        return Win32API.CallNextHookEx((IntPtr)khook, nCode, wParam, lParam);
                    }
    
                    HookHelper.KeyboardHookStruct keyHookStruct = (HookHelper.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(HookHelper.KeyboardHookStruct));
    
                    #region
                    //if ((int)wParam == (int)Keys.C && ((int)lParam & (int)Keys.ControlKey) != 0 ||//Ctrl+C
                    //    (int)wParam == (int)Keys.X && ((int)lParam & (int)Keys.ControlKey) != 0)//Ctrl+V
                    //{
                    //    MessageBox.Show("C||V");
                    //}
    
                    //if (lParam.ToInt32() > 0)//捕获键盘按下
                    //{
                    //    Keys keys = (Keys)wParam;
                    //    MessageBox.Show("键盘按下");
                    //}
                    //if (lParam.ToInt32() < 0)//捕获键盘抬起
                    //{
                    //    MessageBox.Show("键盘抬起");
                    //}
                    /**************** 
                     //全局键盘钩子判断是否按下键 
                     wParam = = 0x100 // 键盘按下 
                     wParam = = 0x101 // 键盘抬起 
                    ****************/
                    //return 0;//如果返回1,则结束消息,消息截止,不再传递。如果返回0或调用CallNextHookEx函数,消息出这个钩子继续往下传递。
                    #endregion  
                    bool handled = false;
                    if (this.OnKeyDown != null && (wParam == (IntPtr)HookHelper.WM_KEYBOARD.WM_KEYDOWN|| wParam == (IntPtr)HookHelper.WM_KEYBOARD.WM_SYSKEYDOWN))
                    {
                        Keys keyData = (Keys)keyHookStruct.VKCode;
                        KeyEventArgs e = new KeyEventArgs(keyData);
                        OnKeyDown.Invoke(this, e);
                        handled = e.Handled;
                    }
    
                    if (handled)
                        return -1;
    
                    return Win32API.CallNextHookEx(khook, nCode, wParam, lParam);
                }
                catch
                {
    
                }
    
                return Win32API.CallNextHookEx(khook, nCode, wParam, lParam);
            }
        }
    }

    MouseHook.cs文件:

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace TestHook.MyHook
    {
        public class MouseHook
        {
            #region 定义变量
            //定义钩子处理函数
            private Win32API.HookProc MouseHookProcedure;
            //定义钩子句柄
            private IntPtr hHook = IntPtr.Zero;
            //定义鼠标事件
            public event MouseEventHandler OnMouseActivity;
            #endregion
    
            /// <summary>
            /// 安装鼠标钩子
            /// </summary>
            public void InstallHook()
            {
                if (hHook == IntPtr.Zero)
                {
                    uint id = Win32API.GetCurrentThreadId();
                    this.MouseHookProcedure = new Win32API.HookProc(this.MouseHookProc);
                    //这里挂节钩子
                    hHook = Win32API.SetWindowsHookEx((IntPtr)HookHelper.WH_Codes.WH_MOUSE_LL, MouseHookProcedure, IntPtr.Zero, id);
                }
            }
    
            /// <summary>
            /// 卸载鼠标钩子
            /// </summary>
            public void UnInstallHook()
            {
                bool isSuccess = false;
                if (this.hHook != IntPtr.Zero)
                {
                    isSuccess = Win32API.UnhookWindowsHookEx(hHook);
                    this.hHook = IntPtr.Zero;
                }
                if (isSuccess)
                {
                    MessageBox.Show("卸载成功!");
                }
                else
                {
                    MessageBox.Show("卸载失败!"); 
                }
            }
    
            /// <summary>
            /// 鼠标钩子处理函数
            /// </summary>
            /// <param name="nCode"></param>
            /// <param name="wParam"></param>
            /// <param name="lParam"></param>
            /// <returns></returns>
            private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
            {
                if (nCode < (int)HookHelper.WH_Codes.HC_ACTION)
                {
                    return Win32API.CallNextHookEx(hHook, nCode, wParam, lParam);
                }
    
                if (OnMouseActivity != null)
                {
                    //Marshall the data from callback.
                    HookHelper.MouseHookStruct mouseHookStruct = (HookHelper.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(HookHelper.MouseHookStruct));
                    MouseButtons button = MouseButtons.None;
                    short mouseDelta = 0;
                    switch ((int)wParam)
                    {
                        case (int)HookHelper.WM_MOUSE.WM_LBUTTONDOWN:
                            //case WM_LBUTTONUP: 
                            //case WM_LBUTTONDBLCLK:
                            button = MouseButtons.Left;
                            break;
                        case (int)HookHelper.WM_MOUSE.WM_RBUTTONDOWN:
                            //case WM_RBUTTONUP: 
                            //case WM_RBUTTONDBLCLK: 
                            button = MouseButtons.Right;
                            break;
                        case (int)HookHelper.WM_MOUSE.WM_MOUSEWHEEL:
                            //button = MouseButtons.Middle;//滚动轮
                            //(value >> 16) & 0xffff; retrieves the high-order word from the given 32-bit value
                            mouseDelta = (short)((mouseHookStruct.MouseData >> 16) & 0xffff);
                            break;
                    }
    
                    int clickCount = 0;//点击数
                    if (button != MouseButtons.None)
                    {
                        if (wParam == (IntPtr)HookHelper.WM_MOUSE.WM_LBUTTONDBLCLK || wParam == (IntPtr)HookHelper.WM_MOUSE.WM_RBUTTONDBLCLK)
                        {
                            clickCount = 2;//双击
                        }
                        else
                        {
                            clickCount = 1;//单击
                        }
                    }
    
                    //鼠标事件传递数据
                    MouseEventArgs e = new MouseEventArgs(button,clickCount,mouseHookStruct.Point.X,mouseHookStruct.Point.Y,mouseDelta);
    
                    //重写事件
                    OnMouseActivity(this, e);
                }
               
                return Win32API.CallNextHookEx(hHook, nCode, wParam, lParam);
            }
        }
    }

    4.对于Hook文件的调用,使用一个WinForm窗体做的测试,鼠标监控按钮、键盘监控按钮、停止监控按钮,一个RichTextBox显示监控日志,一个Label显示鼠标坐标监控:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using TestHook.MyHook;
    
    namespace TestHook
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private Hook hook = new Hook();//总钩子控制
            private KeyHook keyHook = new KeyHook();//键盘钩子        
            private MouseHook  mouseHook = new MouseHook();//鼠标钩子        
    
            private void Form1_Load(object sender, EventArgs e)
            {
                hook.OnMouseActivity += new MouseEventHandler(hook_OnMouseActivity);
                mouseHook.OnMouseActivity += new MouseEventHandler(mouseHook_OnMouseActivity);
                keyHook.OnKeyDown += new KeyEventHandler(keyHook_OnKeyDown);
            }
    
            void keyHook_OnKeyDown(object sender, KeyEventArgs e)
            {
                WriteLog("KeyDown     - " + e.KeyData.ToString());
            }
    
            void hook_OnMouseActivity(object sender, MouseEventArgs e)
            {
                this.lblMousePosition.Text = string.Format("X:{0} Y={1} Wheel={2}", e.X, e.Y, e.Delta);
                if (e.Clicks > 0)
                {
                    WriteLog("MouseButton   -" + e.Button.ToString());
                }
            }
           
            private void btnMouseHook_Click(object sender, EventArgs e)
            {           
                //mouseHook.InstallHook();
                hook.InstallHook(HookHelper.HookType.MouseOperation);
            }
    
            private void btnKeyHook_Click(object sender, EventArgs e)
            {            
                keyHook.InstallHook();
                //hook.InstallHook(HookHelper.HookType.KeyOperation);
            }
    
            private void btnUnIntallHook_Click(object sender, EventArgs e)
            {
                //mouseHook.UnInstallHook();
                //keyHook.UnInstallHook();
    
                hook.UnInstallHook(HookHelper.HookType.KeyOperation);//卸载键盘钩子
                hook.UnInstallHook(HookHelper.HookType.MouseOperation);//卸载鼠标钩子
            }
    
            private void WriteLog(string message)
            {
                if (string.IsNullOrWhiteSpace(this.richMessage.Text))
                {
                    this.richMessage.Text = "监控鼠标和键盘操作记录:" + Environment.NewLine;
                }
                this.richMessage.AppendText(message + Environment.NewLine);
                this.richMessage.SelectionStart = this.richMessage.Text.Length;
            }
    
            void mouseHook_OnMouseActivity(object sender, MouseEventArgs e)
            {
                this.lblMousePosition.Text = string.Format("X:{0} Y={1} Wheel={2}",e.X,e.Y,e.Delta);
                if (e.Clicks > 0)
                {
                    WriteLog("MouseButton   -"+e.Button.ToString());
                }
            }
    
            private void Form1_FormClosed(object sender, FormClosedEventArgs e)
            {
                hook.UnInstallHook(HookHelper.HookType.KeyOperation);//卸载键盘钩子
                hook.UnInstallHook(HookHelper.HookType.MouseOperation);//卸载鼠标钩子
            }
        }
    }

    代码整理,模拟数据:来自蓝天旭日的《C#钩子实现简单鼠标键盘的监控和屏蔽 》文章,其示例来自GermanyGeorge Mamaladze的开源代码:
    http://www.codeproject.com/KB/cs/globalhook.aspx

  • 相关阅读:
    as3 三行三列 布满9个为一个界面
    as3 判断鼠标移动方向
    求两点之间 的直线距离
    AS3 localToGlobal、globalToLocal方法的总结
    as3 TweenMax TweenLite方法
    禁止点击
    影片 发光 变色
    ASCII字符串互换
    关于C语言的书
    关于态度
  • 原文地址:https://www.cnblogs.com/SanMaoSpace/p/2935852.html
Copyright © 2020-2023  润新知