using System; using System.Diagnostics; using System.Runtime.InteropServices; using HandyControl.Data; using HandyControl.Tools.Interop; namespace HandyControl.Tools; public class KeyboardHook { public static event EventHandler KeyDown; public static event EventHandler KeyUp; private static IntPtr HookId = IntPtr.Zero; private static readonly InteropValues.HookProc Proc = HookCallback; private static int VirtualKey; private static readonly IntPtr KeyDownIntPtr = (IntPtr) InteropValues.WM_KEYDOWN; private static readonly IntPtr KeyUpIntPtr = (IntPtr) InteropValues.WM_KEYUP; private static readonly IntPtr SyskeyDownIntPtr = (IntPtr) InteropValues.WM_SYSKEYDOWN; private static readonly IntPtr SyskeyUpIntPtr = (IntPtr) InteropValues.WM_SYSKEYUP; private static int Count; public static void Start() { if (HookId == IntPtr.Zero) { HookId = SetHook(Proc); } if (HookId != IntPtr.Zero) { Count++; } } public static void Stop() { Count--; if (Count < 1) { InteropMethods.UnhookWindowsHookEx(HookId); HookId = IntPtr.Zero; } } private static IntPtr SetHook(InteropValues.HookProc proc) { using var curProcess = Process.GetCurrentProcess(); using var curModule = curProcess.MainModule; if (curModule != null) { return InteropMethods.SetWindowsHookEx((int) InteropValues.HookType.WH_KEYBOARD_LL, proc, InteropMethods.GetModuleHandle(curModule.ModuleName), 0); } return IntPtr.Zero; } private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0) { if (wParam == KeyDownIntPtr) { var virtualKey = Marshal.ReadInt32(lParam); if (VirtualKey != virtualKey) { VirtualKey = virtualKey; KeyDown?.Invoke(null, new KeyboardHookEventArgs(virtualKey, false)); } } else if (wParam == SyskeyDownIntPtr) { var virtualKey = Marshal.ReadInt32(lParam); if (VirtualKey != virtualKey) { VirtualKey = virtualKey; KeyDown?.Invoke(null, new KeyboardHookEventArgs(virtualKey, true)); } } else if (wParam == KeyUpIntPtr) { var virtualKey = Marshal.ReadInt32(lParam); VirtualKey = -1; KeyUp?.Invoke(null, new KeyboardHookEventArgs(virtualKey, false)); } else if (wParam == SyskeyUpIntPtr) { var virtualKey = Marshal.ReadInt32(lParam); VirtualKey = -1; KeyUp?.Invoke(null, new KeyboardHookEventArgs(virtualKey, true)); } } return InteropMethods.CallNextHookEx(HookId, nCode, wParam, lParam); } }