From 3e5b47a61c5a1fa370897d67ca9c63cada28f4d0 Mon Sep 17 00:00:00 2001 From: wangbing Date: Thu, 25 Sep 2025 17:53:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xyz/wbsite/jmacro/util/WindowsUtil.java | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/main/java/xyz/wbsite/jmacro/util/WindowsUtil.java diff --git a/src/main/java/xyz/wbsite/jmacro/util/WindowsUtil.java b/src/main/java/xyz/wbsite/jmacro/util/WindowsUtil.java new file mode 100644 index 0000000..3e0d592 --- /dev/null +++ b/src/main/java/xyz/wbsite/jmacro/util/WindowsUtil.java @@ -0,0 +1,149 @@ +package xyz.wbsite.jmacro.util; + +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.WinUser; +import com.sun.jna.win32.W32APIOptions; + +/** + * 窗口工具类 + *

+ * 可以打印窗口句柄和窗口信息 + * 可以根据关键词匹配窗口句柄 + * + * @author wangbing + * @version 0.0.1 + * @since 1.8 + */ +public class WindowsUtil { + + /** + * 定义 User32 接口 + *

+ * 用于调用 Windows API 中的 user32.dll 库 + */ + public interface User32 extends com.sun.jna.Library { + + /** + * 加载 user32.dll 库 + */ + User32 INSTANCE = Native.load("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS); + + /** + * 查找窗口 + * + * @param lpClassName 类名 + * @param lpWindowName 窗口名 + * @return 窗口句柄 + */ + WinDef.HWND FindWindow(String lpClassName, String lpWindowName); + + /** + * 查找窗口(ANSI 字符编码(单字节字符集)) + * + * @param lpClassName 类名 + * @param lpWindowName 窗口名 + * @return 窗口句柄 + */ + WinDef.HWND FindWindowA(String lpClassName, String lpWindowName); + + /** + * 枚举所有窗口 + * + * @param lpEnumFunc 枚举回调函数 + * @param arg 回调函数参数 + * @return 是否成功 + */ + boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc, Pointer arg); + + /** + * 获取窗口标题 + * + * @param hWnd 窗口句柄 + * @param lpString 标题缓冲区 + * @param nMaxCount 标题缓冲区大小 + * @return 标题长度 + */ + int GetWindowTextW(WinDef.HWND hWnd, char[] lpString, int nMaxCount); + + /** + * 获取窗口类名 + * + * @param hWnd 窗口句柄 + * @param lpString 类名缓冲区 + * @param nMaxCount 类名缓冲区大小 + * @return 类名长度 + */ + int GetClassNameW(WinDef.HWND hWnd, char[] lpString, int nMaxCount); + + /** + * 判断窗口是否可见 + * + * @param hWnd 窗口句柄 + * @return 是否可见 + */ + boolean IsWindowVisible(WinDef.HWND hWnd); + + /** + * 获取窗口矩形 + * + * @param hWnd 窗口句柄 + * @param rect 矩形结构体 + * @return 是否成功 + */ + boolean GetWindowRect(WinDef.HWND hWnd, WinDef.RECT rect); + } + + /** + * 打印所有窗口信息 + */ + public static void printWindowInfoAll() { + printWindowInfo(""); + } + + /** + * 打印窗口信息 + * + * @param keyword 关键词 + */ + public static void printWindowInfo(String keyword) { + User32.INSTANCE.EnumWindows((hWnd, data) -> { + // 跳过隐藏窗口 + if (!User32.INSTANCE.IsWindowVisible(hWnd)) { + return true; + } + + char[] windowText = new char[512]; + User32.INSTANCE.GetWindowTextW(hWnd, windowText, 512); + String title = Native.toString(windowText); + char[] className = new char[512]; + User32.INSTANCE.GetClassNameW(hWnd, className, 512); + String clazz = Native.toString(className); + + // 匹配关键词 + if (title.contains(keyword)) { + WinDef.RECT rect = new WinDef.RECT(); + if (User32.INSTANCE.GetWindowRect(hWnd, rect)) { + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + + System.out.println("窗口标题: " + title); + System.out.println("类名: " + clazz); + System.out.println("位置: (" + rect.left + ", " + rect.top + ")"); + System.out.println("大小: " + width + " x " + height); + System.out.println("----------------------"); + } + } + return true; + }, null); + } + + public static WinDef.HWND findWindow(String className, String windowName) { + return User32.INSTANCE.FindWindow(className, windowName); + } + + public static void main(String[] args) { + printWindowInfo("微信"); + } +}