将NSEvent发送到后台应用程序

7
我需要将键组合 ^⌘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];

现在这才是一个选择器!并不是特别针对你,但是为什么 Obj-C 世界里的每个人都要给它们的方法起这样巨大的名字呢?postFakedKeyboardEventForCopyScreenToPasteboardToPSN - tomsmeding
1个回答

1
一些注意事项:
  1. 发送一个 keyDown 事件,而不仅仅是 keyUp。这样做会更像真正的按键。

  2. 你需要使用 CGEventPostToPSN 函数调用该 CGEvent,或者至少需要某个调用来发布该事件。

  3. 你试过调用 CGPostKeyboardEvent() 吗?

CGPostKeyboardEvent()已被弃用,但我使用文档中推荐的函数使其正常工作。你能解释一下如何使用CGEventPostToPSN()吗?谢谢 :) - Fabian Kreiser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接