gpt4 book ai didi

java - 如何在 MacOS 上使用 Java(使用 JNA)获取前景窗口/进程?

转载 作者:行者123 更新时间:2023-12-04 09:04:46 30 4
gpt4 key购买 nike

目前,我正在努力在 MS Windows 中获取前景(顶部)窗口/进程。我需要使用 JNA 在 macOS 中做类似的事情。
macOS 中的等效代码是什么?

  byte[] windowText = new byte[512];
PointerType hwnd = User32.INSTANCE.GetForegroundWindow();
User32.INSTANCE.GetWindowTextA(hwnd, windowText, 512);
System.out.println(Native.toString(windowText));

最佳答案

这里其实有两个问题,前台窗口和前台进程。我会尽量回答这两个问题。

对于前台进程,使用 JNA 的一种简单方法是映射 Application Services应用程序接口(interface)。请注意,这些函数是在 10.9 中引入的,现在已弃用,但从 10.15 开始仍然有效。较新的版本在 AppKit 中图书馆,见下文。
创建这个类,映射你需要的两个函数:

public interface ApplicationServices extends Library {
ApplicationServices INSTANCE = Native.load("ApplicationServices", ApplicationServices.class);

int GetFrontProcess(LongByReference processSerialNumber);
int GetProcessPID(LongByReference processSerialNumber, IntByReference pid);
}
“前台”进程可以通过 GetFrontProcess() 获得.这会返回一个叫做 ProcessSerialNumber 的东西,整个应用程序服务 API 中使用的唯一 64 位值。要将其转换为您的用户空间使用,您可能需要进程 ID 和 GetProcessPID() 为你做那个翻译。
LongByReference psn = new LongByReference();
IntByReference pid = new IntByReference();
ApplicationServices.INSTANCE.GetFrontProcess(psn);
ApplicationServices.INSTANCE.GetProcessPID(psn, pid);
System.out.println("Front process pid: " + pid.getValue());

虽然上述方法有效,但它已被弃用。新应用程序应使用 AppKit图书馆:
public interface AppKit extends Library {
AppKit INSTANCE = Native.load("AppKit", AppKit.class);
}
关于使用此库的最顶层应用程序,还有多个其他 StackOverflow 问题,例如 this one .映射所需的所有导入和对象比我在这里的答案中做的工作要多得多,但您可能会发现它很有用。弄清楚如何使用 Rococoa framework 可能更容易。 (它在底层使用 JNA,但已经通过 JNAerator 映射了所有 AppKit)来访问这个 API。一些 javadocs are here .
还有 solutions使用 AppleScript您可以使用 Runtime.exec() 通过命令行从 Java 执行并捕获输出。

关于屏幕上的前景窗口,它有点复杂。在 my answer对于您之前关于在 macOS 上迭代所有窗口的问题,我回答了如何使用 CoreGraphics 获取所有窗口的列表通过 JNA,包括 CFDictionary包含更多信息。
这些字典键之一是 kCGWindowLayer 这将返回 CFNumber代表窗口层数。文档说明这是 32 位的,所以 intValue()是合适的。该数字是“绘图顺序”,因此较高的数字将覆盖较低的数字。因此,您可以遍历所有检索到的窗口并找到最大数量。这将是“前景”层。
有一些注意事项:
  • 实际上只有20层可用。许多事物共享一个层。
  • 第 1000 层是屏幕保护程序。您可以忽略 1000 层及更高层。
  • 第 24 层是 Dock,通常在顶部,第 25 层(Dock 上的图标)在更高级别。
  • 第 0 层似乎是桌面的其余部分。
  • 哪个窗口位于“顶部”取决于您在屏幕上的位置。在 Dock 上方,Dock 将位于前台(或应用程序图标)。在屏幕的其余部分,您需要检查您正在评估的像素与从 CoreGraphics 窗口获得的屏幕矩形。 (使用 kCGWindowBounds 键返回 CGRect(具有 4 个 double 、X、Y、宽度、高度的结构)。

  • 您将需要过滤到屏幕窗口。如果您已经获取了列表,您可以使用 kCGWindowIsOnscreen 键来确定窗口是否可见。它返回一个 CFBoolean .由于该 key 是可选的,因此您需要测试 null .但是,如果您从无到有,最好使用 kCGWindowListOptionOnScreenOnly Window Option Constant当您最初拨打 CGWindowListCopyWindowInfo() 时.
    除了迭代所有窗口, CGWindowListCopyWindowInfo() 函数需要一个 CGWindowID 参数 relativeToWindow你可以添加(按位或) kCGWindowListOptionOnScreenAboveWindow到选项。
    最后,您可能会发现限制与当前 session 关联的窗口可能很有用,您应该映射 CGWindowListCreate() 使用与 CopyInfo() 类似的语法变体。它返回一个窗口编号数组,您可以将字典搜索限制到该数组,或者将该数组作为参数传递给 CGWindowListCreateDescriptionFromArray() .
    正如我之前的回答中提到的,您“拥有”使用 Create 创建的每个对象。或 Copy函数,并负责在完成后释放它们,以避免内存泄漏。

    关于java - 如何在 MacOS 上使用 Java(使用 JNA)获取前景窗口/进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63469738/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com