Как я могу обработать ключ ESC в приложении Cocoa?

18

Я сделал приложение переключиться в полноэкранный режим. Я хочу использовать клавишу ESC для выхода из полноэкранного режима, но привязка пункта меню к клавише ESC в IB удаляется во время выполнения. Как я могу сохранить привязку ESC к элементу меню?

    
задан Eonil 13.05.2011 в 17:38
источник

4 ответа

35

Предпочтительный способ обработки escape-ключа в Cocoa - это как @ Джош Касуэлл сказал .

#pragma mark    -   NSResponder
- (void)cancelOperation:(id)sender
{
    [self exitFullScreen];
}
    
ответ дан Eonil 14.05.2011 в 08:53
  • Это должен быть принятый ответ. –  Tom Hamming 04.04.2017 в 16:51
  • Во-вторых, это тоже. –  Marek H 16.10.2017 в 11:43
10

Один из способов захвата событий клавиатуры - это подклассы:

  1. Подкласс для полноэкранного класса (например, NSView).
  2. Добавьте метод - (void) keyDown:(NSEvent *)theEvent к реализации подкласса.
  3. Откройте интерфейс InterfaceBuilder и выберите полноразмерный класс, который вы ранее создали.
  4. Измените свой класс на новый подкласс.

Подкласс выглядит примерно так:

MySubclass.h

@interface MySubclass : NSView {
}
@end

MySubclass.m

@implementation MySubclass
- (void)keyDown:(NSEvent *)theEvent
{       
    switch([theEvent keyCode]) {
        case 53: // esc
            NSLog(@"ESC");
                    // Call the full-screen mode method
            break;
        default:
            [super keyDown:theEvent];
    }
}
@end

Это не привязывает ключ ESC к элементу меню, но дает вам эквивалентную функциональность (и немного более гибкую, поскольку вы можете перехватывать все события клавиатуры).

    
ответ дан phaxian 13.05.2011 в 19:38
  • Другим вариантом является реализация cancelOperation :, который также отвечает на ⌘-. –  Josh Caswell 13.05.2011 в 20:35
  • i подклассифицировал класс nswindow, и я все еще не могу захватить ключ esc, когда редактируется nstextfield ... –  Radu Simionescu 26.11.2015 в 05:04
  • Константа 53 доступна как kVK_Escape, если (в Objective-C) вы @import Carbon; или #import <Carbon / Carbon.h>. В Swift импортируйте Carbon.HIToolbox. –  rob mayoff 24.07.2016 в 23:18
0

Мне нужно было уклониться от WKWebView, когда ESC нажал (?), поэтому я подклассифицирую его и добавил:

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)
    }
}
    
ответ дан slashlos 16.09.2017 в 01:58
0

Многие люди пытаются реализовать функциональность ключа esc. В цепочке ответчиков отменяется действие, чтобы обрабатывать события эвакуации.

//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];
}
    
ответ дан Marek H 16.10.2017 в 11:53