将 NSEvent 发送到后台应用程序

发布于 2024-12-04 21:29:02 字数 2114 浏览 0 评论 0原文

我需要将组合键 ^⌘C 发送到具有捆绑标识符 com.company.app 的后台应用程序。然后组合键应该激活该应用程序中的菜单项。

不幸的是,我不知道该怎么做。一些研究向我指出了使用 CGEventPostToPSN() 的 NSEvent 和 CGEvent API,但我无法使其正常工作,因为我不知道如何设置组合键。 CGEventPost() 似乎无法处理我创建的事件,即使所需的应用程序是活动的。

这是我最终想出的代码,但不起作用:

CGWindowID windowNumber;
NSEvent *event = [NSEvent keyEventWithType:NSKeyUp
                                  location:NSZeroPoint
                             modifierFlags:(NSControlKeyMask | NSCommandKeyMask)
                                 timestamp:[[NSProcessInfo processInfo] systemUptime]
                              windowNumber:windowNumber
                                   context:[NSGraphicsContext currentContext]
                                characters:@"c"
               charactersIgnoringModifiers:@"c"
                                 isARepeat:NO
                                   keyCode:8];
CGEventRef eventRef = [event CGEvent];

我现在应该对该事件做什么?为什么没有与 CGEventPost() 等效的 NSEvent ?有没有比发布事件更简单的方法来激活该菜单项?我可以轻松获取 NSRunningApplication 的实例,但没有合适的 API 来完成我的任务。

更新: 我得到它的工作:

- (void) postFakedKeyboardEventForCopyScreenToPasteboardToPSN:(ProcessSerialNumber)psn {
    CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStatePrivate);
    CGEventRef keyDownEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)8, true);
    CGEventSetFlags(keyDownEvent, (kCGEventFlagMaskControl | kCGEventFlagMaskCommand));
    CGEventRef keyUpEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)8, false);
    CGEventSetFlags(keyUpEvent, (kCGEventFlagMaskControl | kCGEventFlagMaskCommand));
    CFRelease(source);

    CGEventPostToPSN(&psn, keyDownEvent);
    CFRelease(keyDownEvent);
    CGEventPostToPSN(&psn, keyUpEvent);
    CFRelease(keyUpEvent);
}

...

OSStatus err = noErr;
ProcessSerialNumber psn;
err = GetProcessForPID([simulator processIdentifier], &psn);
if (err == noErr)
    [self postFakedKeyboardEventForCopyScreenToPasteboardToPSN:psn];

I need to send the key combo ^⌘C to a background app with the bundle identifier com.company.app. The key combo should then activate a menu item in that application.

Unfortunately, I have no clue how to do that. Some research pointed me to the NSEvent and CGEvent API using CGEventPostToPSN(), but I was unable to get it work correctly, as I don't know how to set up the key combo. CGEventPost() didn't seem to work with the events I created, even if the desired app is the active one.

Here is the code I eventually came up with but that doesn't work:

CGWindowID windowNumber;
NSEvent *event = [NSEvent keyEventWithType:NSKeyUp
                                  location:NSZeroPoint
                             modifierFlags:(NSControlKeyMask | NSCommandKeyMask)
                                 timestamp:[[NSProcessInfo processInfo] systemUptime]
                              windowNumber:windowNumber
                                   context:[NSGraphicsContext currentContext]
                                characters:@"c"
               charactersIgnoringModifiers:@"c"
                                 isARepeat:NO
                                   keyCode:8];
CGEventRef eventRef = [event CGEvent];

What am I supposed to do with that event now? Why is there no NSEvent equivalent for CGEventPost()? Is there even an easier way to activate that menu item than posting an event? I can easily get an instance of NSRunningApplication, but there is no suitable API to accomplish my task.

Update:
I got it working:

- (void) postFakedKeyboardEventForCopyScreenToPasteboardToPSN:(ProcessSerialNumber)psn {
    CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStatePrivate);
    CGEventRef keyDownEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)8, true);
    CGEventSetFlags(keyDownEvent, (kCGEventFlagMaskControl | kCGEventFlagMaskCommand));
    CGEventRef keyUpEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)8, false);
    CGEventSetFlags(keyUpEvent, (kCGEventFlagMaskControl | kCGEventFlagMaskCommand));
    CFRelease(source);

    CGEventPostToPSN(&psn, keyDownEvent);
    CFRelease(keyDownEvent);
    CGEventPostToPSN(&psn, keyUpEvent);
    CFRelease(keyUpEvent);
}

...

OSStatus err = noErr;
ProcessSerialNumber psn;
err = GetProcessForPID([simulator processIdentifier], &psn);
if (err == noErr)
    [self postFakedKeyboardEventForCopyScreenToPasteboardToPSN:psn];

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

記憶穿過時間隧道 2024-12-11 21:29:02

一些注意事项:

  1. 也发送 keyDown 事件,而不仅仅是 keyUp。这样,它将更像是真正的按键。

  2. 您需要使用该 CGEvent 调用 CGEventPostToPSN,或者至少调用一些发布事件的调用。

  3. 您是否尝试过调用 CGPostKeyboardEvent() ?

A few notes:

  1. Send a keyDown event, too, not just keyUp. That way, it will be more like a real keypress.

  2. You need to call CGEventPostToPSN with that CGEvent, or at least SOME call that posts the event.

  3. Have you tried calling CGPostKeyboardEvent() instead?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文