You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

HookHelper.cs 3.0 KiB

8 maanden geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // This code is distributed under MIT license.
  2. // Copyright (c) 2015 George Mamaladze
  3. // See license.txt or https://mit-license.org/
  4. using System;
  5. using System.ComponentModel;
  6. using System.Diagnostics;
  7. using System.Runtime.InteropServices;
  8. using Gma.System.MouseKeyHook.Implementation;
  9. namespace Gma.System.MouseKeyHook.WinApi
  10. {
  11. internal static class HookHelper
  12. {
  13. private static HookProcedure _appHookProc;
  14. private static HookProcedure _globalHookProc;
  15. public static HookResult HookAppMouse(Callback callback)
  16. {
  17. return HookApp(HookIds.WH_MOUSE, callback);
  18. }
  19. public static HookResult HookAppKeyboard(Callback callback)
  20. {
  21. return HookApp(HookIds.WH_KEYBOARD, callback);
  22. }
  23. public static HookResult HookGlobalMouse(Callback callback)
  24. {
  25. return HookGlobal(HookIds.WH_MOUSE_LL, callback);
  26. }
  27. public static HookResult HookGlobalKeyboard(Callback callback)
  28. {
  29. return HookGlobal(HookIds.WH_KEYBOARD_LL, callback);
  30. }
  31. private static HookResult HookApp(int hookId, Callback callback)
  32. {
  33. _appHookProc = (code, param, lParam) => HookProcedure(code, param, lParam, callback);
  34. var hookHandle = HookNativeMethods.SetWindowsHookEx(
  35. hookId,
  36. _appHookProc,
  37. IntPtr.Zero,
  38. ThreadNativeMethods.GetCurrentThreadId());
  39. if (hookHandle.IsInvalid)
  40. ThrowLastUnmanagedErrorAsException();
  41. return new HookResult(hookHandle, _appHookProc);
  42. }
  43. private static HookResult HookGlobal(int hookId, Callback callback)
  44. {
  45. _globalHookProc = (code, param, lParam) => HookProcedure(code, param, lParam, callback);
  46. var hookHandle = HookNativeMethods.SetWindowsHookEx(
  47. hookId,
  48. _globalHookProc,
  49. Process.GetCurrentProcess().MainModule.BaseAddress,
  50. 0);
  51. if (hookHandle.IsInvalid)
  52. ThrowLastUnmanagedErrorAsException();
  53. return new HookResult(hookHandle, _globalHookProc);
  54. }
  55. private static IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam, Callback callback)
  56. {
  57. var passThrough = nCode != 0;
  58. if (passThrough)
  59. return CallNextHookEx(nCode, wParam, lParam);
  60. var callbackData = new CallbackData(wParam, lParam);
  61. var continueProcessing = callback(callbackData);
  62. if (!continueProcessing)
  63. return new IntPtr(-1);
  64. return CallNextHookEx(nCode, wParam, lParam);
  65. }
  66. private static IntPtr CallNextHookEx(int nCode, IntPtr wParam, IntPtr lParam)
  67. {
  68. return HookNativeMethods.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
  69. }
  70. private static void ThrowLastUnmanagedErrorAsException()
  71. {
  72. var errorCode = Marshal.GetLastWin32Error();
  73. throw new Win32Exception(errorCode);
  74. }
  75. }
  76. }