从CGWindowListCreate模拟另一个窗口上的鼠标按下事件

时间:2017-04-09 21:51:12

标签: objective-c macos

您可以使用CGWindowListCreate列出当前打开的窗口,例如:

CFArrayRef windowListArray = CGWindowListCreate(kCGWindowListOptionOnScreenOnly|kCGWindowListExcludeDesktopElements, kCGNullWindowID);
NSArray *windows = CFBridgingRelease(CGWindowListCreateDescriptionFromArray(windowListArray));

// stuff here with windows array

CFRelease(windowListArray);

通过这个,您可以获得一个特定的窗口,例如来自Chrome的窗口,它位于当前工作空间的背景中,但未最小化。我还发现你可以使用CGEventCreateMouseEvent在屏幕上的任何地方模拟鼠标点击:

CGEventRef click_down = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, point, kCGMouseButtonLeft);
CGEventPost(kCGHIDEventTap, click_down);

我可以将此事件发送到后台窗口,而不是将此事件发送到屏幕上此点下方的最前面的窗口吗?或者是暂时切换到该窗口(将其置于前面),单击并切换回上一个最前面窗口的唯一方法?

这篇文章表明后者是可能的: Cocoa switch focus to application and then switch it back

虽然我非常有兴趣了解是否可以避免这种情况,但我们是否可以将鼠标点击直接发送到背景中的特定窗口而不会将其显示在视野中。我可以考虑任何Objective-C,C或C ++选项。

1 个答案:

答案 0 :(得分:2)

在找到弃用的GetPSNForPID函数的替代方法后,最终得到了这个工作:

NSEvent *customEvent = [NSEvent mouseEventWithType: NSEventTypeLeftMouseDown
                                          location: point
                                     modifierFlags: NSEventModifierFlagCommand
                                         timestamp:[NSDate timeIntervalSinceReferenceDate]
                                      windowNumber:[self.windowID intValue]
                                           context: nil
                                       eventNumber: 0
                                        clickCount: 1
                                          pressure: 0];

CGEvent = [customEvent CGEvent];
CGEventPostToPid(PID, CGEvent);

没有意识到有一个CGEventPostToPid方法而不是CGEventPostToPSN。不需要ProcessSerialNumber结构。