38

LSUIElementメニューバーのステータス項目を表示するアプリケーションがあります。アプリケーションは、テキストフィールドを含むダイアログウィンドウを表示できます。

ユーザーがテキストフィールドを右クリック/コントロールクリックすると、切り取り、コピー、貼り付けなどを可能にするメニューが表示されます。ただし、標準のCommand-X、Command-C、およびCommand-Vキーボードショートカットは、分野。これは、私のアプリケーションがこれらのショートカットが定義された編集メニューを提供していないためだと思います。

Ship Some Codeブログで提案されているように、アプリケーションのメニューに[編集]メニュー項目を追加しようとしましたが、機能しませんでした。[編集]メニューのメニュー項目は使用できますが、キーボードショートカットは引き続き機能しません。

キーボードの処理をハックするいくつかの方法を想像できますが、これを機能させるための「推奨される」方法はありますか?

(アプリの詳細については、メニューバーのカウントダウンを参照してください。)

関連する質問:モーダルウィンドウでコピー/貼り付けが機能しない

4

16 に答える 16

44

そのCocoaRocketソリューションの改善:

以下は、NSTextFieldをサブクラス化する必要がなく、アプリケーション全体でサブクラスを使用することを忘れないようにします。また、それらを処理する他のレスポンダーのコピー、貼り付け、および友達も有効になります。NSTextView。

これをNSApplicationのサブクラスに入れ、それに応じてInfo.plistのプリンシパルクラスを変更します。

- (void) sendEvent:(NSEvent *)event {
    if ([event type] == NSKeyDown) {
        if (([event modifierFlags] & NSDeviceIndependentModifierFlagsMask) == NSCommandKeyMask) {
            if ([[event charactersIgnoringModifiers] isEqualToString:@"x"]) {
                if ([self sendAction:@selector(cut:) to:nil from:self])
                    return;
            }
            else if ([[event charactersIgnoringModifiers] isEqualToString:@"c"]) {
                if ([self sendAction:@selector(copy:) to:nil from:self])
                    return;
            }
            else if ([[event charactersIgnoringModifiers] isEqualToString:@"v"]) {
                if ([self sendAction:@selector(paste:) to:nil from:self])
                    return;
            }
            else if ([[event charactersIgnoringModifiers] isEqualToString:@"z"]) {
                if ([self sendAction:@selector(undo:) to:nil from:self])
                    return;
            }
            else if ([[event charactersIgnoringModifiers] isEqualToString:@"a"]) {
                if ([self sendAction:@selector(selectAll:) to:nil from:self])
                    return;
            }
        }
        else if (([event modifierFlags] & NSDeviceIndependentModifierFlagsMask) == (NSCommandKeyMask | NSShiftKeyMask)) {
            if ([[event charactersIgnoringModifiers] isEqualToString:@"Z"]) {
                if ([self sendAction:@selector(redo:) to:nil from:self])
                    return;
            }
        }
    }
    [super sendEvent:event];
}

// Blank Selectors to silence Xcode warnings: 'Undeclared selector undo:/redo:'
- (IBAction)undo:(id)sender {}
- (IBAction)redo:(id)sender {}
于 2010-07-05T02:10:09.570 に答える
31

私にとってうまくいったのは、CocoaRocketのキーボードショートカットのコピーと貼り付けで紹介されているビューソリューションを使用することでした。

基本的に、これはNSTextFieldをサブクラス化してオーバーライドすることを意味しますperformKeyEquivalent:

更新: CocoaRocketサイトは明らかになくなっています。インターネットアーカイブのリンクは次のとおりです:http://web.archive.org/web/20100126000339/http://www.cocoarocket.com/articles/copypaste.html

編集:Swiftコードは次のようになります

class Editing: NSTextField {

