【发布时间】:2017-04-09 21:51:11
【问题描述】:
您可以使用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++ 选项。
【问题讨论】:
-
您的意思是要模拟点击被其他窗口遮挡的窗口部分?如果它没有被遮挡,那么就没有问题。将鼠标放在窗口显示部分上方的位置将导致它被路由到该窗口。否则,您可以尝试
CGEventPostToPSN()将其直接发布到拥有应用程序的进程,尽管它仍会转到该应用程序内事件位置最前面的窗口。 -
这里的想法是它被遮蔽了。这样我就可以自动执行一项任务(在当前窗口遮挡的窗口中单击一些 UI),而不会中断我的主要任务。我正在调查 CGEventPostToPSN。看起来 GetProcessForPID 已被弃用?是否有其他方法可以获取进程的 ProcessSerialNumber?
-
我认为没有现代替代品。我只会使用
GetProcessForPID(),如果你发现它有效并且你依赖它,请向 Apple 提交一个错误,要求适当替换CGEventPostToPSN()。 -
CGEventPostToPSN 运行良好,但我觉得 GetProcessForPID 已被弃用。 NSWorkspace launchApplications 还提供了对 PSN 结构所需的 serialnumberLow 和 High 值的访问权限,但该方法也已被弃用,取而代之的是 runningApplications,它没有该信息
-
应用是否处理后台点击?我不知道 Chrome,但 Safari 和 FireFox 不知道。
标签: objective-c macos