[英]How to create an AXUIElementRef from an NSView or NSWindow?
关于 macOS 辅助功能 API,无论如何创建一个对应于 NSView 或 NSWindow 的 AXUIElementRef?
在使用 AXUIElementCreateWithHIObjectAndIdentifier 的 Carbon 时代,似乎有一种方法可以做到这一点,但该功能不再可用。
我知道的唯一方法是使用 Accessibility API 递归搜索应用程序的整个 UI 元素层次结构,寻找与 NSView 或 NSWindow 匹配的元素。 但是除了是一个繁重的解决方案之外,它甚至不能保证成功,因为可能没有一种方法可以通过使用 AXUIElementRef 的可用属性来积极对应 AXUIElementRef 和 Cocoa 对象。
我愿意考虑帮助实现这一目标的未记录的 API。
我找到了在 iOS 中做同样事情的方法。
我知道这不是对您问题的直接回答,但我会尝试解释我在 iOS 中找到它所做的工作,希望您能够在 macOS 中做同样的事情。 此外,这可能对其他读者有用......
我首先猜测流程本身正在创建AXUIElementRef
,因此当我请求具有AXUIElementRef
值的可访问性属性(例如kAXUIElementAttributeChildren
时,它必须创建它们。
然后我创建了一个应用程序,并 dlsym'ed _AXUIElementCreateAppElementWithPid(int pid)
,用[[NSProcessInfo processInfo] processIdentifier]
调用它。 我收到了根AXUIElementRef
,然后我将其传递给AXError AXUIElementCopyMultipleAttributeValues(AXUIElementRef element, CFArrayRef attributes, AXCopyMultipleAttributeOptions options, CFArrayRef _Nullable *values)
,请求kAXUIElementAttributeChildren
,它工作(应该在主线程上运行)!
我开始在汇编代码AXUIElementCopyMultipleAttributeValues
心地调试AXUIElementCopyMultipleAttributeValues
调用,它非常像这样(这是非常伪代码,当然......):
// serialize the arguments for MIG call
if (axUIElementRef->pid == self pid) {
// that's good that we are calling our own process, we can easily keep debugging!
_MIGXAAXUIElementCopyMultipleAttributeValues(serialized arguments) {
// Get the original element from the AXUIElementRef:
UIView* view = _AXElementForAXUIElementUniqueId(id);
[view accessibilityAttributeValue:kAXUIElementAttributeChildren] {
[view _accessibilityUserTestingChildren] {
// since this is the UIApplication element, it just gets the windows:
NSArray*<UIWindow*> winArr = [(UIApplication*)view _accessibilityWindows];
// for each value in result, convert to AX value:
...
AXConvertOutgoingValue(winArr) {
// For each UIView, convert to AXUIElementRef:
AXUIElementRef e = _AXCreateAXUIElementWithElement(winArr[i]);
}
}
}
}
} else {
// Do the same only if we are entitled, and outside our process
}
因此,在 iOS 中,您只需调用AXUIElementRef _AXCreateAXUIElementWithElement(UIView*);
从 UI 转换为辅助功能元素,以及UIView* _AXElementForAXUIElementUniqueId(AXUIElementRefGetUniqueID(AXUIElementRef));
在相反的方向。
所有符号都来自AXRuntime.framework
。
在 mac 中,您需要链接ApplicationServices.framework
并尝试类似的操作。
希望这可以帮助...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.