如何处理 Cocoa 应用程序中的 ESC 键?

发布于 2024-11-07 02:14:10 字数 90 浏览 0 评论 0原文

我制作了一个切换到全屏模式的应用程序。我想使用 ESC 键退出全屏模式,但是在运行时删除了 IB 中将菜单项绑定到 ESC 键的操作。如何将 ESC 键绑定到菜单项?

I made an app switching to full screen mode. I want to use ESC key to escaping fullscreen mode, but binding menu item to ESC key in IB is removed at runtime. How can I keep ESC key binding to a menu item?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

那支青花 2024-11-14 02:14:10

在 Cocoa 中处理转义键的首选方法是这样的 @Josh Caswell 说道

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

Preferred way to handle escape key in Cocoa is this as like @Josh Caswell said.

#pragma mark - NSResponder
- (void)cancelOperation:(id)sender
{
    [self exitFullScreen];
}
独留℉清风醉 2024-11-14 02:14:10

捕获键盘事件的一种方法涉及子类化:

  1. 对全屏类(例如)NSView 进行子类化。
  2. 将方法 - (void) keyDown:(NSEvent *)theEvent 添加到子类实现中。
  3. 打开 InterfaceBuilder 并选择您之前创建的全屏类。
  4. 将其类更改为您的新子类。

子类看起来像:

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 键绑定到菜单项,但它确实为您提供了等效的功能(以及更多的灵活性,因为您可以拦截所有键盘事件)。

One way to capture keyboard events involves subclassing:

  1. Subclass your full-screen class (e.g.) NSView.
  2. Add the method - (void) keyDown:(NSEvent *)theEvent to the subclass implementation.
  3. Open up InterfaceBuilder and select the full-screen class that you previously created.
  4. Change its class to your new subclass.

The subclass looks something like:

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

This doesn't bind the ESC key to the menu item, but it does give you equivalent functionality (and a bit more flexability since you can intercept all keyboard events).

甲如呢乙后呢 2024-11-14 02:14:10

许多人尝试实现 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];
}

Many people try to implement esc key functionality. There is cancelOperation in the responder chain to handle escape events.

//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];
}
一曲琵琶半遮面シ 2024-11-14 02:14:10

我需要在按下 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)
    }
}

I needed to dodge WKWebView crashes when ESC is pressed(?) so I sub-class it, and added:

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)
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文