关于最近给一家企业做的文档保全系统的技术整理(3)
4、全局键盘钩子
如果程序需要监视键盘的按键动作,那么最好的方法就是使用键盘钩子程序。
钩子程序首先需要一个键盘钩子结构体
code //键盘钩子结构体 [StructLayout(LayoutKind.Sequential)] public struct KeyBoardDllHookStruct { public int vkCode; public int scanCode; public int flags; public int time; public int dwExtraInfo; }
code //键盘钩子事件 public class KeyboardHookEventArgs : System.EventArgs { private string keyName; private int keyCode; private bool passThrough; /// <summary> /// The name of the key that was pressed. /// </summary> public string KeyName { get { return keyName; } } public int KeyCode { get { return keyCode; } } public bool PassThrough { get { return passThrough; } } public KeyboardHookEventArgs(int evtKeyCode, bool evtPassThrough) { keyName = ((Keys)evtKeyCode).ToString(); keyCode = evtKeyCode; passThrough = evtPassThrough; } }
钩子:
code public class KeyBoardHook { private static IntPtr hookID = IntPtr.Zero; private const int WM_KEYDOWN = 0x0100; private const int WM_KEYUP = 0x0101; private const int WH_KEYBOARD_LL = 13; private const int WM_SYSKEYDOWN = 0x0104; private const int WM_SYSKEYUP = 0x0105; private static bool PassAllKeysToNextApp = true; public delegate IntPtr HookHandlerDelegate(int nCode, IntPtr wParam, ref KeyBoardDllHookStruct lParam); public delegate void KeyboardHookEventHandler(KeyboardHookEventArgs e); public static event KeyboardHookEventHandler KeyDownEvent; public static event KeyboardHookEventHandler KeyUpEvent; private static HookHandlerDelegate proc; private delegate IntPtr HookProc( int nCode, IntPtr wParam, ref KeyBoardDllHookStruct lParam ); //注册键盘钩子 public static void KeyBoardDllHookStart() { proc = new HookHandlerDelegate(HookCallback); using (Process curProcess = Process.GetCurrentProcess()) { using (ProcessModule curModule = curProcess.MainModule) { hookID = Win32API.SetWindowsHookEx(WH_KEYBOARD_LL, proc, Win32API.GetModuleHandle(curModule.ModuleName), 0); } } } //卸载键盘钩子 public static void KeyBoardDllHookStop() { if (hookID != IntPtr.Zero) { Win32API.UnhookWindowsHookEx(hookID); } } //激发事件 private static void OnKeyDown(KeyboardHookEventArgs e) { if (KeyDownEvent != null) KeyDownEvent(e); } //激发事件 private static void OnKeyUp(KeyboardHookEventArgs e) { if (KeyUpEvent != null) KeyUpEvent(e); } private static IntPtr HookCallback(int nCode, IntPtr wParam, ref KeyBoardDllHookStruct lParam) { bool AllowKey = PassAllKeysToNextApp; //过滤wParam的KeyDown事件 if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)) { AllowKey = true; OnKeyDown(new KeyboardHookEventArgs(lParam.vkCode, AllowKey)); if (AllowKey) { return Win32API.CallNextHookEx(hookID, nCode, wParam, ref lParam); } else { return (System.IntPtr)1; } } //过滤wParam的KeyUp事件 if (nCode >= 0 && (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)) { AllowKey = true; ; OnKeyUp(new KeyboardHookEventArgs(lParam.vkCode, AllowKey)); if (AllowKey) { return Win32API.CallNextHookEx(hookID, nCode, wParam, ref lParam); } else { return (System.IntPtr)1; } } return Win32API.CallNextHookEx(hookID, nCode, wParam, ref lParam); } }
该类提供了两个事件KeyDownEvent和KeyUpEvent分别在按下和释放时激发,大家可以通过这两个事件添加自己的处理程序。
在程序的适当入口通过调用该类的KeyBoardDllHookStart方法注册该钩子程序。关闭的时候调用KeyBoardDllHookStop方法卸载钩子。
例如:我在程序主窗体的构造函数中注册
code //注册键盘钩子 KeyBoardHook.KeyBoardDllHookStart(); KeyBoardHook.KeyDownEvent += new KeyBoardHook.KeyboardHookEventHandler(KeyBoardHook_KeyDownEvent); KeyBoardHook.KeyUpEvent += new KeyBoardHook.KeyboardHookEventHandler(KeyBoardHook_KeyUpEvent);
浙公网安备 33010602011771号