目前,我正在努力获得前景(顶部)窗口/进程在微软视窗。我需要在macos中使用jna做一些类似的事情。
macos中的等效代码是什么?
byte[] windowText = new byte[512];
PointerType hwnd = User32.INSTANCE.GetForegroundWindow();
User32.INSTANCE.GetWindowTextA(hwnd, windowText, 512);
System.out.println(Native.toString(windowText));
2条答案
按热度按时间7dl7o3gd1#
这里实际上有两个问题,前台窗口和前台进程。我会尽量回答这两个问题。
对于前台进程,使用jna的一个简单方法是Map应用程序服务api。请注意,这些函数是在10.9中引入的,现在已被弃用,但从10.15开始仍然可以使用。更新的版本在
AppKitLibrary
,见下文。创建这个类,Map您需要的两个函数:
“前景”过程可以通过
GetFrontProcess()
. 返回一个叫做ProcessSerialNumber
,在整个应用程序服务api中使用的唯一64位值。要将其转换为用户空间使用,您可能需要进程id,并且GetProcessPID()
帮你翻译一下。虽然上面的方法有效,但不推荐使用。新应用程序应使用
AppKitLibrary
:关于使用此库的最顶层应用程序,还有其他多个stackoverflow问题,例如这个问题。Map所有需要的导入和对象比我在这里的答案中花的时间多得多,但您可能会发现它很有用。可能更容易弄清楚如何使用洛可可框架(它在引擎盖下使用jna,但已经通过jnavigatorMap了所有appkit)来访问这个api。一些javadocs在这里。
也有使用
AppleScript
可以通过命令行从java执行Runtime.exec()
以及捕捉输出。关于屏幕上的前景窗口,它有点复杂。在我回答您之前关于在macos上迭代所有窗口的问题时,我回答了如何获取使用macos的所有窗口的列表
CoreGraphics
通过jna,包括CFDictionary
包含更多信息。其中一个字典键是
kCGWindowLayer
它将返回一个CFNumber
表示窗口层编号。文件上说这是32位的,所以intValue()
是合适的。数字是“绘图顺序”,因此较高的数字将覆盖较低的数字。因此,您可以遍历所有检索到的窗口并找到最大数目。这将是“前景”层。有一些警告:
实际上只有20层可用。许多事物共享一层。
第1000层是屏幕保护程序。可以忽略1000层或更高的层。
第24层是dock,通常在上面,第25层(dock上的图标)在更高的层次上。
层0似乎是桌面的其余部分。
哪个窗口“在最上面”取决于你在屏幕上看的位置。在dock上,dock将位于前台(或应用程序图标)。在屏幕的其余部分,您需要检查正在评估的像素与从coregraphics窗口获得的屏幕矩形(使用
kCGWindowBounds
返回CGRect
(一种有4个双倍x,y,宽,高的结构)。你需要过滤到屏幕上的窗口。如果您已经获取了列表,则可以使用
kCGWindowIsOnscreen
键确定窗口是否可见。它返回一个CFBoolean
. 因为该键是可选的,所以您需要测试null
. 但是,如果您是从零开始,那么最好使用kCGWindowListOptionOnScreenOnly
初始调用时的窗口选项常量CGWindowListCopyWindowInfo()
.除了迭代所有窗口之外
CGWindowListCopyWindowInfo()
函数需要CGWindowID
参数relativeToWindow
您可以添加(按位或)kCGWindowListOptionOnScreenAboveWindow
到选项。最后,您可能会发现限制与当前会话相关联的窗口可能很有用,您应该Map
CGWindowListCreate()
使用与CopyInfo()
变体。它返回一个窗口编号数组,您可以将字典搜索限制为该数组,或者将该数组作为参数传递给它CGWindowListCreateDescriptionFromArray()
.正如我在前面的回答中提到的,您“拥有”了使用
Create
或者Copy
函数,并负责在完成时释放它们,以避免内存泄漏。4zcjmb1e2#