WindowsHook.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. namespace HZH_Controls
  7. {
  8. /// <summary>
  9. /// 钩子类型
  10. /// </summary>
  11. public enum HookType : int
  12. {
  13. /// <summary>
  14. /// 安装一个钩子过程,该过程监视由于对话框,消息框,菜单或滚动条中的输入事件而生成的消息。
  15. /// 有关更多信息,请参阅MessageProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644987(v=vs.85))挂接过程。
  16. /// </summary>
  17. WH_MSGFILTER = -1,
  18. /// <summary>
  19. /// 安装一个钩子过程,记录发布到系统消息队列的输入消息。 此挂钩对于录制宏非常有用。
  20. /// 有关更多信息,请参阅JournalRecordProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644983(v=vs.85))挂钩过程。
  21. /// </summary>
  22. WH_JOURNALRECORD = 0,
  23. /// <summary>
  24. /// 安装一个挂钩过程,该过程发布先前由WH_JOURNALRECORD挂钩过程记录的消息。
  25. /// 有关更多信息,请参阅JournalPlaybackProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644982(v=vs.85))挂钩过程。
  26. /// </summary>
  27. WH_JOURNALPLAYBACK = 1,
  28. /// <summary>
  29. /// 安装一个监视击键消息的钩子程序。
  30. /// 有关更多信息,请参阅KeyboardProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644984(v=vs.85))挂钩过程。
  31. /// </summary>
  32. WH_KEYBOARD = 2,
  33. /// <summary>
  34. /// 安装一个钩子过程来监视发布到消息队列的消息。
  35. /// 有关更多信息,请参阅GetMsgProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644981(v=vs.85))挂接过程。
  36. /// </summary>
  37. WH_GETMESSAGE = 3,
  38. /// <summary>
  39. /// 安装一个钩子过程,在系统将消息发送到目标窗口过程之前监视消息。
  40. /// 有关更多信息,请参阅CallWndProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644975(v=vs.85))挂接过程。
  41. /// </summary>
  42. WH_CALLWNDPROC = 4,
  43. /// <summary>
  44. /// 安装一个钩子程序,接收对CBT应用程序有用的通知。
  45. /// 有关更多信息,请参阅CBTProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644977(v=vs.85))挂钩过程。
  46. /// </summary>
  47. WH_CBT = 5,
  48. /// <summary>
  49. /// 安装一个钩子过程,该过程监视由于对话框,消息框,菜单或滚动条中的输入事件而生成的消息。
  50. /// 钩子过程监视与调用线程在同一桌面中的所有应用程序的这些消息。
  51. /// 有关更多信息,请参阅SysMsgProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644992(v=vs.85))挂接过程。
  52. /// </summary>
  53. WH_SYSMSGFILTER = 6,
  54. /// <summary>
  55. /// 安装监视鼠标消息的钩子过程。
  56. /// 有关更多信息,请参阅MouseProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644988(v=vs.85))挂钩过程。
  57. /// </summary>
  58. WH_MOUSE = 7,
  59. /// <summary>
  60. /// 安装一个用于调试其他钩子过程的钩子过程。
  61. /// 有关更多信息,请参阅DebugProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644978(v=vs.85))挂接过程。
  62. /// </summary>
  63. WH_DEBUG = 9,
  64. /// <summary>
  65. /// 安装一个钩子过程,接收对shell应用程序有用的通知。
  66. /// 有关更多信息,请参阅ShellProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644991(v=vs.85))挂钩过程。
  67. /// </summary>
  68. WH_SHELL = 10,
  69. /// <summary>
  70. /// 安装一个钩子过程,当应用程序的前台线程即将变为空闲时将调用该过程。
  71. /// 此挂钩对于在空闲时执行低优先级任务非常有用。
  72. /// 有关更多信息,请参阅ForegroundIdleProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644980(v=vs.85))挂钩过程。
  73. /// </summary>
  74. WH_FOREGROUNDIDLE = 11,
  75. /// <summary>
  76. /// 安装一个钩子过程,该过程在目标窗口过程处理完消息后对其进行监视。
  77. /// 有关更多信息,请参阅CallWndRetProc(https://docs.microsoft.com/windows/desktop/api/winuser/nc-winuser-hookproc)挂接过程。
  78. /// </summary>
  79. WH_CALLWNDPROCRET = 12,
  80. /// <summary>
  81. /// 安装一个监视低级键盘输入事件的钩子过程。 有关更多信息,
  82. /// 请参阅LowLevelKeyboardProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644985(v=vs.85))挂接过程。
  83. /// </summary>
  84. WH_KEYBOARD_LL = 13,
  85. /// <summary>
  86. /// 安装一个监视低级鼠标输入事件的钩子过程。 有关更多信息,
  87. /// 请参阅LowLevelMouseProc(https://docs.microsoft.com/previous-versions/windows/desktop/legacy/ms644986(v=vs.85))挂接过程。
  88. /// </summary>
  89. WH_MOUSE_LL = 14,
  90. }
  91. public class WindowsHook
  92. {
  93. public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
  94. // 装置钩子的函数
  95. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  96. public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, int hInstance, int threadId);
  97. // 卸下钩子的函数
  98. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  99. public static extern bool UnhookWindowsHookEx(int idHook);
  100. // 下一个钩挂的函数
  101. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  102. public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
  103. [DllImport("User32.dll", CharSet = CharSet.Auto)]
  104. public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
  105. /// <summary>
  106. /// Delegate HookMsgHandler
  107. /// </summary>
  108. /// <param name="strHookName">钩子名称</param>
  109. /// <param name="msg">消息值</param>
  110. public delegate void HookMsgHandler(string strHookName, int nCode, IntPtr msg, IntPtr lParam);
  111. /// <summary>
  112. /// 钩子消息事件
  113. /// </summary>
  114. public static event HookMsgHandler HookMsgChanged;
  115. /// <summary>
  116. /// 启动一个钩子
  117. /// </summary>
  118. /// <param name="hookType">钩子类型</param>
  119. /// <param name="wParam">模块句柄,为空则为当前模块</param>
  120. /// <param name="pid">进程句柄,默认为0则表示当前进程</param>
  121. /// <param name="strHookName">钩子名称</param>
  122. /// <returns>钩子句柄(消耗钩子时需要使用)</returns>
  123. /// <exception cref="Exception">SetWindowsHookEx failed.</exception>
  124. public static int StartHook(HookType hookType, int wParam = 0, int pid = 0, string strHookName = "")
  125. {
  126. int _hHook = 0;
  127. // 生成一个HookProc的实例.
  128. var _hookProcedure = new HookProc((nCode, msg, lParam) =>
  129. {
  130. if (HookMsgChanged != null)
  131. {
  132. try
  133. {
  134. HookMsgChanged(strHookName, nCode, msg, lParam);
  135. }
  136. catch { }
  137. }
  138. int inext = CallNextHookEx(_hHook, nCode, msg, lParam);
  139. return inext;
  140. });
  141. if (pid ==0)
  142. pid = AppDomain.GetCurrentThreadId();
  143. _hHook = SetWindowsHookEx((int)hookType, _hookProcedure, wParam, pid);
  144. //假设装置失败停止钩子
  145. if (_hHook == 0)
  146. {
  147. StopHook(_hHook);
  148. }
  149. return _hHook;
  150. }
  151. /// <summary>
  152. /// 停止钩子
  153. /// </summary>
  154. /// <param name="_hHook">StartHook函数返回的钩子句柄</param>
  155. /// <returns><c>true</c> if 停止成功, <c>false</c> 否则.</returns>
  156. public static bool StopHook(int _hHook)
  157. {
  158. bool ret = true;
  159. if (_hHook != 0)
  160. {
  161. ret = UnhookWindowsHookEx(_hHook);
  162. }
  163. // 假设卸下钩子失败
  164. if (!ret)
  165. return false;
  166. return true;
  167. }
  168. }
  169. }