2011-05-30 76 views
19

我正在研究一个将第三方应用程序的窗口在屏幕上移动的应用程序。通过OSX可访问性获取窗口号API

为了得到当前打开的所有窗口的概述,我用

CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); 

这将返回字典定义每一个打开的窗口的数组。 下面是一个典型的字典返回:

{ 
    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; 
}, 

的词典已满的其他地方使用良好的信息,但缺乏可用于修改Windows的位置可访问的对象。窗口号码清楚地标识了Windows。

我现在用的PID(kCGWindowOwnerPID)创建窗口的应用程序可访问对象:

AXUIElementRef app = AXUIElementCreateApplication(pid); 

随后检索应用程序使用AXUIElementCopyAttributeValues打开的​​所有窗口的列表:

NSArray *result; 

AXUIElementCopyAttributeValues(
           (AXUIElementRef) app, 
           kAXWindowsAttribute, 
           0, 
           99999, 
           (CFArrayRef *) &result 
           ); 

这可以工作并返回一个AXUIElements数组。 这是我卡住的地方。似乎没有API调用来检索辅助功能对象的窗口号。有什么办法要么

a)求的辅助功能对象的窗口编号(最终迭代这个数组,并找到合适的窗口)

b)否则清楚地匹配所描述的一个窗口由CGWindowListCopyWindowInfo返回给由AXUIElementCopyAttributeValues返回的辅助功能对象的数组?

回答

21

我们最终为此任务聘请了专门的可访问性开发人员。

事实证明,如果不使用未记录的API(在我们的例子中不行),没有办法做到这一点。

幸运的是,有一个实际的解决办法:

遍历应用程序的所有打开的窗口。获取自己的位置,大小和标题:

AXUIElementCopyAttributeValue(target, kAXPositionAttribute, CFTypeRef*)&posValue); 
AXUIElementCopyAttributeValue(target, kAXSizeAttribute, (CFTypeRef*)&sizeValue); 
AXUIElementCopyAttributeValue(target, kAXTitleAttribute, (CFTypeRef*)&titleValue); 

接下来,转换位置和大小转化为实际CGPointCGSize值:

AXValueGetValue(posValue, kAXValueCGPointType, &point); 
AXValueGetValue(sizeValue, kAXValueCGSizeType, &size); 

比较反对由对象返回的值的大小,位置和标题在CGWindowListCopyWindowInfo()。 如果它们匹配,则可以放心地假定它是您正在寻找的窗口,并使用已打开的AXUIElement(我们的案例中的target)来处理它。

在OSX上,循环浏览所有打开的窗口的开销变得微不足道。有多少个窗户同时打开的数量相当低。此外,虽然这不是100%准确(2个窗口可能具有相同的位置,大小和标题),但在迄今为止发生这种情况时,我们还没有遇到任何实际使用情况。

+9

对于那些可以使用无证API的应用程序,它将如何完成? – Samuel 2012-08-23 05:01:55

8

有一个私人函数用于获取窗口给定AX对象的CG窗口编号:_AXUIElementGetWindow。 在SO讨论中的更多细节Uniquely identify active window on OS X 看起来好像没有公共API可以100%的概率完成任务。通过标题和框架标识窗口(如上面的答案中所述)将适用于99.9%的案例。