HookApi.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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
  11. {
  12. class HookApi
  13. {
  14. delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
  15. // 导入用户32位API函数
  16. [DllImport("user32.dll", SetLastError = true)]
  17. static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
  18. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  19. static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
  20. // 导入用户32位API函数
  21. [DllImport("user32.dll", SetLastError = true)]
  22. static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
  23. [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  24. static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
  25. [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  26. static extern int GetWindowTextLength(IntPtr hWnd);
  27. [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  28. static extern bool IsWindowVisible(IntPtr hWnd);
  29. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  30. static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
  31. public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
  32. public HookProc _hookProc;
  33. public IntPtr _hHook;
  34. public ManualResetEvent _windowCreatedEvent = new ManualResetEvent(false);
  35. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  36. private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
  37. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  38. [return: MarshalAs(UnmanagedType.Bool)]
  39. private static extern bool UnhookWindowsHookEx(IntPtr hhk);
  40. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  41. private static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
  42. [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  43. private static extern IntPtr GetModuleHandle(string lpModuleName);
  44. [DllImport("kernel32.dll", SetLastError = true)]
  45. private static extern uint GetLastError();
  46. public HookApi()
  47. {
  48. Global.writeLog("创建HookAPI");
  49. _hookProc = new HookProc(HookCallback);
  50. IntPtr hInstance = GetModuleHandle(null);
  51. Global.writeLog($"hInstance:{hInstance}");
  52. _hHook = SetWindowsHookEx(WH_CBT, _hookProc, hInstance, 0); // 设置全局钩子
  53. if (_hHook == IntPtr.Zero)
  54. {
  55. uint lastError = GetLastError();
  56. Global.writeLog($"Failed to set hook. Error code: {lastError}");
  57. return;
  58. }
  59. // 启动消息循环
  60. Application.Run(new Form()); // 使用一个空的Form来启动消息循环
  61. }
  62. const uint WM_KEYDOWN = 0x100;
  63. const uint WM_KEYUP = 0x101;
  64. const int VK_CONTROL = 0x11; // Ctrl键
  65. const int VK_A = 0x41; // A键
  66. const int VK_R = 0x52;
  67. const int VK_P = 0x50;
  68. const int VK_S = 0x53;
  69. const int VK_F = 0x46;
  70. const int VK_C = 0x43;
  71. const int WH_CBT = 5;
  72. const int HCBT_CREATEWND = 3;
  73. const uint WM_CLOSE = 0x0010;
  74. public int HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
  75. {
  76. Global.writeLog($"创建HookCallback:{nCode}" );
  77. if (nCode < 0)
  78. {
  79. return CallNextHookEx(_hHook, nCode, wParam, lParam);
  80. }
  81. if (nCode == HCBT_CREATEWND)
  82. {
  83. IntPtr hWnd = wParam;
  84. if (IsTargetWindow(hWnd))
  85. {
  86. Global.writeLog("检测到身份识别窗口且成功获取句柄");
  87. // 窗口创建成功,执行操作
  88. OperateYHControl((int)hWnd, "身份识别");
  89. // 设置事件,通知主线程窗口已创建
  90. _windowCreatedEvent.Set();
  91. // 可以选择关闭窗口
  92. SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
  93. // 移除钩子
  94. UnhookWindowsHookEx(_hHook);
  95. }
  96. }
  97. return CallNextHookEx(_hHook, nCode, wParam, lParam);
  98. }
  99. private bool IsTargetWindow(IntPtr hWnd)
  100. {
  101. // 根据窗口标题判断是否为目标窗口
  102. const string targetWindowTitle = "身份识别";
  103. StringBuilder sb = new StringBuilder(256);
  104. GetWindowText(hWnd, sb, sb.Capacity);
  105. return sb.ToString() == targetWindowTitle;
  106. }
  107. public void OperateYHControl(int key,string title)
  108. {
  109. //// 获取窗口句柄
  110. //IntPtr hWnd = FindWindow(null, title); // 替换为实际的窗口标题
  111. // 枚举所有顶级窗口
  112. IntPtr hWnd = FindWindowByPartialTitle(title); // 替换为实际的部分窗口标题
  113. if (hWnd != IntPtr.Zero)
  114. {
  115. Global.writeLog("找到了窗口,句柄: " + hWnd.ToString());
  116. // 发送单快捷键
  117. SendShortcutKey(hWnd, key);
  118. }
  119. else
  120. {
  121. Global.writeLog("未找到窗口" + title);
  122. }
  123. }
  124. private void SendShortcutKey(IntPtr hWnd, int key)
  125. {
  126. // 按下A键
  127. PostMessage(hWnd, WM_KEYDOWN, (IntPtr)key, IntPtr.Zero);
  128. // 释放A键
  129. PostMessage(hWnd, WM_KEYUP, (IntPtr)key, IntPtr.Zero);
  130. }
  131. private void SendShortcutKey(IntPtr hWnd, int controlKey, int key)
  132. {
  133. // 按下Ctrl键
  134. PostMessage(hWnd, WM_KEYDOWN, (IntPtr)controlKey, IntPtr.Zero);
  135. // 按下A键
  136. PostMessage(hWnd, WM_KEYDOWN, (IntPtr)key, IntPtr.Zero);
  137. // 释放A键
  138. PostMessage(hWnd, WM_KEYUP, (IntPtr)key, IntPtr.Zero);
  139. // 释放Ctrl键
  140. PostMessage(hWnd, WM_KEYUP, (IntPtr)controlKey, IntPtr.Zero);
  141. }
  142. private IntPtr FindWindowByPartialTitle(string partialTitle)
  143. {
  144. IntPtr hWnd = IntPtr.Zero;
  145. EnumWindows((hWndIter, lParam) =>
  146. {
  147. if (IsWindowVisible(hWndIter))
  148. {
  149. int length = GetWindowTextLength(hWndIter);
  150. StringBuilder sb = new StringBuilder(length + 1);
  151. GetWindowText(hWndIter, sb, sb.Capacity);
  152. string windowText = sb.ToString();
  153. if (windowText.Contains(partialTitle))
  154. {
  155. hWnd = hWndIter;
  156. return false; // 停止枚举
  157. }
  158. }
  159. return true; // 继续枚举
  160. }, IntPtr.Zero);
  161. return hWnd;
  162. }
  163. }
  164. }