From 3b49adcd596b2297bd3f296ee17166116fb01dd9 Mon Sep 17 00:00:00 2001 From: fofolee Date: Sat, 18 Jan 2025 15:58:16 +0800 Subject: [PATCH] =?UTF-8?q?automation.cs=E6=94=AF=E6=8C=81=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E6=9D=A1=E4=BB=B6=E6=9F=A5=E6=89=BEwindows=EF=BC=8C?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E4=BE=9D=E7=84=B6=E9=99=90=E5=88=B6=E5=8F=AA?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E5=8F=A5=E6=9F=84=E6=9F=A5=E6=89=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugin/lib/csharp/automation.cs | 120 ++++++++++++++++-- .../lib/quickcomposer/windows/automation.js | 4 +- src/js/composer/commands/windowsCommands.js | 2 +- 3 files changed, 110 insertions(+), 16 deletions(-) diff --git a/plugin/lib/csharp/automation.cs b/plugin/lib/csharp/automation.cs index 704e2da..c58013e 100644 --- a/plugin/lib/csharp/automation.cs +++ b/plugin/lib/csharp/automation.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading; using System.Windows.Forms; using System.Drawing; +using System.Diagnostics; public class AutomationManager { @@ -72,6 +73,17 @@ public class AutomationManager [DllImport("user32.dll")] static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle); + [DllImport("user32.dll")] + static extern bool IsWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); + + [DllImport("user32.dll")] + private static extern bool IsWindowVisible(IntPtr hWnd); + + private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); + private const int GWL_EXSTYLE = -20; private const int WS_EX_TRANSPARENT = 0x20; private const int WS_EX_LAYERED = 0x80000; @@ -342,25 +354,22 @@ public class AutomationManager { // 获取起始窗口 AutomationElement root; - string windowArg = GetArgumentValue(args, "-window"); - if (!string.IsNullOrEmpty(windowArg)) + try { - // 通过窗口句柄查找 - int handle = int.Parse(windowArg); - try + List targetWindows = GetTargetWindows(args); + if (targetWindows.Count == 0) { - root = AutomationElement.FromHandle(new IntPtr(handle)); - } - catch - { - throw new Exception("无法获取指定的窗口"); + throw new Exception("未找到目标窗口"); } + + // 总是使用第一个窗口 + IntPtr handle = targetWindows[0]; + + root = AutomationElement.FromHandle(handle); } - else + catch { - // 使用当前活动窗口 - IntPtr activeHandle = GetForegroundWindow(); - root = AutomationElement.FromHandle(activeHandle); + throw new Exception("无法获取指定的窗口"); } if (root == null) @@ -456,6 +465,89 @@ public class AutomationManager throw new Exception("必须指定元素的识别方式: -xpath, -id, -name 或 -condition"); } + private static List GetTargetWindows(string[] args) + { + List targetWindows = new List(); + string method = GetArgumentValue(args, "-method") ?? "handle"; + string value = GetArgumentValue(args, "-window") ?? ""; + + switch (method.ToLower()) + { + case "handle": + IntPtr handle = new IntPtr(long.Parse(value)); + if (!IsWindow(handle)) + { + throw new Exception("指定的句柄不是一个有效的窗口句柄"); + } + targetWindows.Add(handle); + break; + + case "active": + targetWindows.Add(GetForegroundWindow()); + break; + + case "process": + var processes = Process.GetProcessesByName(value); + foreach (var process in processes) + { + if (process.MainWindowHandle != IntPtr.Zero) + { + targetWindows.Add(process.MainWindowHandle); + } + } + break; + + case "class": + EnumWindows((hwnd, param) => + { + if (!IsWindowVisible(hwnd)) + { + return true; + } + + StringBuilder className = new StringBuilder(256); + GetClassName(hwnd, className, className.Capacity); + string windowClassName = className.ToString(); + + if (windowClassName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) + { + targetWindows.Add(hwnd); + } + return true; + }, IntPtr.Zero); + break; + + case "title": + default: + if (!string.IsNullOrEmpty(value)) + { + EnumWindows((hwnd, param) => + { + StringBuilder title = new StringBuilder(256); + GetWindowText(hwnd, title, title.Capacity); + string windowTitle = title.ToString(); + + if (!string.IsNullOrEmpty(windowTitle) && + windowTitle.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) + { + targetWindows.Add(hwnd); + } + return true; + }, IntPtr.Zero); + } + break; + } + + if (targetWindows.Count == 0) + { + throw new Exception("未找到匹配的窗口"); + } + + return targetWindows; + } + + + private static void ShowHelp() { Console.WriteLine(@"UI自动化工具 v1.0 diff --git a/plugin/lib/quickcomposer/windows/automation.js b/plugin/lib/quickcomposer/windows/automation.js index 7bc59a3..682af3f 100644 --- a/plugin/lib/quickcomposer/windows/automation.js +++ b/plugin/lib/quickcomposer/windows/automation.js @@ -20,7 +20,9 @@ async function runAutomation( const args = []; if (window) { - args.push("-window", window); + args.push("-method", "handle", "-window", window); + } else { + args.push("-method", "active"); } args.push("-type", type); diff --git a/src/js/composer/commands/windowsCommands.js b/src/js/composer/commands/windowsCommands.js index 502d176..04b90e5 100644 --- a/src/js/composer/commands/windowsCommands.js +++ b/src/js/composer/commands/windowsCommands.js @@ -157,7 +157,7 @@ const windowHandleConfig = [ ]; const searchElementConfig = [ - windowHandleConfig, + ...windowHandleConfig, { label: "元素查找方式", component: "q-select",