9

非常にまれにしか使用されないメニュー項目をアプリケーションのメインメニューに追加したいと思います。デフォルトで非表示にし、ユーザーがOptionキーを押したときにのみ表示したい。どうすればこれを行うことができますか?

処理する必要があるようですflagsChanged:が、これはNSResponderのメソッドであり、 ?NSMenuから継承しません。NSResponderメインウィンドウコントローラー内で試してみましたが、メニューをクリックする前にOptionキーを押すと機能します。次の使用例は機能しません。メニュー項目をクリックし(項目がありません)、オプションキーを押します—項目が表示され、オプションキーを離します—項目が消えます。

NSEventも試しましaddLocalMonitorForEventsMatchingMask:handler:addGlobalMonitorForEventsMatchingMask:handler:NSFlagsChangedMask、メインメニューが開いているときにオプションキーを押すと、ローカルハンドラーもグローバルハンドラーも起動されません。

これどうやってするの?

4

5 に答える 5

11

メニューを作成するときは、オプションの項目を含めて、非表示としてマークします。次に、クラス インスタンスをメニューのデリゲートとして設定し、メニューが開いている間に実行ループ オブザーバーを追加して、オプション項目の非表示状態を制御します。

@implementation AppController {
    CFRunLoopObserverRef _menuObserver;
}

- (void)updateMenu {
    BOOL hideOptionalMenuItems = ([NSEvent modifierFlags] & NSAlternateKeyMask) != NSAlternateKeyMask;
    [self.optionalMenuItem setHidden:hideOptionalMenuItems];
}

- (void)menuWillOpen:(NSMenu *)menu {
    [self updateMenu];

    if (_menuObserver == NULL) {
        _menuObserver = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
            [self updateMenu];
        });

        CFRunLoopAddObserver(CFRunLoopGetCurrent(), _menuObserver, kCFRunLoopCommonModes);
    }
}

- (void)menuDidClose:(NSMenu *)menu {
    if (_menuObserver != NULL) {
        CFRunLoopObserverInvalidate(_menuObserver);
        CFRelease(_menuObserver);
        _menuObserver = NULL;
    }
}
于 2013-03-16T20:00:43.727 に答える
10

これを実現する最善の方法は、2 つのメニュー項目を使用することです。最初のメニュー項目は高さ 0 のカスタム ビューを使用して無効にし、そのすぐ下に「代替」項目を配置します。(この項目を に設定する必要がありますkeyEquivalentModifierMask)NSAlternateKeyMaskこの配置では、オプション キーを押すと、NSMenu は高さゼロのメニュー項目を、メニュー項目を魔法のように表示する効果を持つ代替項目に自動的に置き換えます。

タイマー、更新、またはフラグ変更通知は必要ありません。

この機能については、次のドキュメントで説明されています:代替の管理

于 2013-12-19T22:22:13.767 に答える