using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; namespace PTMedicalInsurance.Common.WinAPI { class WndHelper { // /// 枚举窗口时的委托参数 /// /// /// /// public delegate bool WndEnumProc(IntPtr hWnd, int lParam); /// /// 枚举所有窗口 /// /// /// /// [DllImport("user32")] public static extern bool EnumWindows(WndEnumProc lpEnumFunc, int lParam); /// /// 获取窗口的父窗口句柄 /// /// /// [DllImport("user32")] public static extern IntPtr GetParent(IntPtr hWnd); [DllImport("user32")] public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32")] public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); [DllImport("user32")] public static extern bool GetWindowRect(IntPtr hWnd, ref LPRECT rect); [DllImport("user32.dll")] public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint wFlags); [StructLayout(LayoutKind.Sequential)] public readonly struct LPRECT { public readonly int Left; public readonly int Top; public readonly int Right; public readonly int Bottom; } public const int HWND_TOP = 0; public const int HWND_BOTTOM = 1; public const int HWND_TOPMOST = -1; public const int HWND_NOTOPMOST = -2; ///   /// 设置窗体为TopMost   ///   /// public static void SetTopomost(IntPtr hWnd) { LPRECT rect = new LPRECT(); GetWindowRect(hWnd, ref rect); SetWindowPos(hWnd, (IntPtr)HWND_TOPMOST, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, 0); } [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern IntPtr GetForegroundWindow(); /// /// 判断是否窗体 /// /// /// [DllImport("user32.dll", SetLastError = true)] public static extern bool IsWindow(IntPtr hWnd); /// /// 当前窗口是否最小化 /// /// /// [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsIconic(IntPtr hWnd); /// /// 当前窗口是否最大化 /// /// /// [DllImport("user32.dll")] public static extern bool IsZoomed(IntPtr hWnd); /// /// 判断窗口是否可见 /// /// /// [DllImport("user32")] public static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("user32.dll")] public static extern int ShowWindow(IntPtr hwnd, int nCmdShow); // 获取窗口文本长度 /// /// 获取目标窗口标题的文本长度 /// /// 目标窗口句柄 /// 标题文本长度 [DllImport("user32.dll")] public static extern int GetWindowTextLength(IntPtr hWnd); /// /// 获取窗口文本,文本会塞入StringBuilder中,需要指明字符串最大长度nMaxCount /// /// 窗口句柄 /// 返回目标窗口的内容 /// 允许返回的字符数量上限 /// 实际获取到的文本长度 [DllImport("User32.dll", EntryPoint = "GetWindowText")] public static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount); [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID); /// /// 获取 Win32 窗口的一些基本信息。 /// public struct WindowInfo { public WindowInfo(IntPtr hWnd, string className, string title, bool isVisible, Rectangle bounds) : this() { Hwnd = hWnd; ClassName = className; Title = title; IsVisible = isVisible; Bounds = bounds; } /// /// 获取窗口句柄。 /// public IntPtr Hwnd { get; } /// /// 获取窗口类名。 /// public string ClassName { get; } /// /// 获取窗口标题。 /// public string Title { get; } /// /// 获取当前窗口是否可见。 /// public bool IsVisible { get; } /// /// 获取窗口当前的位置和尺寸。 /// public Rectangle Bounds { get; } /// /// 获取窗口当前是否是最小化的。 /// public bool IsMinimized => Bounds.Left == -32000 && Bounds.Top == -32000; } public struct wndInfo { public IntPtr hWnd; public string szWindowName; public string szClassName; } [DllImport("user32.dll")] private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount); [DllImport("user32.dll")] private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount); public static wndInfo[] GetAllDesktopWindows() { List wndList = new List(); // 使用委托实现窗口枚举逻辑 EnumWindows(delegate (IntPtr hWnd, int lParam) { wndInfo wnd = new wndInfo(); StringBuilder sb = new StringBuilder(256); // 获取窗口句柄 wnd.hWnd = hWnd; // 获取窗口名称 GetWindowTextW(hWnd, sb, sb.Capacity); wnd.szWindowName = sb.ToString(); // 获取窗口类名 GetClassNameW(hWnd, sb, sb.Capacity); wnd.szClassName = sb.ToString(); // 添加到列表中 wndList.Add(wnd); return true; }, 0); return wndList.ToArray(); } /// /// 查找当前用户空间下所有符合条件的(顶层)窗口。如果不指定条件,将仅查找可见且有标题栏的窗口。 /// /// 过滤窗口的条件。如果设置为 null,将仅查找可见和标题栏不为空的窗口。 /// 找到的所有窗口信息 public static IReadOnlyList FindAllWindows(Predicate match = null) { windowList = new List(); //遍历窗口并查找窗口相关WindowInfo信息 EnumWindows(OnWindowEnum, 0); return windowList.FindAll(match ?? DefaultPredicate); } /// /// 遍历窗体处理的函数 /// /// /// /// public static bool OnWindowEnum(IntPtr hWnd, int lparam) { // 仅查找顶层窗口。 if (GetParent(hWnd) == IntPtr.Zero) { // 获取窗口类名。 var lpString = new StringBuilder(512); GetClassName(hWnd, lpString, lpString.Capacity); var className = lpString.ToString(); // 获取窗口标题。 var lptrString = new StringBuilder(512); GetWindowText(hWnd, lptrString, lptrString.Capacity); var title = lptrString.ToString().Trim(); // 获取窗口可见性。 var isVisible = IsWindowVisible(hWnd); // 获取窗口位置和尺寸。 LPRECT rect = default; GetWindowRect(hWnd, ref rect); var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top); // 添加到已找到的窗口列表。 windowList.Add(new WindowInfo(hWnd, className, title, isVisible, bounds)); } return true; } /// /// 默认的查找窗口的过滤条件。可见 + 非最小化 + 包含窗口标题。 /// public static readonly Predicate DefaultPredicate = x => x.IsVisible && !x.IsMinimized && x.Title.Length > 0; /// /// 窗体列表 /// public static List windowList; /// /// 遍历子窗体(控件) /// /// 父窗口句柄 /// 遍历的回调函数 /// 传给遍历时回调函数的额外数据 /// [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumChildWindows(IntPtr hwndParent, WndEnumProc lpEnumFunc, int lParam); /// /// 查找窗体 /// /// 窗体的类名称,比如Form、Window。若不知道,指定为null即可 /// 窗体的标题/文字 /// [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); /// /// 查找子窗体(控件) /// /// 父窗体句柄,不知道窗体时可指定IntPtr.Zero /// 子窗体(控件),通常不知道子窗体(句柄),指定0即可 /// 子窗体(控件)的类名,通常指定null,它是window class name,并不等同于C#中的列名Button、Image、PictureBox等,两者并不相同,可通过GetClassName获取正确的类型名 /// 子窗体的名字或控件的Title、Text,通常为显示的文字 /// [DllImport("user32.dll", EntryPoint = "FindWindowEx", SetLastError = true)] public static extern IntPtr FindWindowEx(IntPtr hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow); //消息发送API [DllImport("user32.dll", EntryPoint = "PostMessage")] public static extern bool PostMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam); [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, int Msg, uint wParam, uint lParam); [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo); private const int KEYEVENTF_EXTENDEDKEY = 0x1; private const int KEYEVENTF_KEYUP = 0x2; const uint WM_KEYDOWN = 0x100; const uint WM_KEYUP = 0x101; const uint WM_SYSKEYDOWN = 0x104; const uint WM_SYSKEYUP = 0x105; const int VK_CONTROL = 0x11; // Ctrl键 const int VK_A = 0x41; // A键 const int VK_R = 0x52; const int VK_P = 0x50; const int VK_S = 0x53; const int VK_F = 0x46; const int VK_C = 0x43; public enum msgType { send = 0, post =1, keybd_event =2 } public static void SendMsg(msgType mType,IntPtr hWnd,int key) { //SetTopomost(hWnd); SetForegroundWindow(hWnd); switch (mType) { case msgType.send: { Thread.Sleep(2000); SendMessage(hWnd, 0X100, (uint)key, 0);// SendMessage(hWnd, 0X101, (uint)key, 0);// break; } case msgType.post: { PostMessage(hWnd, 0X100, (uint)key, 0);// PostMessage(hWnd, 0X101, (uint)key, 0);// break; } case msgType.keybd_event: { keybd_event(Convert.ToByte(key), 0, 0, 0); keybd_event(Convert.ToByte(key), 0, KEYEVENTF_KEYUP, 0); break; } default: { SendMessage(hWnd, 0X100, (uint)key, 0);// SendMessage(hWnd, 0X101, (uint)key, 0);// break; } } //Lparam的解释壳参考 //https://blog.csdn.net/deniece1/article/details/103588428 扫描码 //https://blog.csdn.net/yizhe0731/article/details/103194401 } } }