winform键盘全局与线程Hook

  • A+
所属分类:.NET技术
摘要

注:idHook 钩子类型,即确定钩子监听何种消息
线程钩子监听键盘消息应设为2,全局钩子监听键盘消息应设为13
线程钩子监听鼠标消息应设为7,全局钩子监听鼠标消息应设为14


定义数据结构

        /// <summary>         /// 声明键盘钩子的封送结构类型         /// </summary>         [StructLayout(LayoutKind.Sequential)]         public class KeyboardHookStruct         {             public int vkCode;//表示一个1到254间的虚拟键盘码             public int scanCode;//表示硬件扫描码             public int flags;             public int time;             public int dwExtraInfo;         }

声明Hook相关方法

        //使用WINDOWS API函数代替获取当前实例的函数,防止钩子失效         [DllImport("kernel32.dll")]         public static extern IntPtr GetModuleHandle(string lpModuleName);         //安装钩子         [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 int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);         //卸载钩子         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]         public static extern bool UnhookWindowsHookEx(int idHook);         // 取得当前线程编号(线程钩子需要用到)         [DllImport("kernel32.dll")]         static extern int GetCurrentThreadId();

Hook拦截方法

全局Hook

        private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)         {             if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))             {                 KeyboardHookStruct MyKBHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));                   //引发OnKeyDownEvent                 if (OnKeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))                 {                     Keys keyData = (Keys)MyKBHookStruct.vkCode;                     KeyEventArgs e = new KeyEventArgs(keyData);                     OnKeyDownEvent(this, e);                 }             }             return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);         }

线程Hook

 private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)         {             if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))             {                                 //引发OnKeyDownEvent                 if (OnKeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))                 {                     Keys keyData = (Keys)wParam;                     KeyEventArgs e = new KeyEventArgs(keyData);                     OnKeyDownEvent(this, e);                 }             }             return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);         }

全局/线程Hook参数结构区别

线程Hook KeyboardHookProc函数的各个参数意义如下:  nCode    消息的类型,分HC_ACTION和HC_NOREMOVE  wParam    按键的虚拟键码   lParam    按键的相关参数信息,包括重复时间、按键的状态(按下或弹起)等  全局Hook KeyboardHookProc函数的各个参数意义如下:  nCode    消息的类型,有HC_ACTION  wParam    按键的状态(按下或弹起)WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN、WM_SYSKEYUP  lParam    指向KeyboardHookStruct结构的指针,该结构包含了按键的详细信息。

添加Hook

全局Hook

        public void Start()         {             if (hKeyboardHook == 0)             {                 KeyboardHookProcedure = new HookProc(KeyboardHookProc);                 using (System.Diagnostics.Process curProcess = System.Diagnostics.Process.GetCurrentProcess())                 using (System.Diagnostics.ProcessModule curModule = curProcess.MainModule)                     hKeyboardHook = SetWindowsHookEx(13, KeyboardHookProcedure, GetModuleHandle(curModule.ModuleName), 0);                   if (hKeyboardHook == 0)                 {                     Stop();                     throw new Exception("Set GlobalKeyboardHook failed!");                 }             }         }

线程Hook

   public void Start()         {             if (hKeyboardHook == 0)             {                 KeyboardHookProcedure = new HookProc(KeyboardHookProc);                 hKeyboardHook = SetWindowsHookEx(2, KeyboardHookProcedure,  IntPtr.Zero, GetCurrentThreadId());                   if (hKeyboardHook == 0)                 {                     Stop();                     throw new Exception("Set GlobalKeyboardHook failed!");                 }             }         }

注:idHook 钩子类型,即确定钩子监听何种消息
线程钩子监听键盘消息应设为2,全局钩子监听键盘消息应设为13
线程钩子监听鼠标消息应设为7,全局钩子监听鼠标消息应设为14