  private let commandKey = NSEventModifierFlags.CommandKeyMask.rawValue
  private let commandShiftKey = NSEventModifierFlags.CommandKeyMask.rawValue | NSEventModifierFlags.ShiftKeyMask.rawValue
  override func performKeyEquivalent(event: NSEvent) -> Bool {
    if event.type == NSEventType.KeyDown {
      if (event.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == commandKey {
        switch event.charactersIgnoringModifiers! {
        case "x":
          if NSApp.sendAction(Selector("cut:"), to:nil, from:self) { return true }
        case "c":
          if NSApp.sendAction(Selector("copy:"), to:nil, from:self) { return true }
        case "v":
          if NSApp.sendAction(Selector("paste:"), to:nil, from:self) { return true }
        case "z":
          if NSApp.sendAction(Selector("undo:"), to:nil, from:self) { return true }
        case "a":
          if NSApp.sendAction(Selector("selectAll:"), to:nil, from:self) { return true }
        default:
          break
        }
      }
      else if (event.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == commandShiftKey {
        if event.charactersIgnoringModifiers == "Z" {
          if NSApp.sendAction(Selector("redo:"), to:nil, from:self) { return true }
        }
      }
    }
    return super.performKeyEquivalent(event)
  }
}

編集: Swift3コードは次のようになります

class Editing: NSTextView {

private let commandKey = NSEventModifierFlags.command.rawValue
private let commandShiftKey = NSEventModifierFlags.command.rawValue | NSEventModifierFlags.shift.rawValue

override func performKeyEquivalent(with event: NSEvent) -> Bool {
    if event.type == NSEventType.keyDown {
        if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
            switch event.charactersIgnoringModifiers! {
            case "x":
                if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return true }
            case "c":
                if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return true }
            case "v":
                if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return true }
            case "z":
                if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return true }
            case "a":
                if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return true }
            default:
                break
            }
        }
        else if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
            if event.charactersIgnoringModifiers == "Z" {
                if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return true }
            }
        }
    }
    return super.performKeyEquivalent(with: event)
 }
}
于 2009-06-11T05:52:56.787 に答える
19

私はあなたと同じ問題を抱えていました、そして私はもっと簡単な解決策を見つけることができたと思います。MainMenu.xibに元のメインメニューを残す必要があります-表示されませんが、すべてのアクションは適切に処理されます。秘訣は、元のメニューである必要があることです。ライブラリから新しいNSMenuをドラッグするだけでは、アプリはそれをメインメニューとして認識せず、そのようにマークする方法がわかりません(LSUIElementのチェックを外すと、元のアプリでない場合は、上部に表示されないことがわかります)。すでに削除している場合は、新しいサンプルアプリを作成し、NIBからメニューをドラッグすることもできます。これも機能します。

于 2010-09-19T14:23:00.113 に答える
10

CapsLockがオンの場合にも機能するようにAdrianのソリューションを改善しました。

- (void)sendEvent:(NSEvent *)event
{
    if (event.type == NSKeyDown)
    {
        NSString *inputKey = [event.charactersIgnoringModifiers lowercaseString];
        if ((event.modifierFlags & NSDeviceIndependentModifierFlagsMask) == NSCommandKeyMask ||
            (event.modifierFlags & NSDeviceIndependentModifierFlagsMask) == (NSCommandKeyMask | NSAlphaShiftKeyMask))
        {
            if ([inputKey isEqualToString:@"x"])
            {
                if ([self sendAction:@selector(cut:) to:nil from:self])
                    return;
            }
            else if ([inputKey isEqualToString:@"c"])
            {
                if ([self sendAction:@selector(copy:) to:nil from:self])
                    return;
            }
            else if ([inputKey isEqualToString:@"v"])
            {
                if ([self sendAction:@selector(paste:) to:nil from:self])
                    return;
            }
            else if ([inputKey isEqualToString:@"z"])
            {
                if ([self sendAction:NSSelectorFromString(@"undo:") to:nil from:self])
                    return;
            }
            else if ([inputKey isEqualToString:@"a"])
            {
                if ([self sendAction:@selector(selectAll:) to:nil from:self])
                    return;
            }
        }
        else if ((event.modifierFlags & NSDeviceIndependentModifierFlagsMask) == (NSCommandKeyMask | NSShiftKeyMask) ||
                 (event.modifierFlags & NSDeviceIndependentModifierFlagsMask) == (NSCommandKeyMask | NSShiftKeyMask | NSAlphaShiftKeyMask))
        {
            if ([inputKey isEqualToString:@"z"])
            {
                if ([self sendAction:NSSelectorFromString(@"redo:") to:nil from:self])
                    return;
            }
        }
    }
    [super sendEvent:event];
}
于 2014-10-30T22:42:06.300 に答える
8

