代码之家  ›  专栏  ›  技术社区  ›  Corey Floyd

在Cocoa状态栏应用程序中接收按键和按键事件

  •  1
  • Corey Floyd  · 技术社区  · 16 年前

    如果您创建了一个没有窗口的状态栏应用程序,您如何响应事件?

    我的第一个猜测是创建一个子类NSResponder并重写适当的方法。 但是他们从来没有接到过电话。

    该领导明确要求:

    [self becomeFirstResponder];
    

    这也不起作用(我也不相信是苹果文档公司推荐的)

    有什么方法可以在响应链中获取我的NSResponder子类吗?

    2 回复  |  直到 16 年前
        1
  •  2
  •   Rob Keniger    16 年前

    如果没有窗口,您希望接收什么类型的关键事件?

    如果您需要在全球范围内拦截关键事件,那么您将需要使用Quartz事件tap。您必须非常小心,因为在事件中引发异常tap处理程序可能会冻结窗口服务器,因此您应该有适当的异常处理。

    #import <ApplicationServices/ApplicationServices.h>
    
    //assume CGEventTap eventTap is an ivar or other global
    
    void createEventTap(void)
    {
     CFRunLoopSourceRef runLoopSource;
    
     ///we only want keydown events
     CGEventMask eventMask = (1 << kCGEventKeyDown);
    
     // Keyboard event taps need Universal Access enabled, 
     // check whether we're allowed to attach an event tap
     if (!AXAPIEnabled()&&!AXIsProcessTrusted()) { 
      // error dialog here 
      NSAlert *alert = [[[NSAlert alloc] init] autorelease];
      [alert addButtonWithTitle:@"OK"];
      [alert setMessageText:@"Could not start event monitoring."];
      [alert setInformativeText:@"Please enable \"access for assistive devices\" in the Universal Access pane of System Preferences."];
      [alert runModal];
      return;
     } 
    
    
     //create the event tap
     eventTap = CGEventTapCreate(kCGHIDEventTap, //this intercepts events at the lowest level, where they enter the window server
            kCGHeadInsertEventTap, 
            kCGEventTapOptionDefault, 
            eventMask,
            myCGEventCallback, //this is the callback that we receive when the event fires
            nil); 
    
     // Create a run loop source.
     runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
    
     // Add to the current run loop.
     CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
    
     // Enable the event tap.
     CGEventTapEnable(eventTap, true);
    }
    
    
    //the CGEvent callback that does the heavy lifting
    CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef theEvent, void *refcon)
    {
     //handle the event here
     //if you want to capture the event and prevent it propagating as normal, return NULL.
    
     //if you want to let the event process as normal, return theEvent.
     return theEvent;
    }
    
        2
  •  2
  •   Corey Floyd    16 年前

    当然,答案很简单:

    [NSApp currentEvent]; 
    

    返回任何Cocoa应用程序中的当前事件。