Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 通过OSX可访问性API获取窗口号_Objective C_Cocoa_Accessibility_Macos Carbon_Accessibility Api - Fatal编程技术网

Objective c 通过OSX可访问性API获取窗口号

Objective c 通过OSX可访问性API获取窗口号,objective-c,cocoa,accessibility,macos-carbon,accessibility-api,Objective C,Cocoa,Accessibility,Macos Carbon,Accessibility Api,我正在开发一个可以在屏幕上移动第三方应用程序窗口的应用程序 要获得当前打开的所有窗口的概览,我使用 CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); 这将返回定义每个打开窗口的字典数组。 以下是返回的示例词典: { kCGWindowAlpha = 1; kCGWindowBounds =

我正在开发一个可以在屏幕上移动第三方应用程序窗口的应用程序

要获得当前打开的所有窗口的概览,我使用

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;
},
字典中充满了其他地方使用的有用信息,但缺少可用于修改窗口位置的辅助对象。窗户由窗户编号清楚标识

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

AXUIElementRef app = AXUIElementCreateApplication(pid);
然后检索应用程序使用AxUIElementCopyAttributeValue打开的所有窗口的列表:

NSArray *result;

AXUIElementCopyAttributeValues(
                               (AXUIElementRef) app, 
                               kAXWindowsAttribute,
                               0,
                               99999,
                               (CFArrayRef *) &result
                               );
这将工作并返回AXUIElements数组。 这就是我被困的地方。似乎没有API调用来检索可访问性对象的窗口号。有没有什么办法

a) 找到可访问性对象的窗口号(最终遍历数组并找到正确的窗口)


b) 否则,请将CGWindowListCopyWindowInfo返回的数组中描述的窗口与AxuiElementCopyAttributeValue返回的辅助功能对象明确匹配?

我们为此任务雇佣了一名专门的辅助功能开发人员

事实证明,如果不使用未记录的API(在我们的案例中是不允许的),就无法做到这一点

幸运的是,有一个切实可行的解决办法:

循环应用程序的所有打开窗口。获取他们的位置、大小和头衔:

AXUIElementCopyAttributeValue(target, kAXPositionAttribute, CFTypeRef*)&posValue);
AXUIElementCopyAttributeValue(target, kAXSizeAttribute, (CFTypeRef*)&sizeValue);
AXUIElementCopyAttributeValue(target, kAXTitleAttribute, (CFTypeRef*)&titleValue);
接下来,将位置和大小转换为实际的
CGPoint
CGSize
值:

AXValueGetValue(posValue, kAXValueCGPointType, &point);
AXValueGetValue(sizeValue, kAXValueCGSizeType, &size);
将大小、位置和标题与
CGWindowListCopyWindowInfo()
中对象返回的值进行比较。 如果它们匹配,您可以安全地假设它是您正在查找的窗口,并使用已经打开的AXUIElement(
target
,在本例中)来处理它

在OSX上,在所有打开的窗口中循环的开销可以忽略不计。同时打开多少扇窗户的上限很低


此外,虽然这不是100%准确(可能有两个窗口具有相同的位置、大小和标题),但到目前为止,我们在实际使用中还没有遇到这种情况。

有一个私有函数可用于获取给定AX对象的CG窗口编号:
\u AXUIElementGetWindow
。 更多细节请参见SO讨论
看起来好像没有公共API来以100%的概率完成任务。通过标题和框架识别窗口(如上面的回答所述)将在99.9%的情况下起作用。

对于那些可以使用未记录API的窗口,如何做到这一点?