迅速な3のトーマスキリアンソリューション。

private let commandKey = NSEventModifierFlags.command.rawValue
private let commandShiftKey = NSEventModifierFlags.command.rawValue | NSEventModifierFlags.shift.rawValue
override func performKeyEquivalent(with event: NSEvent) -> Bool {
  if event.type == NSEventType.keyDown {
    if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
    switch event.charactersIgnoringModifiers! {
    case "x":
      if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return true }
    case "c":
      if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return true }
    case "v":
      if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return true }
    case "z":
      if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return true }
    case "a":
      if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return true }
    default:
      break
    }
  }
  else if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
    if event.charactersIgnoringModifiers == "Z" {
      if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return true }
    }
  }
}
return super.performKeyEquivalent(with: event)
}
于 2016-12-17T15:55:13.520 に答える
7

Xcode10 / Swift 4.2ソリューション:

import Cocoa

extension NSTextView {
override open func performKeyEquivalent(with event: NSEvent) -> Bool {
    let commandKey = NSEvent.ModifierFlags.command.rawValue
    let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue
    if event.type == NSEvent.EventType.keyDown {
        if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
            switch event.charactersIgnoringModifiers! {
            case "x":
                if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return true }
            case "c":
                if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return true }
            case "v":
                if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return true }
            case "z":
                if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return true }
            case "a":
                if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return true }
            default:
                break
            }
        } else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
            if event.charactersIgnoringModifiers == "Z" {
                if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return true }
            }
        }
    }
    return super.performKeyEquivalent(with: event)
}
}
于 2019-02-02T10:32:08.743 に答える
5

ThomasKilianソリューション用のSwift4.2

class MTextField: NSSecureTextField {

    private let commandKey = NSEvent.ModifierFlags.command.rawValue
    private let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue

    override func performKeyEquivalent(with event: NSEvent) -> Bool {
        if event.type == NSEvent.EventType.keyDown {
            if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
                switch event.charactersIgnoringModifiers! {
                case "x":
                    if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return true }
                case "c":
                    if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return true }
                case "v":
                    if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return true }
                case "z":
                    if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return true }
                case "a":
                    if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return true }
                default:
                    break
                }
            }
            else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
                if event.charactersIgnoringModifiers == "Z" {
                    if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return true }
                }
            }
        }
        return super.performKeyEquivalent(with: event)
    }

}
于 2018-09-26T15:38:05.243 に答える
4

@ Adrian、Travis B、Thomas Kilianによる優れた回答に基づいた、迅速なステップバイステップガイドを以下に示します。

目標は、NSTextFieldではなくNSApplicationをサブクラス化することです。このクラスを作成したら、Adrianが述べているように、Info.plistの「principalClass」設定にリンクしてください。Objective-Cの人々とは対照的に、私たちのスウィフトラーは、principalClass構​​成に追加のプレフィックスを追加する必要があります。プロジェクトの名前が「Foo」なので、「PrincipalClass」を「Foo.MyApplication」に設定します。そうしないと、「クラスMyApplicationが見つかりません」ランタイムエラーが発生します。

MyApplicationの内容は次のとおりです(これまでに提供されたすべての回答からコピーおよび適合)

import Cocoa

