小牛队中的CGEventTapCreateForPSN +(不推荐使用GetCurrentProcess)

Jod*_*ins 15 macos cocoa cgeventtap osx-mavericks osx-yosemite

我正在使用CGEventTapCreateForPSN陷阱和过滤我的应用程序的键.我对拦截其他应用程序的事件不感兴趣.我很确定一个事件水龙头太重了我的目的,但我一直无法找到更好的方法,并使用事件水龙头工作.

具体来说,这段代码可以满足我的需求.

GetCurrentProcess(&psn);
CFMachPortRef eventTap = CGEventTapCreateForPSN(
    &psn,
    kCGHeadInsertEventTap,
    kCGEventTapOptionDefault,
    CGEventMaskBit(kCGEventKeyDown)
        | CGEventMaskBit(kCGEventKeyUp),
    eventCallback,
    userInfo);
Run Code Online (Sandbox Code Playgroud)

并且我的回调处理得很好,事件只从当前应用程序中截获.

不幸的是,ProcessSerialNumber从10.9开始,所有获得当前的方法都已被弃用.有一种旧的标准方法可以ProcessSerialNumber在同一个进程中传递给其他例程,这个初始化...

ProcessSerialNumber psn = { 0, kCurrentProcess };
Run Code Online (Sandbox Code Playgroud)

但是在打电话时这不起作用CGEventTapCreateForPSN.头文件docs表示尽可能多,并且以下代码段NULL作为确认返回.

ProcessSerialNumber psn = { 0, kCurrentProcess };
CFMachPortRef eventTap = CGEventTapCreateForPSN(
    &psn,
    kCGHeadInsertEventTap,
    kCGEventTapOptionDefault,
    CGEventMaskBit(kCGEventKeyDown)
        | CGEventMaskBit(kCGEventKeyUp),
    eventCallback,
    userInfo);
Run Code Online (Sandbox Code Playgroud)

我可以使用,CGEventTapCreate但它点击整个主机,然后我需要过滤任何不指向我的应用程序的东西,并且CGEventTapProxy是不透明的,我不知道如何使用它来确定它是否是我的应用程序.

我已经验证了已弃用的代码仍然有效,但Apple可以随时决定将其删除.那么,有没有人知道我应该怎样继续CGEventTapCreateForPSN在小牛队以及其他地方打电话?

谢谢!


UPDATE

在10.11(我认为那是El Capitan),增加了一个新功能.虽然它没有文档,但它的签名几乎完全相同CGEventTapCreateForPSN.

CFMachPortRef CGEventTapCreateForPSN(
    void *processSerialNumber,
    CGEventTapPlacement place,
    CGEventTapOptions options,
    CGEventMask eventsOfInterest,
    CGEventTapCallBack callback,
    void *userInfo);

CFMachPortRef CGEventTapCreateForPid(
    pid_t pid,
    CGEventTapPlacement place,
    CGEventTapOptions options,
    CGEventMask eventsOfInterest,
    CGEventTapCallBack callback,
    void *userInfo);
Run Code Online (Sandbox Code Playgroud)

因此,不需要不推荐使用的功能,因为PID可以用作第一个参数.

Ast*_*ria 1

我认为你应该- (void)sendEvent:(NSEvent *)theEvent为此目的子类化 NSApplication 并重写方法。来自文档

您很少会发现真正需要创建自定义 NSApplication 子类。与一些面向对象的库不同,Cocoa 不需要您子类化 NSApplication 来自定义应用程序行为。相反,它为您提供了许多其他方式来自定义应用程序。

还:

重要的

许多 AppKit 类依赖于 NSApplication 类,并且在该类完全初始化之前可能无法正常工作。因此,您不应该尝试从 NSApplication 子类的初始化方法调用其他 AppKit 类的方法。

因此,您可以拦截通过应用程序传递的所有事件并调用自定义 NSApplicationDelegate 继承的协议方法。

// in SubApplication.h

@protocol ExtendedApplicationDelegate : NSApplicationDelegate

- (void)applicationDidTrapSomeInterestingEvent:(NSEvent *)event;

@end

// in SubApplication.m

- (void)sendEvent:(NSEvent *)event
{
    if ([event type] == NSKeyDown && [event keyCode]==_someCode)
    {
      // call application delegate method
    }
    [super sendEvent:event];
}
Run Code Online (Sandbox Code Playgroud)

我不确定这种方法是否能解决问题,但你仍然可以尝试一下。