2015-04-02 55 views
14

我正在使用CGEventTapCreateForPSN来为我的应用程序捕获和筛选密钥。我不想拦截其他应用程序的事件。我很确定事件点击是为了我的目的而过于沉重,但我一直无法找到更好的方法,并使用事件点击工作。小牛+中的CGEventTapCreateForPSN +(取消当前进程)

具体来说,此代码做我想要的。

GetCurrentProcess(&psn); 
CFMachPortRef eventTap = CGEventTapCreateForPSN(
    &psn, 
    kCGHeadInsertEventTap, 
    kCGEventTapOptionDefault, 
    CGEventMaskBit(kCGEventKeyDown) 
     | CGEventMaskBit(kCGEventKeyUp), 
    eventCallback, 
    userInfo); 

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

不幸的是,所有获得当前ProcessSerialNumber的方法从10.9开始已被弃用。有得到ProcessSerialNumber传递到其他程序在同一个进程,这个初始化的老标准的方式...

ProcessSerialNumber psn = { 0, kCurrentProcess }; 

但调用CGEventTapCreateForPSN时不起作用。头文件docs表示同样多,下面的代码片段返回NULL作为确认。

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

我可以用CGEventTapCreate但水龙头整个主机,然后我将需要过滤嘴不是针对我的应用程序,而CGEventTapProxy是不透明的,我不知道如何使用它来确定如果它是我的应用程序或不。

我已验证过时的代码仍然有效,但Apple可以随时决定将其删除。那么,有没有人有一个想法,我应该如何继续在小牛队和其他地方拨打CGEventTapCreateForPSN

谢谢!

+1

这不完全是你的问题的答案,但关于可能更好的方法,你看过'+ [NSEvent addLocalMonitorForEventsMatchingMask:handler:]'? – JWWalker 2015-04-17 21:04:39

+0

在这种特殊情况下安装较重的事件分接头的动力是我需要在弹出式菜单事件循环期间拦截(并且可能改变或防止)键盘事件。不幸的是,[NSEvent addLocalMonitorForEventsMatchingMask:handler:]'不监视嵌套事件循环中的事件。 – 2015-04-18 14:02:13

+2

我用于过滤鼠标事件的另一种方法是在事件分派器目标('GetEventDispatcherTarget()')上安装Carbon事件处理程序。据我可以从10.10 SDK头中得知,必要的API不会被弃用,并且可用于64位。 – JWWalker 2015-04-18 15:14:33

回答

0

我认为你应该子类NSApplication和覆盖- (void)sendEvent:(NSEvent *)theEvent方法为此目的。 从docs

你很少会发现真正需要创建一个自定义的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]; 
} 

我不确定这种方法是否可以解决问题,但您仍然试试。

+0

不,这不起作用。请仔细阅读文档。该方法仅适用于主事件中调度的事件它不处理嵌套的事件循环,请参阅附加到原始文章的注释以进行相同的讨论。 – 2015-05-21 21:24:36