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
}
}
}