如何在Cocoa应用程序中处理箭头键事件?

时间:2011-05-14 06:08:06

标签: cocoa keyboard-events

如何在Cocoa app中处理箭头键事件?

3 个答案:

答案 0 :(得分:16)

但是,但是......但我不想成为NSResponder子类。

@interface AMonitorNotAResponder : NSObject 
@end

@implementation AMonitorNotAResponder
{
    id eventMonitor;   // An event monitor object; instance of
                       // private class _NSLocalEventObserver
}

- (id)init 
{
    self = [super init];
    if( !self ) return nil;

    NSEvent * (^monitorHandler)(NSEvent *);
    monitorHandler = ^NSEvent * (NSEvent * theEvent){

        switch ([theEvent keyCode]) {
            case 123:    // Left arrow
                NSLog(@"Left behind.");
                break;
            case 124:    // Right arrow
                NSLog(@"Right as always!");
                break;
            case 125:    // Down arrow
                NSLog(@"Downward is Heavenward");
                break;
            case 126:    // Up arrow
                NSLog(@"Up, up, and away!");
                break;
            default:
                break;
        }
        // Return the event, a new event, or, to stop 
        // the event from being dispatched, nil
        return theEvent;
    };

    // Creates an object we do not own, but must keep track
    // of so that it can be "removed" when we're done
    eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask 
                                                         handler:monitorHandler];

    return self;
}

- (void)dealloc 
{
    [NSEvent removeMonitor:eventMon];
}

@end

Event Handling Guide提供了一些可能的用途。似乎是CGEventTap的友好Cocoa版本,或者为某些特定目的绕过响应链的方法。可以监视的事件类型选择有限,例如,只有按键,而不是向上。 docs有列表。

同样可用:使用addGlobalMonitorForEventsMatchingMask:handler:检查发往任何其他应用程序的事件(无法修改它们)。与事件点击一样,此方法需要启用“辅助功能”。

答案 1 :(得分:11)

请参阅此代码。我假设该类是NSView的子类。

#pragma mark    -   NSResponder

- (void)keyDown:(NSEvent *)theEvent
{
    NSString*   const   character   =   [theEvent charactersIgnoringModifiers];
    unichar     const   code        =   [character characterAtIndex:0];

    switch (code) 
    {
        case NSUpArrowFunctionKey:
        {
            break;
        }
        case NSDownArrowFunctionKey:
        {
            break;
        }
        case NSLeftArrowFunctionKey:
        {
            [self navigateToPreviousImage];
            break;
        }
        case NSRightArrowFunctionKey:
        {
            [self navigateToNextImage];
            break;
        }
    }
}

视图应该是接收事件的第一响应者。也许这段代码需要支持。

#pragma mark    -   NSResponder
- (BOOL)canBecomeKeyView
{
    return  YES;
}
- (BOOL)acceptsFirstResponder
{
    return  YES;
}

要使用此方法,该类应该是NSResponder的子类。请参阅其他答案处理,无需继承NSResponder。

答案 2 :(得分:3)

在我的情况下,我希望一个呈现的NSViewController子类能够以最小的努力收听箭头键事件以进行导航。这是我发现的最佳解决方案,Josh Caswell的答案略有不同。

定义事件监视器(可选),可以在NSViewController子类.m

中本地
id keyMonitor;

然后开始监视事件,例如在viewDidLoad中。

keyMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event) {

    unichar character = [[event characters] characterAtIndex:0];
    switch (character) {
        case NSUpArrowFunctionKey:
            NSLog(@"Up");
            break;
        case NSDownArrowFunctionKey:
            NSLog(@"Down");
            break;
        case NSLeftArrowFunctionKey:
            NSLog(@"Left");
            break;
        case NSRightArrowFunctionKey:
            NSLog(@"Right");
            break;
        default:
            break;
    }
    return event;
}];

在不需要时删除显示器(假设您已定义)

[NSEvent removeMonitor:keyMonitor];