objective-c - 在 OS X 上唯一标识事件窗口

标签 objective-c macos cocoa

我正在尝试修补 an application使用可访问性 API 调整窗口大小。

我需要维护一个包含之前窗口大小的字典。该键需要标识当前事件的窗口。目前,这个事件窗口是通过 NSAccessibilityFocusedWindowAttribute 检索的。按下热键。

但是,每次调用此方法时,返回的标识窗口的 AXUIElementRef 都是不同的!这当然意味着我不能将它用作字典键——字典找不到相应的条目。

下面的代码重现了这个问题:

-(IBAction)testWindowIdentification:(id)sender{
    AXUIElementRef focusedApp;
    AXUIElementRef focusedWindow;

    AXUIElementCopyAttributeValue(_systemWideElement,
                                  (CFStringRef) kAXFocusedApplicationAttribute,
                                  (CFTypeRef*) &focusedApp);
    AXUIElementCopyAttributeValue((AXUIElementRef) focusedApp,
                                  (CFStringRef) NSAccessibilityFocusedWindowAttribute,
                                  (CFTypeRef*) &focusedWindow);
    CFShow(focusedWindow);
}

_systemWideElement 已通过调用 AXUIElementCreateSystemWide()init 方法中初始化。

CFShow 语句在每次调用方法时都清楚地显示不同的 ID(即使同一个窗口处于事件状态),这对我来说没用:

<AXUIElement 0x47e850> {pid=42463}
<AXUIElement 0x47e890> {pid=42463}
<AXUIElement 0x47e2c0> {pid=42463}
…

documentation on AXUIElement没有显示检索 UI 元素的唯一属性的方法,that of the NSAccessibility protocol 也没有显示. 唯一的 PID 对我来说不够,因为一个进程可以有多个窗口。

如何在 Cocoa 中检索事件窗口的一些唯一标识符?

(顺便说一句,真正的代码是检查上面调用中的返回码;没有错误,调用成功。)

最佳答案

Rob Keniger 对 his answer here 有正确的策略。这个答案中唯一缺少的东西(实际上,悬赏安置的原因)是一个可行的实现,它采用当前事件窗口并将其转换为适合在当前工作应用程序的上下文中进行索引的唯一键。

Rob 的解决方案通过使用在 Quartz Window Services 上下文中给出的 CGWindowID 勾勒出这一点。当然,强烈暗示此窗口引用是 only useful for your current application

获取此窗口引用很棘手,因为在辅助功能 API 和 Quartz 窗口服务之间不存在强有力的保证。但是,您可以通过以下方式解决此问题:

  1. 使用 extern "C"AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out);,作为 documented here 。这不是保证工作,但如果它在您的 OSX 版本中工作,它可以作为一个底层测试来启动事情。

  2. 直接获取CGWindowID,例如使用HIWindowGetCGWindowID()。有关选择事件窗口和提取 ID 的更多详细信息,请参阅 the reference manual for the Carbon Window Manager(警告:大 PDF)。

  3. 使用 CGWindowListCreateDescriptionFromArray 之类的东西为您的 CGWindowID 集编目,完全按照 Rob 的建议。这里的目标是找到一些桥接 Accessibility API 和 Quartz 的方案,但这可以通过使用例如绑定(bind)到当前事件窗口上下文的回调来实现。不过,老实说,我不知道这个适合 future 发展的最佳示例。

在这些选项中,如果您无法为您的窗口创建一些其他装饰器来唯一标识它们,我建议您使用 2. 来满足您当前的需求。它目前在遗留代码库中定义,但它会做你想做的事。

祝你申请顺利。

关于objective-c - 在 OS X 上唯一标识事件窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7422666/

相关文章:

macos - 无法向 NSSegmentedControl 添加更多元素

php - 终端显示错误的 php 版本 (Snow Leopard)

objective-c - 以编程方式启用对辅助设备的访问

iphone - KVC : How do I save UIKit structs in plist?

iphone - 实现 transient 属性

objective-c - iOS TCP/IP 检查连接

ios - 为什么尽管安装了相同的代码,不同的设备从高清返回同一组的顺序不同

ios - 简单查询 : How does one detect the addition of an item in a mutable array?

java - 如何为我的 Java 应用程序创建 Mac 安装程序?

objective-c - OS X 中的全屏应用程序有多个窗口吗?