[英]Get all visible windows with JNA
我正在 Java 中编写覆盖图,显示多个 windows 的信息。
我需要它跟随它正在跟踪的 window,为此我会定期获取有关当前 windows 的信息,以更新我的叠加层的 position。 但我还需要知道 windows 是否可见以隐藏叠加层(如果不可见)。 理想情况下,我应该能够实时完成所有这些工作,但我担心这对性能的要求太高了。
我用 JNA 做所有这些
public interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.load("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);
HWND FindWindow(String lpClassName, String lpWindowName);
int GetWindowRect(HWND handle, int[] rect);
boolean IsWindowVisible(HWND handle); // always true if window exist
}
public static int[] getWindowInformation(String windowName) {
int[] rectangle = {0,0,0,0};
HWND hwnd = User32.INSTANCE.FindWindow(null, windowName);
User32.INSTANCE.GetWindowRect(hwnd, rectangle);
boolean res = User32.INSTANCE.IsWindowVisible(hwnd);
System.out.println(windowName + " is visible ? " + res);
return rectangle;
}
这是我的代码,你可以看到我在完全阅读了 JNA 的 User32 API 之后尝试了“IsWindowVisible”,但它没有做我想要的。
您使用User32
的IsWindowVisible
的直觉很好。 JNA 实际上已经在其WindowUtils class 中实现了这一点。
List<DesktopWindow> windows = WindowUtils.getAllWindows(true);
boolean 参数是onlyVisibleWindows
。
请注意,这里的“可见”是指 window 本身的 state,而不是它是否被最小化(可能具有屏幕外或“零”坐标)或其他 windows 的“后面”与“顶部”,因此对用户。 来自IsWindowVisible
文档(注意第二段):
如果指定的 window、其父级 window、其父级的父级 window 等具有WS_VISIBLE样式,则返回值为非零。 否则,返回值为零。
因为返回值指定 window 是否具有WS_VISIBLE样式,所以即使 window 被其他 windows 完全遮盖,它也可能是非零的。
为了确定 window 是部分还是完全被遮挡,您必须使用 Z 顺序评估其相对于其“前面”的所有 windows 的locAndSize
矩形。 您可以逐个像素地执行此操作,也可以仅评估角点,具体取决于您希望如何处理部分模糊的 windows。
JNA getAllWindows()
方法返回封装这些字段的 JNA DesktopWindow
的列表(按可见性过滤):
private HWND hwnd;
private String title;
private String filePath;
private Rectangle locAndSize;
在内部,您可以在内部 class W32WindowUtils
中看到实现,它使用发送到User32
的EnumWindows
function 的回调 function:
@Override
public List<DesktopWindow> getAllWindows(final boolean onlyVisibleWindows) {
final List<DesktopWindow> result = new LinkedList<DesktopWindow>();
final WNDENUMPROC lpEnumFunc = new WNDENUMPROC() {
@Override
public boolean callback(final HWND hwnd, final Pointer arg1) {
try {
final boolean visible = !onlyVisibleWindows
|| User32.INSTANCE.IsWindowVisible(hwnd);
if (visible) {
final String title = getWindowTitle(hwnd);
final String filePath = getProcessFilePath(hwnd);
final Rectangle locAndSize = getWindowLocationAndSize(hwnd);
result.add(new DesktopWindow(hwnd, title, filePath,
locAndSize));
}
} catch (final Exception e) {
// FIXME properly handle whatever error is raised
e.printStackTrace();
}
return true;
}
};
if (!User32.INSTANCE.EnumWindows(lpEnumFunc, null))
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
return result;
}
我维护基于 JNA 的OSHI项目,并通过new SystemInfo().getOperatingSystem().getDesktopWindows()
实现了这个跨平台,它在 Windows 上使用上述实现并添加来自其他函数的信息以获得 window 排序。 OSHI 的返回列表包括这些字段并且返回的列表已经order
以帮助您确定用户可见性:
private final long windowId;
private final String title;
private final String command;
private final Rectangle locAndSize;
private final long owningProcessId;
private final int order;
private final boolean visible;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.