WndHelper.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. namespace PTMedicalInsurance.Common.WinAPI
  10. {
  11. class WndHelper
  12. {
  13. // 发送按键的方法(根据你的需求)
  14. [DllImport("user32.dll")]
  15. public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
  16. // <summary>
  17. /// 枚举窗口时的委托参数
  18. /// </summary>
  19. /// <param name="hWnd"></param>
  20. /// <param name="lParam"></param>
  21. /// <returns></returns>
  22. public delegate bool WndEnumProc(IntPtr hWnd, int lParam);
  23. /// <summary>
  24. /// 枚举所有窗口
  25. /// </summary>
  26. /// <param name="lpEnumFunc"></param>
  27. /// <param name="lParam"></param>
  28. /// <returns></returns>
  29. [DllImport("user32")]
  30. public static extern bool EnumWindows(WndEnumProc lpEnumFunc, int lParam);
  31. /// <summary>
  32. /// 获取窗口的父窗口句柄
  33. /// </summary>
  34. /// <param name="hWnd"></param>
  35. /// <returns></returns>
  36. [DllImport("user32")]
  37. public static extern IntPtr GetParent(IntPtr hWnd);
  38. [DllImport("user32")]
  39. public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
  40. [DllImport("user32")]
  41. public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
  42. [DllImport("user32")]
  43. public static extern bool GetWindowRect(IntPtr hWnd, ref LPRECT rect);
  44. [DllImport("user32.dll")]
  45. public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint wFlags);
  46. [StructLayout(LayoutKind.Sequential)]
  47. public readonly struct LPRECT
  48. {
  49. public readonly int Left;
  50. public readonly int Top;
  51. public readonly int Right;
  52. public readonly int Bottom;
  53. }
  54. public const int HWND_TOP = 0;
  55. public const int HWND_BOTTOM = 1;
  56. public const int HWND_TOPMOST = -1;
  57. public const int HWND_NOTOPMOST = -2;
  58. /// <summary>
  59.   /// 设置窗体为TopMost
  60.   /// </summary>
  61.   /// <param name="hWnd"></param>
  62. public static void SetTopomost(IntPtr hWnd)
  63. {
  64. LPRECT rect = new LPRECT();
  65. GetWindowRect(hWnd, ref rect);
  66. SetWindowPos(hWnd, (IntPtr)HWND_TOPMOST, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, 0);
  67. }
  68. [DllImport("user32.dll")]
  69. [return: MarshalAs(UnmanagedType.Bool)]
  70. public static extern bool SetForegroundWindow(IntPtr hWnd);
  71. [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
  72. public static extern IntPtr GetForegroundWindow();
  73. /// <summary>
  74. /// 判断是否窗体
  75. /// </summary>
  76. /// <param name="hWnd"></param>
  77. /// <returns></returns>
  78. [DllImport("user32.dll", SetLastError = true)]
  79. public static extern bool IsWindow(IntPtr hWnd);
  80. /// <summary>
  81. /// 当前窗口是否最小化
  82. /// </summary>
  83. /// <param name="hWnd"></param>
  84. /// <returns></returns>
  85. [DllImport("user32.dll")]
  86. [return: MarshalAs(UnmanagedType.Bool)]
  87. public static extern bool IsIconic(IntPtr hWnd);
  88. /// <summary>
  89. /// 当前窗口是否最大化
  90. /// </summary>
  91. /// <param name="hWnd"></param>
  92. /// <returns></returns>
  93. [DllImport("user32.dll")]
  94. public static extern bool IsZoomed(IntPtr hWnd);
  95. /// <summary>
  96. /// 判断窗口是否可见
  97. /// </summary>
  98. /// <param name="hWnd"></param>
  99. /// <returns></returns>
  100. [DllImport("user32")]
  101. public static extern bool IsWindowVisible(IntPtr hWnd);
  102. [DllImport("user32.dll")]
  103. public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
  104. // 获取窗口文本长度
  105. /// <summary>
  106. /// 获取目标窗口标题的文本长度
  107. /// </summary>
  108. /// <param name="hWnd">目标窗口句柄</param>
  109. /// <returns>标题文本长度</returns>
  110. [DllImport("user32.dll")]
  111. public static extern int GetWindowTextLength(IntPtr hWnd);
  112. /// <summary>
  113. /// 获取窗口文本,文本会塞入StringBuilder中,需要指明字符串最大长度nMaxCount
  114. /// </summary>
  115. /// <param name="hwnd">窗口句柄</param>
  116. /// <param name="lpString">返回目标窗口的内容</param>
  117. /// <param name="nMaxCount">允许返回的字符数量上限</param>
  118. /// <returns>实际获取到的文本长度</returns>
  119. [DllImport("User32.dll", EntryPoint = "GetWindowText")]
  120. public static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
  121. [DllImport("User32.dll", CharSet = CharSet.Auto)]
  122. public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
  123. /// <summary>
  124. /// 获取 Win32 窗口的一些基本信息。
  125. /// </summary>
  126. public struct WindowInfo
  127. {
  128. public WindowInfo(IntPtr hWnd, string className, string title, bool isVisible, Rectangle bounds) : this()
  129. {
  130. Hwnd = hWnd;
  131. ClassName = className;
  132. Title = title;
  133. IsVisible = isVisible;
  134. Bounds = bounds;
  135. }
  136. /// <summary>
  137. /// 获取窗口句柄。
  138. /// </summary>
  139. public IntPtr Hwnd { get; }
  140. /// <summary>
  141. /// 获取窗口类名。
  142. /// </summary>
  143. public string ClassName { get; }
  144. /// <summary>
  145. /// 获取窗口标题。
  146. /// </summary>
  147. public string Title { get; }
  148. /// <summary>
  149. /// 获取当前窗口是否可见。
  150. /// </summary>
  151. public bool IsVisible { get; }
  152. /// <summary>
  153. /// 获取窗口当前的位置和尺寸。
  154. /// </summary>
  155. public Rectangle Bounds { get; }
  156. /// <summary>
  157. /// 获取窗口当前是否是最小化的。
  158. /// </summary>
  159. public bool IsMinimized => Bounds.Left == -32000 && Bounds.Top == -32000;
  160. }
  161. public struct wndInfo
  162. {
  163. public IntPtr hWnd;
  164. public string szWindowName;
  165. public string szClassName;
  166. }
  167. [DllImport("user32.dll")]
  168. private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount);
  169. [DllImport("user32.dll")]
  170. private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount);
  171. public static wndInfo[] GetAllDesktopWindows()
  172. {
  173. List<wndInfo> wndList = new List<wndInfo>();
  174. // 使用委托实现窗口枚举逻辑
  175. EnumWindows(delegate (IntPtr hWnd, int lParam)
  176. {
  177. wndInfo wnd = new wndInfo();
  178. StringBuilder sb = new StringBuilder(256);
  179. // 获取窗口句柄
  180. wnd.hWnd = hWnd;
  181. // 获取窗口名称
  182. GetWindowTextW(hWnd, sb, sb.Capacity);
  183. wnd.szWindowName = sb.ToString();
  184. // 获取窗口类名
  185. GetClassNameW(hWnd, sb, sb.Capacity);
  186. wnd.szClassName = sb.ToString();
  187. // 添加到列表中
  188. wndList.Add(wnd);
  189. return true;
  190. }, 0);
  191. return wndList.ToArray();
  192. }
  193. /// <summary>
  194. /// 查找当前用户空间下所有符合条件的(顶层)窗口。如果不指定条件,将仅查找可见且有标题栏的窗口。
  195. /// </summary>
  196. /// <param name="match">过滤窗口的条件。如果设置为 null,将仅查找可见和标题栏不为空的窗口。</param>
  197. /// <returns>找到的所有窗口信息</returns>
  198. public static IReadOnlyList<WindowInfo> FindAllWindows(Predicate<WindowInfo> match = null)
  199. {
  200. windowList = new List<WindowInfo>();
  201. //遍历窗口并查找窗口相关WindowInfo信息
  202. EnumWindows(OnWindowEnum, 0);
  203. return windowList.FindAll(match ?? DefaultPredicate);
  204. }
  205. /// <summary>
  206. /// 遍历窗体处理的函数
  207. /// </summary>
  208. /// <param name="hWnd"></param>
  209. /// <param name="lparam"></param>
  210. /// <returns></returns>
  211. public static bool OnWindowEnum(IntPtr hWnd, int lparam)
  212. {
  213. // 仅查找顶层窗口。
  214. if (GetParent(hWnd) == IntPtr.Zero)
  215. {
  216. // 获取窗口类名。
  217. var lpString = new StringBuilder(512);
  218. GetClassName(hWnd, lpString, lpString.Capacity);
  219. var className = lpString.ToString();
  220. // 获取窗口标题。
  221. var lptrString = new StringBuilder(512);
  222. GetWindowText(hWnd, lptrString, lptrString.Capacity);
  223. var title = lptrString.ToString().Trim();
  224. // 获取窗口可见性。
  225. var isVisible = IsWindowVisible(hWnd);
  226. // 获取窗口位置和尺寸。
  227. LPRECT rect = default;
  228. GetWindowRect(hWnd, ref rect);
  229. var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
  230. // 添加到已找到的窗口列表。
  231. windowList.Add(new WindowInfo(hWnd, className, title, isVisible, bounds));
  232. }
  233. return true;
  234. }
  235. /// <summary>
  236. /// 默认的查找窗口的过滤条件。可见 + 非最小化 + 包含窗口标题。
  237. /// </summary>
  238. public static readonly Predicate<WindowInfo> DefaultPredicate = x => x.IsVisible && !x.IsMinimized && x.Title.Length > 0;
  239. /// <summary>
  240. /// 窗体列表
  241. /// </summary>
  242. public static List<WindowInfo> windowList;
  243. /// <summary>
  244. /// 遍历子窗体(控件)
  245. /// </summary>
  246. /// <param name="hwndParent">父窗口句柄</param>
  247. /// <param name="lpEnumFunc">遍历的回调函数</param>
  248. /// <param name="lParam">传给遍历时回调函数的额外数据</param>
  249. /// <returns></returns>
  250. [DllImport("user32.dll")]
  251. [return: MarshalAs(UnmanagedType.Bool)]
  252. public static extern bool EnumChildWindows(IntPtr hwndParent, WndEnumProc lpEnumFunc, int lParam);
  253. /// <summary>
  254. /// 查找窗体
  255. /// </summary>
  256. /// <param name="lpClassName">窗体的类名称,比如Form、Window。若不知道,指定为null即可</param>
  257. /// <param name="lpWindowName">窗体的标题/文字</param>
  258. /// <returns></returns>
  259. [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
  260. public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
  261. /// <summary>
  262. /// 查找子窗体(控件)
  263. /// </summary>
  264. /// <param name="hwndParent">父窗体句柄,不知道窗体时可指定IntPtr.Zero</param>
  265. /// <param name="hwndChildAfter">子窗体(控件),通常不知道子窗体(句柄),指定0即可</param>
  266. /// <param name="lpszClass">子窗体(控件)的类名,通常指定null,它是window class name,并不等同于C#中的列名Button、Image、PictureBox等,两者并不相同,可通过GetClassName获取正确的类型名</param>
  267. /// <param name="lpszWindow">子窗体的名字或控件的Title、Text,通常为显示的文字</param>
  268. /// <returns></returns>
  269. [DllImport("user32.dll", EntryPoint = "FindWindowEx", SetLastError = true)]
  270. public static extern IntPtr FindWindowEx(IntPtr hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow);
  271. //消息发送API
  272. [DllImport("user32.dll", EntryPoint = "PostMessage")]
  273. public static extern bool PostMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);
  274. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  275. static extern IntPtr SendMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam);
  276. [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
  277. private const int KEYEVENTF_EXTENDEDKEY = 0x1;
  278. private const int KEYEVENTF_KEYUP = 0x2;
  279. const uint WM_KEYDOWN = 0x100;
  280. const uint WM_KEYUP = 0x101;
  281. const uint WM_SYSKEYDOWN = 0x104;
  282. const uint WM_SYSKEYUP = 0x105;
  283. const int VK_CONTROL = 0x11; // Ctrl键
  284. const int VK_A = 0x41; // A键
  285. const int VK_R = 0x52;
  286. const int VK_P = 0x50;
  287. const int VK_S = 0x53;
  288. const int VK_F = 0x46;
  289. const int VK_C = 0x43;
  290. public enum msgType
  291. {
  292. send = 0,
  293. post =1,
  294. keybd_event =2
  295. }
  296. public static void SendMsg(msgType mType,IntPtr hWnd,int key)
  297. {
  298. //SetTopomost(hWnd);
  299. SetForegroundWindow(hWnd);
  300. switch (mType)
  301. {
  302. case msgType.send:
  303. {
  304. Thread.Sleep(2000);
  305. SendMessage(hWnd, 0X100, (uint)key, 0);//
  306. SendMessage(hWnd, 0X101, (uint)key, 0);//
  307. break;
  308. }
  309. case msgType.post:
  310. {
  311. PostMessage(hWnd, 0X100, (uint)key, 0);//
  312. PostMessage(hWnd, 0X101, (uint)key, 0);//
  313. break;
  314. }
  315. case msgType.keybd_event:
  316. {
  317. keybd_event(Convert.ToByte(key), 0, 0, 0);
  318. keybd_event(Convert.ToByte(key), 0, KEYEVENTF_KEYUP, 0);
  319. break;
  320. }
  321. default:
  322. {
  323. SendMessage(hWnd, 0X100, (uint)key, 0);//
  324. SendMessage(hWnd, 0X101, (uint)key, 0);//
  325. break;
  326. }
  327. }
  328. //Lparam的解释壳参考
  329. //https://blog.csdn.net/deniece1/article/details/103588428 扫描码
  330. //https://blog.csdn.net/yizhe0731/article/details/103194401
  331. }
  332. }
  333. }