class MyApplication: NSApplication {
    override func sendEvent(event: NSEvent) {
        if event.type == NSEventType.KeyDown {
            if (event.modifierFlags & NSEventModifierFlags.DeviceIndependentModifierFlagsMask == NSEventModifierFlags.CommandKeyMask) {
                switch event.charactersIgnoringModifiers!.lowercaseString {
                case "x":
                    if NSApp.sendAction(Selector("cut:"), to:nil, from:self) { return }
                case "c":
                    if NSApp.sendAction(Selector("copy:"), to:nil, from:self) { return }
                case "v":
                    if NSApp.sendAction(Selector("paste:"), to:nil, from:self) { return }
                case "z":
                    if NSApp.sendAction(Selector("undo:"), to:nil, from:self) { return }
                case "a":
                    if NSApp.sendAction(Selector("selectAll:"), to:nil, from:self) { return }
                default:
                    break
                }
            }
            else if (event.modifierFlags & NSEventModifierFlags.DeviceIndependentModifierFlagsMask == (NSEventModifierFlags.CommandKeyMask | NSEventModifierFlags.ShiftKeyMask)) {
                if event.charactersIgnoringModifiers == "Z" {
                    if NSApp.sendAction(Selector("redo:"), to:nil, from:self) { return }
                }
            }
        }
        return super.sendEvent(event)
    }

}
于 2015-03-26T15:49:14.900 に答える
3

XCode 8 /Swift3で何がうまくいったかを説明します。

MyApplication.swiftプロジェクトフォルダ内に作成しましたMyApp

import Foundation
import Cocoa

class MyApplication: NSApplication {
    override func sendEvent(_ event: NSEvent) {
        if event.type == NSEventType.keyDown {

            if (event.modifierFlags.contains(NSEventModifierFlags.command)) {
                switch event.charactersIgnoringModifiers!.lowercased() {
                case "x":
                    if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return }
                case "c":
                    if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return }
                case "v":
                    if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return }
                case "a":
                    if NSApp.sendAction(#selector(NSText.selectAll(_:)), to:nil, from:self) { return }
                default:
                    break
                }
            }
        }
        return super.sendEvent(event)
    }

}

次に、をに変更Info.plist Principal classMyApp.MyApplicationます。ビルドして実行し、テキストフィールドとテキストビューが、、、およびをサポートしていることをCmd + X検証しCmd + Cます。Cmd + VCmd + A

于 2016-09-19T10:11:00.223 に答える
3

新しいクラス、拡張機能、または実際にはコードを追加する必要はまったくありません。

  1. メニューの1つに新しいMenuItemを追加し、「コピー」、「切り取り」、「貼り付け」という名前を付けるだけです。
  2. 各アイテムに正しいショートカットキーを追加します。
  3. Control +ドラッグして、ファーストレスポンダーの下にリストされている対応するメソッドに接続します。

ここでの利点は、アイテムがユーザーから隠されていないことです。これにより、新しいクラスを作成して既存のすべてのTextFieldをそのクラスに再割り当てするよりも時間がかかりません。

于 2017-07-23T19:11:45.337 に答える
0

ちょうど約1時間前、私は同じ問題に遭遇しました。何もコーディングする必要はありません。私はInterfaceBuilderでこれを行うことができます:

  • 切り取り/コピー/貼り付けメニュー項目を含むメニュー(「編集」など)を作成します
  • CMDキーに相当するKeyEquivalentを[編集]メニューに追加します(これが本当に必要な場合は、別のプロジェクトから構造をコピーしただけです)。
  • これらのメニュー項目にKeyEquivalentsを追加します(CMD + Xなど)
  • FirstResponder's cut:copy:およびpaste:関数を対応するメニュー項目にリンクします

それは私のために働いた。残念ながら、この(デフォルトの)動作は、[編集]メニューを非表示にした場合(試してみただけ)は機能しないようです。

于 2015-03-25T10:41:47.623 に答える
0

