first commit
This commit is contained in:
commit
761b95080f
404 files changed
+312608
No files matched your search
@@ -0,0 +1,110 @@
|
||||
using anjianjingling.Native;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace anjianjingling.Window
|
||||
{
|
||||
public record WindowInfo(IntPtr Handle, string Title);
|
||||
|
||||
/// <summary>
|
||||
/// 系统级窗口管理:枚举、查找、激活、启动程序、后台消息投递。
|
||||
/// </summary>
|
||||
public sealed class WindowManager
|
||||
{
|
||||
/// <summary>启动外部程序或打开文件。</summary>
|
||||
public void Launch(string path, string? arguments = null)
|
||||
{
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = path,
|
||||
UseShellExecute = true
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(arguments)) psi.Arguments = arguments;
|
||||
Process.Start(psi);
|
||||
}
|
||||
|
||||
/// <summary>枚举所有可见且有标题的顶层窗口。</summary>
|
||||
public List<WindowInfo> GetWindows()
|
||||
{
|
||||
var list = new List<WindowInfo>();
|
||||
Win32.EnumWindows((h, _) =>
|
||||
{
|
||||
if (Win32.IsWindowVisible(h))
|
||||
{
|
||||
int len = Win32.GetWindowTextLength(h);
|
||||
if (len > 0)
|
||||
{
|
||||
var sb = new StringBuilder(len + 1);
|
||||
Win32.GetWindowText(h, sb, sb.Capacity);
|
||||
var title = sb.ToString().Trim();
|
||||
if (title.Length > 0) list.Add(new WindowInfo(h, title));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, IntPtr.Zero);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>按标题关键字(包含匹配,不区分大小写)查找窗口。</summary>
|
||||
public IntPtr FindByTitle(string keyword)
|
||||
{
|
||||
foreach (var w in GetWindows())
|
||||
{
|
||||
if (w.Title.Contains(keyword, StringComparison.OrdinalIgnoreCase))
|
||||
return w.Handle;
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
/// <summary>激活窗口并前置(最小化则恢复,使用 AttachThreadInput 解决前台锁定)。</summary>
|
||||
public bool Activate(IntPtr hWnd)
|
||||
{
|
||||
if (hWnd == IntPtr.Zero) return false;
|
||||
if (Win32.IsIconic(hWnd)) Win32.ShowWindow(hWnd, Win32.SW_RESTORE);
|
||||
|
||||
uint foregroundThread = Win32.GetWindowThreadProcessId(Win32.GetForegroundWindow(), out _);
|
||||
uint currentThread = Win32.GetCurrentThreadId();
|
||||
|
||||
if (foregroundThread != currentThread)
|
||||
{
|
||||
Win32.AttachThreadInput(currentThread, foregroundThread, true);
|
||||
Win32.SetForegroundWindow(hWnd);
|
||||
Win32.AttachThreadInput(currentThread, foregroundThread, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Win32.SetForegroundWindow(hWnd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>按标题激活。</summary>
|
||||
public bool ActivateByTitle(string keyword)
|
||||
{
|
||||
var h = FindByTitle(keyword);
|
||||
return h != IntPtr.Zero && Activate(h);
|
||||
}
|
||||
|
||||
/// <summary>获取窗口屏幕矩形。</summary>
|
||||
public Rectangle? GetBounds(IntPtr hWnd)
|
||||
{
|
||||
if (Win32.GetWindowRect(hWnd, out var r))
|
||||
return new Rectangle(r.Left, r.Top, r.Width, r.Height);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 后台点击:向窗口句柄 PostMessage 发送鼠标按下/弹起(客户区坐标),不抢焦点。
|
||||
/// 注意:对 DirectX/自绘程序可能无效。
|
||||
/// </summary>
|
||||
public void PostClick(IntPtr hWnd, int clientX, int clientY, bool right = false)
|
||||
{
|
||||
var lp = Win32.MakeLParam(clientX, clientY);
|
||||
uint down = right ? Win32.WM_RBUTTONDOWN : Win32.WM_LBUTTONDOWN;
|
||||
uint up = right ? Win32.WM_RBUTTONUP : Win32.WM_LBUTTONUP;
|
||||
Win32.PostMessage(hWnd, down, Win32.MK_LBUTTON, lp);
|
||||
Thread.Sleep(60);
|
||||
Win32.PostMessage(hWnd, up, IntPtr.Zero, lp);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user