这是我现在在做什么首先,我使用CGWindowListCopyWindowInfo找到窗口及其PID的列表.然后,对于每个窗口,我使用AXUIElementCreateApplication获取窗口的AXUIElementRef.之后,我应该使用AXUIElementCopyAttributeValue与属性kAXPositionAttribute(我没有得到正确的位置,总是得到零).最后,我应该将所需的偏移量添加到位置,并使用属性kAXPositionAttribute和新的位置点(即使我设置了绝对值,如0,0),我得到运行时错误的AXUIElementSetAttributeValue).
有人可以用我上面描述的代码片段来帮助我,因为我尝试了许多事情,没有任何运气.此外,它不应该像我决定在上面实现的那样完全正确.如果有更好的方法去做,那么我会很乐意改变它.
// Get all the windows CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly,kCGNullWindowID); NSArray* arr = CFBridgingRelease(windowList); // Loop through the windows for (NSMutableDictionary* entry in arr) { // Get window PID pid_t pid = [[entry objectForKey:(id)kCGWindowOwnerPID] intValue]; // Get AXUIElement using PID AXUIElementRef elementRef = AXUIElementCreateApplication(pid); CFTypeRef position; CGPoint point; // Get the position attribute of the window (maybe something is wrong?) AXUIElementCopyAttributeValue(elementRef,kAXPositionAttribute,(CFTypeRef *)&position); AXValueGetValue(position,kAXValueCGPointType,&point); // Debugging (always zeros?) NSLog(@"point=%@",point); // Create a point NSPoint newPoint; newPoint.x = 0; newPoint.y = 0; position = (CFTypeRef)(AXValueCreate(kAXValueCGPointType,(const void *)&newPoint)); // Set the position attribute of the window (runtime error over here) AXUIElementSetAttributeValue(elementRef,(CFTypeRef *)&position); }
解决方法
这里有几个注意事项:
>您正在通过PID检索应用程序,然后作为窗口执行.这是您问题的核心,但它只是解决方案的开始.
>您将需要走出可访问性应用程序对象的窗口列表,以便找到可以使用辅助功能框架移动的可重定位窗口.
> CGWindowListCopyWindowInfo将在询问您的方式时返回“全屏幕”窗口,但不能保证这些窗口是“用户窗口”或具有可访问性的窗口.大多数菜单栏项目都有一个根窗口,它是“屏幕上的”,大多数菜单栏是不可访问的(当您尝试走出您检索的PID的辅助功能树时显示).
>您可能会发现AXRole的测试是有帮助的,或者您可能会发现其他窗口辅助功能属性在确定是否移动窗口方面更有用.
我已经在这里修改了你的代码(这将运行而不会崩溃),这将从您通过PID检索的应用程序获取相关的窗口信息,然后移动窗口.我有一个睡眠声明,所以我可以停止执行,因为我只是测试运动的效果:
#import <Foundation/Foundation.h> #import <CoreFoundation/CoreFoundation.h> #import <ApplicationServices/ApplicationServices.h> int main(int argc,char *argv[]) { @autoreleasepool { // Get all the windows CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly,kCGNullWindowID); NSArray* arr = CFBridgingRelease(windowList); // Loop through the windows for (NSMutableDictionary* entry in arr) { // Get window PID pid_t pid = [[entry objectForKey:(id)kCGWindowOwnerPID] intValue]; // Get AXUIElement using PID AXUIElementRef appRef = AXUIElementCreateApplication(pid); NSLog(@"Ref = %@",appRef); // Get the windows CFArrayRef windowList; AXUIElementCopyAttributeValue(appRef,kAXWindowsAttribute,(CFTypeRef *)&windowList); NSLog(@"WindowList = %@",windowList); if ((!windowList) || CFArrayGetCount(windowList)<1) continue; // get just the first window for now AXUIElementRef windowRef = (AXUIElementRef) CFArrayGetValueAtIndex( windowList,0); CFTypeRef role; AXUIElementCopyAttributeValue(windowRef,kAXRoleAttribute,(CFTypeRef *)&role); CFTypeRef position; CGPoint point; // Get the position attribute of the window (maybe something is wrong?) AXUIElementCopyAttributeValue(windowRef,(CFTypeRef *)&position); AXValueGetValue(position,&point); // Debugging (always zeros?) NSLog(@"point=%f,%f",point.x,point.y); // Create a point CGPoint newPoint; newPoint.x = 0; newPoint.y = 0; NSLog(@"Create"); position = (CFTypeRef)(AXValueCreate(kAXValueCGPointType,(const void *)&newPoint)); // Set the position attribute of the window (runtime error over here) NSLog(@"SetAttribute"); AXUIElementSetAttributeValue(windowRef,position); sleep(5); } } }