HookManager.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. using PTMedicalInsurance.Variables;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. namespace PTMedicalInsurance.Common.Hook
  11. {
  12. public class HookManager
  13. {
  14. #region 钩子类型的枚举
  15. public const int WH_JOURNALRECORD = 0; //监视和记录输入事件。安装一个挂钩处理过程,对寄送至系统消息队列的输入消息进行纪录
  16. public const int WH_JOURNALPLAYBACK = 1; //回放用WH_JOURNALRECORD记录事件
  17. public const int WH_KEYBOARD = 2; //键盘钩子,键盘触发消息。WM_KEYUP或WM_KEYDOWN消息
  18. public const int WH_GETMESSAGE = 3; //发送到窗口的消息。GetMessage或PeekMessage触发
  19. public const int WH_CALLWNDPROC = 4; //发送到窗口的消息。由SendMessage触发
  20. public const int WH_CBT = 5; //当基于计算机的训练(CBT)事件发生时
  21. public const int WH_SYSMSGFILTER = 6; //同WH_MSGFILTER一样,系统范围的。
  22. public const int WH_MOUSE = 7; //鼠标钩子,查询鼠标事件消息
  23. public const int WH_HARDWARE = 8; //非鼠标、键盘消息时
  24. public const int WH_DEBUG = 9; //调试钩子,用来给钩子函数除错
  25. public const int WH_SHELL = 10; //外壳钩子,当关于WINDOWS外壳事件发生时触发.
  26. public const int WH_FOREGROUNDIDLE = 11; //前台应用程序线程变成空闲时候,钩子激活。
  27. public const int WH_CALLWNDPROCRET = 12; //发送到窗口的消息。由SendMessage处理完成返回时触发
  28. public const int WH_KEYBOARD_LL = 13; //此挂钩只能在Windows NT中被安装,用来对底层的键盘输入事件进行监视
  29. public const int WH_MOUSE_LL = 14; //此挂钩只能在Windows NT中被安装,用来对底层的鼠标输入事件进行监视
  30. public const int WM_MOUSEMOVE = 0x200;
  31. public const int WM_LBUTTONDOWN = 0x201;
  32. public const int WM_RBUTTONDOWN = 0x204;
  33. public const int WM_MBUTTONDOWN = 0x207;
  34. public const int WM_LBUTTONUP = 0x202;
  35. public const int WM_RBUTTONUP = 0x205;
  36. public const int WM_MBUTTONUP = 0x208;
  37. public const int WM_LBUTTONDBLCLK = 0x203;
  38. public const int WM_RBUTTONDBLCLK = 0x206;
  39. public const int WM_MBUTTONDBLCLK = 0x209;
  40. public const int WM_KEYDOWN = 256;
  41. #endregion
  42. public delegate int HookProc(int nCode, int wParam, IntPtr lParam);
  43. // 安装钩子
  44. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  45. public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
  46. // 卸载钩子
  47. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  48. public static extern bool UnhookWindowsHookEx(int idHook);
  49. // 继续下一个钩子
  50. [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  51. public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
  52. // 取得当前线程编号
  53. [DllImport("kernel32.dll")]
  54. static extern int GetCurrentThreadId();
  55. [DllImport("kernel32.dll", SetLastError = true)]
  56. private static extern uint GetLastError();
  57. [DllImport("kernel32.dll")]
  58. static extern IntPtr LoadLibrary(string lpFileName);
  59. [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  60. public static extern IntPtr GetModuleHandle(string lpModuleName);
  61. static int hMouseHook = 0;
  62. HookProc MouseHookProcedure;
  63. static int hKeyboardHook = 0;
  64. HookProc KeyboardHookProcedure;
  65. static int hWindowHook = 0;
  66. HookProc WindowHookProcedure;
  67. private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
  68. {
  69. if (nCode >= 0 && wParam == WM_KEYDOWN)
  70. {
  71. int vkCode = Marshal.ReadInt32(lParam); //按键ascii码
  72. if (vkCode.ToString() == "13")
  73. {
  74. MessageBox.Show("按了Enter");
  75. }
  76. //返回1 相当于屏蔽了Enter
  77. return 1;
  78. }
  79. return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
  80. }
  81. private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
  82. {
  83. if (nCode >= 0)
  84. {
  85. switch (wParam)
  86. {
  87. case WM_LBUTTONDOWN:
  88. MessageBox.Show("鼠标左键按下");
  89. break;
  90. case WM_LBUTTONUP:
  91. MessageBox.Show("鼠标左键抬起");
  92. break;
  93. case WM_LBUTTONDBLCLK:
  94. MessageBox.Show("鼠标左键双击");
  95. break;
  96. case WM_RBUTTONDOWN:
  97. MessageBox.Show("鼠标右键按下");
  98. break;
  99. case WM_RBUTTONUP:
  100. MessageBox.Show("鼠标右键抬起");
  101. break;
  102. case WM_RBUTTONDBLCLK:
  103. MessageBox.Show("鼠标右键双击");
  104. break;
  105. }
  106. }
  107. return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
  108. }
  109. private int WindowHookProc(int nCode, Int32 wParam, IntPtr lParam)
  110. {
  111. if (nCode >= 0)
  112. {
  113. switch (wParam)
  114. {
  115. case WH_CALLWNDPROC:
  116. Global.writeLog("窗体消息过程");
  117. break;
  118. case WH_CBT:
  119. Global.writeLog("窗体创建");
  120. break;
  121. default:
  122. Global.writeLog("窗体创建1");
  123. //Logger.writeLog($"{wParam}");
  124. break;
  125. }
  126. }
  127. return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
  128. }
  129. // 安装钩子
  130. public void HookStart(IntPtr hInstance,int threadId)
  131. {
  132. //hInstance = LoadLibrary("User32");
  133. if (hWindowHook == 0)
  134. {
  135. // 创建HookProc实例
  136. WindowHookProcedure = new HookProc(WindowHookProc);
  137. // 设置钩子
  138. hWindowHook = SetWindowsHookEx(WH_CBT, WindowHookProcedure, hInstance, threadId);
  139. // 如果设置钩子失败
  140. if (hWindowHook == 0)
  141. {
  142. uint lastError = GetLastError();
  143. HookStop();
  144. MessageBox.Show($"SetWindowsHookEx failed.Error code: {lastError}");
  145. //throw new Exception($"SetWindowsHookEx failed.Error code: {lastError}");
  146. }
  147. }
  148. //if (hKeyboardHook == 0)
  149. //{
  150. // // 创建HookProc实例
  151. // KeyboardHookProcedure = new HookProc(KeyboardHookProc);
  152. // // 设置钩子
  153. // hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, hInstance, 0);
  154. // // 如果设置钩子失败
  155. // if (hKeyboardHook == 0)
  156. // {
  157. // HookStop();
  158. // throw new Exception("SetWindowsHookEx failed.");
  159. // }
  160. //}
  161. //if (hMouseHook == 0)
  162. //{
  163. // MouseHookProcedure = new HookProc(MouseHookProc);
  164. // hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProcedure, hInstance, 0);
  165. // // 如果设置钩子失败
  166. // if (hMouseHook == 0)
  167. // {
  168. // HookStop();
  169. // throw new Exception("SetWindowsHookEx failed.");
  170. // }
  171. //}
  172. }
  173. // 卸载钩子
  174. public void HookStop()
  175. {
  176. bool retKeyboard = true;
  177. bool retMouse = true;
  178. if (hKeyboardHook != 0)
  179. {
  180. retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
  181. hKeyboardHook = 0;
  182. }
  183. if (hMouseHook != 0)
  184. {
  185. retMouse = UnhookWindowsHookEx(hMouseHook);
  186. hMouseHook = 0;
  187. }
  188. if (hWindowHook != 0)
  189. {
  190. retMouse = UnhookWindowsHookEx(hWindowHook);
  191. hWindowHook = 0;
  192. }
  193. if (!(retMouse && retKeyboard)) throw new Exception("UnhookWindowsHookEx failed.");
  194. }
  195. }
  196. }