0x9*_*x90 22 cocoa accessibility macos-carbon objective-c accessibility-api
我正在开发一个应用程序,可以在屏幕上移动第三方应用程序的窗口.
为了概述所有当前打开的窗口,我使用
CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
Run Code Online (Sandbox Code Playgroud)
这将返回定义每个打开窗口的字典数组.这是一个返回的示例字典:
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 442;
Width = 475;
X = 3123;
Y = "-118";
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 907184;
kCGWindowName = Untitled;
kCGWindowNumber = 7328;
kCGWindowOwnerName = TextEdit;
kCGWindowOwnerPID = 20706;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 3;
},
Run Code Online (Sandbox Code Playgroud)
字典中充满了其他地方使用的良好信息,但缺少可用于修改窗口位置的辅助功能对象.窗口编号清楚地标识Windows.
我现在使用PID(kCGWindowOwnerPID)为窗口的应用程序创建一个辅助功能对象:
AXUIElementRef app = AXUIElementCreateApplication(pid);
Run Code Online (Sandbox Code Playgroud)
然后使用AXUIElementCopyAttributeValues检索应用程序已打开的所有窗口的列表:
NSArray *result;
AXUIElementCopyAttributeValues(
(AXUIElementRef) app,
kAXWindowsAttribute,
0,
99999,
(CFArrayRef *) &result
);
Run Code Online (Sandbox Code Playgroud)
这适用于并返回一组AXUIElements.这是我被困的地方.似乎没有API调用来检索辅助功能对象的窗口号.有没有办法
a)找到辅助功能对象的窗口编号(最终迭代数组并找到正确的窗口)
要么
b)否则,将CGWindowListCopyWindowInfo返回的数组中描述的窗口与AXUIElementCopyAttributeValues返回的辅助功能对象清楚地匹配?
0x9*_*x90 24
我们最终聘请了一位专门的辅助功能开发人员来完成这项任务.
事实证明,如果不使用未记录的API,就无法做到这一点(在我们的案例中不行).
幸运的是,有一个实际的解决方法:
循环遍历应用程序的所有打开窗口.获得他们的位置,大小和头衔:
AXUIElementCopyAttributeValue(target, kAXPositionAttribute, CFTypeRef*)&posValue);
AXUIElementCopyAttributeValue(target, kAXSizeAttribute, (CFTypeRef*)&sizeValue);
AXUIElementCopyAttributeValue(target, kAXTitleAttribute, (CFTypeRef*)&titleValue);
Run Code Online (Sandbox Code Playgroud)
接下来,将位置和大小转换为实际值CGPoint和CGSize值:
AXValueGetValue(posValue, kAXValueCGPointType, &point);
AXValueGetValue(sizeValue, kAXValueCGSizeType, &size);
Run Code Online (Sandbox Code Playgroud)
将大小,位置和标题与对象返回的值进行比较CGWindowListCopyWindowInfo().如果它们匹配,您可以放心地假设它是您正在寻找的窗口并使用已经打开的AXUIElement(target在我们的例子中)来工作.
在OSX上,循环通过所有打开的窗口的开销几乎可以忽略不计.同时打开多少个窗口的上限相当低.
此外,虽然这不是100%准确(2个窗口可能有相同的位置,大小和标题),但到目前为止,我们还没有遇到任何实际使用情况.
有一个私有函数用于获取窗口的给定AX对象的CG窗口号:_AXUIElementGetWindow.SO讨论中的更多细节在OS X上唯一标识活动窗口
看起来没有公共API以100%的概率执行任务.按标题和框架识别窗口(如上面的答案中所述)将在99.9%的情况下有效.