问题
How to handle arrow key event in Cocoa app?
回答1:
But, but, but...I don't wanna be an NSResponder
subclass.
@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
The Event Handling Guide gives some possible uses. Seems to be a friendly Cocoa version of the CGEventTap, or a way to bypass the responder chain for some specific purpose. There's a limited selection of event types that can be monitored, e.g, only key down, not up. The docs have the list.
Also available: inspect events going to any other application (without being able to modify them) using addGlobalMonitorForEventsMatchingMask:handler:. Like event taps, this method requires Accessibility to be turned on.
回答2:
See this code. I assumed the class is subclass of 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;
}
}
}
A view should be first responder to receive events. Maybe this code will be required to support that.
#pragma mark - NSResponder
- (BOOL)canBecomeKeyView
{
return YES;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
To use this method, the class should be subclass of NSResponder
. See the other answer handling without subclassing NSResponder.
回答3:
In my case I wanted a presented NSViewController subclass to be able to listen to arrow key events for navigation with minimal effort. Here's the best solution I've found, a slight variation of Josh Caswell's answer.
Define an event monitor (optional), can be locally in your NSViewController subclass .m
id keyMonitor;
Then start monitoring events, for example in 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;
}];
To remove the monitor when not required (assuming you defined it)
[NSEvent removeMonitor:keyMonitor];
来源:https://stackoverflow.com/questions/6000133/how-to-handle-arrow-key-event-in-cocoa-app