Xamarin.Macで使用するC#としてのTravisの回答は次のとおりです。

    public override bool PerformKeyEquivalent (AppKit.NSEvent e)
    {
        if (e.Type == NSEventType.KeyDown) {
            var inputKey = e.CharactersIgnoringModifiers.ToLower ();
            if (   (e.ModifierFlags & NSEventModifierMask.DeviceIndependentModifierFlagsMask) == NSEventModifierMask.CommandKeyMask
                || (e.ModifierFlags & NSEventModifierMask.DeviceIndependentModifierFlagsMask) == (NSEventModifierMask.CommandKeyMask | NSEventModifierMask.AlphaShiftKeyMask)) {
                switch (inputKey) {
                case "x":
                    NSApplication.SharedApplication.SendAction (new Selector ("cut:"), null, this);
                    return true;
                case "c":
                    NSApplication.SharedApplication.SendAction (new Selector ("copy:"), null, this);
                    return true;
                case "v":
                    NSApplication.SharedApplication.SendAction (new Selector ("paste:"), null, this);
                    return true;
                case "z":
                    NSApplication.SharedApplication.SendAction (new Selector ("undo:"), null, this);
                    return true;
                case "a":
                    NSApplication.SharedApplication.SendAction (new Selector ("selectAll:"), null, this);
                    return true;
                }
            } else if (   (e.ModifierFlags & NSEventModifierMask.DeviceIndependentModifierFlagsMask) == (NSEventModifierMask.CommandKeyMask | NSEventModifierMask.ShiftKeyMask)
                       || (e.ModifierFlags & NSEventModifierMask.DeviceIndependentModifierFlagsMask) == (NSEventModifierMask.CommandKeyMask | NSEventModifierMask.ShiftKeyMask | NSEventModifierMask.AlphaShiftKeyMask)) {
                switch (inputKey) {
                case "z":
                    NSApplication.SharedApplication.SendAction (new Selector ("redo:"), null, this);
                    return true;
                }
            }
        }
        return base.PerformKeyEquivalent(e);
    }
于 2016-02-25T02:11:50.403 に答える
0

の回答に基づいてThomas Kilian、NSTextFieldの拡張機能を実際に作成できます

let commandKey = NSEvent.ModifierFlags.command.rawValue
let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue

extension NSTextField {
    func performEditingKeyEquivalent(with event: NSEvent) -> Bool {
        guard event.type == NSEvent.EventType.keyDown else { return false }

        if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
            if let character = event.charactersIgnoringModifiers {
                switch character {
                case "x":
                    if NSApp.sendAction(#selector(NSText.cut(_:)), to: nil, from: self) { return true }
                case "c":
                    if NSApp.sendAction(#selector(NSText.copy(_:)), to: nil, from: self) { return true }
                case "v":
                    if NSApp.sendAction(#selector(NSText.paste(_:)), to: nil, from: self) { return true }
                case "z":
                    if NSApp.sendAction(Selector(("undo:")), to: nil, from: self) { return true }
                case "a":
                    if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to: nil, from: self) { return true }
                default:
                    break
                }
            }
        } else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
            if event.charactersIgnoringModifiers == "Z" {
                if NSApp.sendAction(Selector(("redo:")), to: nil, from: self) { return true }
            }
        }

        return false
    }
}

NSTextField次の例では、実際に任意のNSTextField継承クラス(たとえばNSSearchField、 )に置き換えNSSecureTextFieldて、新しい機能を使用できます。

class SearchField: NSTextField {
    override func performKeyEquivalent(with event: NSEvent) -> Bool {
        if performEditingKeyEquivalent(with: event) {
            return true
        }

        return super.performEditingKeyEquivalent(with: event)
    }
}
于 2018-03-20T06:18:43.217 に答える
0

この解決策をありがとう!それは私を大いに助けてくれたので、他の誰かに役立つことを願って、いくつかのコードを提供することにしました。上記の提案された解決策は、に変換した後、完全に機能しましたSwift 4.2。次に、コードを少しリファクタリングしました。これは少しきれいだと思います。これはSwift 4.2互換性があります:

// NSEventExtensions.swift

import AppKit

extension NSEvent {
    func containsKeyModifierFlags(_ flags: NSEvent.ModifierFlags) -> Bool {
        switch modifierFlags.intersection(.deviceIndependentFlagsMask) {
        case [flags]: return true
        default: return false
        }
    }
}

// SearchFiled.swift

import AppKit
import Carbon

final class SearchField: NSSearchField {
    override func performKeyEquivalent(with event: NSEvent) -> Bool {
        switch event.type {
        case .keyDown: return performKeyDownEquivalent(with: event)
        default: return super.performKeyEquivalent(with: event)
        }
    }

