- A+
所属分类:.NET技术
定义数据结构
/// <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