KeyboardHook.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Runtime.InteropServices;
  5. using System.Windows.Forms;
  6. namespace GUI.Hook
  7. {
  8. public class KeyboardHook : IHook
  9. {
  10. int hHook;
  11. Win32Api.HookProc KeyboardHookDelegate;
  12. public event KeyEventHandler OnKeyDownEvent;
  13. public event KeyEventHandler OnKeyUpEvent;
  14. public event KeyPressEventHandler OnKeyPressEvent;
  15. public KeyboardHook() { }
  16. public void SetHook()
  17. {
  18. KeyboardHookDelegate = new Win32Api.HookProc(KeyboardHookProc);
  19. Process cProcess = Process.GetCurrentProcess();
  20. ProcessModule cModule = cProcess.MainModule;
  21. var mh = Win32Api.GetModuleHandle(cModule.ModuleName);
  22. hHook = Win32Api.SetWindowsHookEx(Win32Api.WH_KEYBOARD_LL, KeyboardHookDelegate, mh, 0);
  23. }
  24. public void UnHook()
  25. {
  26. Win32Api.UnhookWindowsHookEx(hHook);
  27. }
  28. readonly List<Keys> preKeysList = new();
  29. int KeyboardHookProc(int nCode, int wParam, IntPtr lParam)
  30. {
  31. if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null))
  32. {
  33. Win32Api.KeyboardHookStruct KeyDataFromHook = (Win32Api.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.KeyboardHookStruct));
  34. Keys keyData = (Keys)KeyDataFromHook.vkCode;
  35. if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN))
  36. {
  37. if (IsCtrlAltShiftKeys(keyData) && preKeysList.IndexOf(keyData) == -1)
  38. {
  39. preKeysList.Add(keyData);
  40. }
  41. }
  42. if (OnKeyDownEvent != null && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN))
  43. {
  44. KeyEventArgs e = new(GetDownKeys(keyData));
  45. OnKeyDownEvent(this, e);
  46. }
  47. if (OnKeyPressEvent != null && wParam == Win32Api.WM_KEYDOWN)
  48. {
  49. byte[] keyState = new byte[256];
  50. _ = Win32Api.GetKeyboardState(keyState);
  51. byte[] inBuffer = new byte[2];
  52. if (Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1)
  53. {
  54. KeyPressEventArgs e = new((char)inBuffer[0]);
  55. OnKeyPressEvent(this, e);
  56. }
  57. }
  58. if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP))
  59. {
  60. if (IsCtrlAltShiftKeys(keyData))
  61. {
  62. for (int i = preKeysList.Count - 1; i >= 0; i--)
  63. {
  64. if (preKeysList[i] == keyData) { preKeysList.RemoveAt(i); }
  65. }
  66. }
  67. }
  68. if (OnKeyUpEvent != null && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP))
  69. {
  70. KeyEventArgs e = new(GetDownKeys(keyData));
  71. OnKeyUpEvent(this, e);
  72. }
  73. }
  74. return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
  75. }
  76. Keys GetDownKeys(Keys key)
  77. {
  78. Keys rtnKey = Keys.None;
  79. foreach (Keys i in preKeysList)
  80. {
  81. if (i == Keys.LControlKey || i == Keys.RControlKey) { rtnKey |= Keys.Control; }
  82. if (i == Keys.LMenu || i == Keys.RMenu) { rtnKey |= Keys.Alt; }
  83. if (i == Keys.LShiftKey || i == Keys.RShiftKey) { rtnKey |= Keys.Shift; }
  84. }
  85. return rtnKey | key;
  86. }
  87. static bool IsCtrlAltShiftKeys(Keys key)
  88. {
  89. if (key == Keys.LControlKey || key == Keys.RControlKey || key == Keys.LMenu || key == Keys.RMenu || key == Keys.LShiftKey || key == Keys.RShiftKey) { return true; }
  90. return false;
  91. }
  92. }
  93. }