    // MARK: - private

    private func performKeyDownEquivalent(with event: NSEvent) -> Bool {
        if event.containsKeyModifierFlags(.command) {
            switch Int(event.keyCode) {
            case kVK_ANSI_X: return NSApp.sendAction(#selector(NSText.cut(_:)), to: nil, from: self)
            case kVK_ANSI_C: return NSApp.sendAction(#selector(NSText.copy(_:)), to: nil, from: self)
            case kVK_ANSI_V: return NSApp.sendAction(#selector(NSText.paste(_:)), to: nil, from: self)
            case kVK_ANSI_Z: return NSApp.sendAction(Selector(("undo:")), to: nil, from: self)
            case kVK_ANSI_A: return NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to: nil, from: self)
            default: break
            }
        } else if event.containsKeyModifierFlags([.command, .shift]) {
            switch Int(event.keyCode) {
            case kVK_ANSI_Z: return NSApp.sendAction(Selector(("redo:")), to: nil, from: self)
            default: break
            }
        }
        return false
    }
}
于 2019-01-31T20:04:18.357 に答える
0

NSApplicationサブクラス向けのSwift5ソリューション

open override func sendEvent(_ event: NSEvent) {
    if event.type == .keyDown {
        if event.modifierFlags.contains(.command)  && NSEvent.ModifierFlags.deviceIndependentFlagsMask.contains(.command) {
            if event.modifierFlags.contains(.shift) && NSEvent.ModifierFlags.deviceIndependentFlagsMask.contains(.shift) {
                if event.charactersIgnoringModifiers == "Z" {
                    if NSApp.sendAction(Selector("redo:"), to:nil, from:self) { return }
                }
            }
            guard let key = event.charactersIgnoringModifiers else { return super.sendEvent(event) }
            switch key {
            case "x":
                if NSApp.sendAction(Selector("cut:"), to:nil, from:self) { return }
            case "c":
                if NSApp.sendAction(Selector("copy:"), to:nil, from:self) { return }
            case "v":
                if NSApp.sendAction(Selector("paste:"), to:nil, from:self) { return }
            case "z":
                if NSApp.sendAction(Selector("undo:"), to:nil, from:self) { return }
            case "a":
                if NSApp.sendAction(Selector("selectAll:"), to:nil, from:self) { return }
            default:
                break
          }
        }
    }
    super.sendEvent(event)
}
于 2020-08-23T21:20:33.523 に答える
-1

エイドリアンの解決策は良いですが、これらすべての文字列比較ではなく、switchステートメントを使用する方が良いと思います。例:

    uint const modifierCode = (theEvent.modifierFlags & NSDeviceIndependentModifierFlagsMask);
    BOOL usingModifiers = ( modifierCode != 0 );
    //BOOL const usingShiftKey = ((theEvent.modifierFlags & NSShiftKeyMask) != 0);
    //BOOL const usingCommandKey = ((theEvent.modifierFlags & NSCommandKeyMask) != 0);
    NSString * ch = [theEvent charactersIgnoringModifiers];
    if ( ( usingModifiers ) && ( ch.length == 1 ) ) switch ( [ch characterAtIndex:0] )
    {
        case 'x':
            if ( modifierCode == NSCommandKeyMask ) [m cut]; // <-- m = model
            break;
        case 'c':
            if ( modifierCode == NSCommandKeyMask ) [m copy];
            break;
        case 'v':
            if ( modifierCode == NSCommandKeyMask ) [m paste];
            break;
        case 'z':
            if ( modifierCode == NSCommandKeyMask ) [m undo];
            break;
        case 'Z':
            if ( modifierCode == ( NSCommandKeyMask | NSShiftKeyMask ) ) [m redo];
            break;
        default: // etc.
            break;
    }
    else switch ( theEvent.keyCode ) // <-- for independent keycodes!
    {
        case kVK_Home:
            [m moveToBeginningOfDocument:nil];
            break;
        case kVK_End: // etc!
于 2015-01-26T14:38:22.113 に答える