我尝试使用辅助功能API来更改其他应用程序窗口的位置。我希望做的是从所有应用程序获取屏幕上的所有窗口,然后将它们全部移动到给定的偏移量(让我们说5或10或任何值)。我这样做有困难,因为这是我在Objective-C中编程的第一天。
这就是我现在正在做的事情。首先,我使用CGWindowListCopyWindowInfo
找到窗口列表及其PID。然后,对于每个窗口,我使用AXUIElementCreateApplication
来获取窗口的AXUIElementRef
。之后,我应该使用AXUIElementCopyAttributeValue
属性kAXPositionAttribute
(我无法获得正确的位置,总是得到零)。最后,我应该将想要的偏移量添加到位置并使用AXUIElementSetAttributeValue
和属性kAXPositionAttribute
以及新的位置点(即使我设置了0,0的绝对值,我也会得到运行时错误)。 / p>
有人可以用我上面描述的片段来帮助我,因为我尝试了许多没有运气的东西。此外,它不应该与我决定在上面实现它完全一样。如果有更好的方法去做,那么我很乐意改变它。
更新 根据评论中的要求,以下是其中一次尝试的代码段:
// 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, kAXPositionAttribute, (CFTypeRef *)&position);
}
答案 0 :(得分:21)
根据您的示例代码(略有修改,因为您发布的内容未编译且未经修改会崩溃),我做了一些实验。
以下是一些注意事项:
CGWindowListCopyWindowInfo
将返回“屏幕上的所有”窗口,但不保证这些是“用户窗口”或具有辅助功能的窗口。大多数菜单栏项目都有一个“在屏幕上”的根窗口,其中大多数都不可访问(当您尝试为您检索的PID遍历辅助功能树时会显示该窗口。)我在这里包含了对代码的修改(这将运行而不会崩溃),它将从您通过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, kAXPositionAttribute, (CFTypeRef *)&position);
AXValueGetValue(position, kAXValueCGPointType, &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, kAXPositionAttribute, position);
sleep(5);
}
}
}