KeyboardHook.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. using System;
  2. using System.Diagnostics;
  3. using System.Runtime.InteropServices;
  4. using HandyControl.Data;
  5. using HandyControl.Tools.Interop;
  6. namespace HandyControl.Tools;
  7. public class KeyboardHook
  8. {
  9. public static event EventHandler<KeyboardHookEventArgs> KeyDown;
  10. public static event EventHandler<KeyboardHookEventArgs> KeyUp;
  11. private static IntPtr HookId = IntPtr.Zero;
  12. private static readonly InteropValues.HookProc Proc = HookCallback;
  13. private static int VirtualKey;
  14. private static readonly IntPtr KeyDownIntPtr = (IntPtr) InteropValues.WM_KEYDOWN;
  15. private static readonly IntPtr KeyUpIntPtr = (IntPtr) InteropValues.WM_KEYUP;
  16. private static readonly IntPtr SyskeyDownIntPtr = (IntPtr) InteropValues.WM_SYSKEYDOWN;
  17. private static readonly IntPtr SyskeyUpIntPtr = (IntPtr) InteropValues.WM_SYSKEYUP;
  18. private static int Count;
  19. public static void Start()
  20. {
  21. if (HookId == IntPtr.Zero)
  22. {
  23. HookId = SetHook(Proc);
  24. }
  25. if (HookId != IntPtr.Zero)
  26. {
  27. Count++;
  28. }
  29. }
  30. public static void Stop()
  31. {
  32. Count--;
  33. if (Count < 1)
  34. {
  35. InteropMethods.UnhookWindowsHookEx(HookId);
  36. HookId = IntPtr.Zero;
  37. }
  38. }
  39. private static IntPtr SetHook(InteropValues.HookProc proc)
  40. {
  41. using var curProcess = Process.GetCurrentProcess();
  42. using var curModule = curProcess.MainModule;
  43. if (curModule != null)
  44. {
  45. return InteropMethods.SetWindowsHookEx((int) InteropValues.HookType.WH_KEYBOARD_LL, proc,
  46. InteropMethods.GetModuleHandle(curModule.ModuleName), 0);
  47. }
  48. return IntPtr.Zero;
  49. }
  50. private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
  51. {
  52. if (nCode >= 0)
  53. {
  54. if (wParam == KeyDownIntPtr)
  55. {
  56. var virtualKey = Marshal.ReadInt32(lParam);
  57. if (VirtualKey != virtualKey)
  58. {
  59. VirtualKey = virtualKey;
  60. KeyDown?.Invoke(null, new KeyboardHookEventArgs(virtualKey, false));
  61. }
  62. }
  63. else if (wParam == SyskeyDownIntPtr)
  64. {
  65. var virtualKey = Marshal.ReadInt32(lParam);
  66. if (VirtualKey != virtualKey)
  67. {
  68. VirtualKey = virtualKey;
  69. KeyDown?.Invoke(null, new KeyboardHookEventArgs(virtualKey, true));
  70. }
  71. }
  72. else if (wParam == KeyUpIntPtr)
  73. {
  74. var virtualKey = Marshal.ReadInt32(lParam);
  75. VirtualKey = -1;
  76. KeyUp?.Invoke(null, new KeyboardHookEventArgs(virtualKey, false));
  77. }
  78. else if (wParam == SyskeyUpIntPtr)
  79. {
  80. var virtualKey = Marshal.ReadInt32(lParam);
  81. VirtualKey = -1;
  82. KeyUp?.Invoke(null, new KeyboardHookEventArgs(virtualKey, true));
  83. }
  84. }
  85. return InteropMethods.CallNextHookEx(HookId, nCode, wParam, lParam);
  86. }
  87. }