【发布时间】:2019-01-14 16:15:17
【问题描述】:
我让一个应用程序切换到全屏模式。我想使用 ESC 键来转义全屏模式,但是在运行时将菜单项绑定到 IB 中的 ESC 键被删除。如何保持 ESC 键绑定到菜单项?
【问题讨论】:
我让一个应用程序切换到全屏模式。我想使用 ESC 键来转义全屏模式,但是在运行时将菜单项绑定到 IB 中的 ESC 键被删除。如何保持 ESC 键绑定到菜单项?
【问题讨论】:
在 Cocoa 中处理转义键的首选方法是 @Josh Caswell said。
#pragma mark - NSResponder
- (void)cancelOperation:(id)sender
{
[self exitFullScreen];
}
【讨论】:
捕获键盘事件的一种方法涉及子类化:
- (void) keyDown:(NSEvent *)theEvent添加到子类实现中。子类看起来像:
MySubclass.h
@interface MySubclass : NSView {
}
@end
MySubclass.m
#import <Carbon/Carbon.h>
@implementation MySubclass
- (void)keyDown:(NSEvent *)theEvent
{
switch([theEvent keyCode]) {
case kVK_Escape:
NSLog(@"ESC");
// Call the full-screen mode method
break;
default:
[super keyDown:theEvent];
}
}
@end
这不会将ESC 键绑定到菜单项,但它确实为您提供了等效的功能(并且更灵活,因为您可以拦截所有键盘事件)。
【讨论】:
cancelOperation:,它也响应⌘-。
@import Carbon; 或 #import <Carbon/Carbon.h>,常量 53 可以作为 kVK_Escape 使用。在 Swift 中,import Carbon.HIToolbox.
许多人尝试实现 esc 键功能。响应者链中有 cancelOperation 来处理逃逸事件。
//WRONG
- (void)keyDown:(NSEvent *)event
{
//unichar character = 0;
//if ([event type] == NSEventTypeKeyDown) {
// if ([[event charactersIgnoringModifiers] length] == 1) {
// character = [[event characters] characterAtIndex:0];
// }
//}
switch (character) {
//THIS IS WRONG correct is to implement interpretKeyEvents+moveRight
//case NSRightArrowFunctionKey:
// [self moveSelectedIndexRight];
// break;
//THIS IS WRONG correct is to implement interpretKeyEvents+ moveLeft
//case NSLeftArrowFunctionKey:
// [self moveSelectedIndexLeft];
// break;
//THIS IS WRONG correct is to implement interpretKeyEvents+ moveLeft
//case NSCarriageReturnCharacter:
// [self dismissWithCurrentlySelectedToken];
// break;
default:
[self interpretKeyEvents:@[event]];
[super keyDown:event]
break;
}
}
//CORRECT
- (void)keyDown:(NSEvent *)event
{
[self interpretKeyEvents:@[event]];
[super keyDown:event];
}
`/* Catch the commands interpreted by interpretKeyEvents:. Normally, if we don't implement (or any other view in the hierarchy implements) the selector, the system beeps. Menu navigation generally doesn't beep, so stop doCommandBySelector: from calling up t`he hierarchy just to stop the beep.
*/
- (void)doCommandBySelector:(SEL)selector {
if ( selector == @selector(moveRight:)
|| selector == @selector(moveLeft:)
|| selector == @selector(cancelOperation:)
|| selector == @selector(insertNewline:) )
{
[super doCommandBySelector:selector];
}
// do nothing, let the menu handle it (see call to super in -keyDown:)
// But don't call super to prevent the system beep
}
- (void)cancelOperation:(id)sender
{
//do your escape stuff
}
- (void)insertNewline:(id)sender
{
//do your enter stuff
}
- (void)moveRight:(nullable id)sender
{
[self moveSelectedIndexRight];
}
- (void)moveLeft:(nullable id)sender
{
[self moveSelectedIndexLeft];
}
【讨论】:
我需要在按下 ESC 时躲避 WKWebView 崩溃(?),所以我对它进行了子类化,并补充说:
import Carbon.HIToolbox
override func keyDown(with event: NSEvent) {
if event.keyCode == UInt16(kVK_Escape) {
// We crash otherwise, so just close window
self.window?.performClose(event)
}
else
{
// still here?
super.keyDown(with: event)
}
}
【讨论】: