2011-05-13 13 views
17

Hice una aplicación cambiando al modo de pantalla completa. Quiero usar la tecla ESC para escapar del modo de pantalla completa, pero el elemento del menú de enlace a la tecla ESC en IB se elimina en el tiempo de ejecución. ¿Cómo puedo mantener la tecla ESC vinculante a un elemento del menú?¿Cómo puedo manejar la tecla ESC en la aplicación Cocoa?

Respuesta

10

Una forma de capturar los eventos del teclado consiste en subclases:

  1. Subclase su clase de pantalla completa (por ejemplo) NSView.
  2. Agregue el método - (void) keyDown:(NSEvent *)theEvent a la implementación de la subclase.
  3. Abre InterfaceBuilder y selecciona la clase de pantalla completa que creaste anteriormente.
  4. Cambie su clase a su nueva subclase.

La subclase se ve algo como:

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 

Esto no se une la tecla ESC al elemento de menú, pero le da una funcionalidad equivalente (y un poco más flexibilidad ya que puede interceptar todos los eventos del teclado).

+8

Otra opción es implementar 'cancelOperation:', que también responde a ⌘-. –

+0

he subclasificado la clase nswindow y todavía no puedo capturar la clave esc, cuando se está editando un nstextfield ... –

+0

La constante '53' está disponible como' kVK_Escape' si (en Objective-C) 'importan carbono; 'o' #import '. En Swift, 'importa Carbon.HIToolbox'. –

34

La forma preferida de manejar la clave de escape en Cocoa es como @Josh Caswell said.

#pragma mark - NSResponder 
- (void)cancelOperation:(id)sender 
{ 
    [self exitFullScreen]; 
} 
+0

Esta debería ser la respuesta aceptada. –

+0

Lo segundo también. –

0

que necesitaba para esquivar WKWebView se bloquea cuando se pulsa ESC así que subclase, y añadió (?):

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) 
    } 
} 
0

Muchas personas tratan de implementar la funcionalidad clave esc. Hay cancelOperation en la cadena de respuesta para manejar eventos de escape.

//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]; 
} 
Cuestiones relacionadas