2011-05-30 88 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%的案例。