8

LSUIElement が 1 に設定されたアプリケーションがあります。エディタが組み込まれているため、エディタが開いているときにアプリケーションが Cmd+Tab サイクルで表示されるようにします。

    -(void)stepIntoForeground
    {
        if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) return;
        if (counter == 0) {
            ProcessSerialNumber psn = {0, kCurrentProcess};
            OSStatus osstatus = TransformProcessType(&psn, kProcessTransformToForegroundApplication);
            if (osstatus == 0) {
                ++counter;
            } else {
                //...
            }
        }
    }
    -(void)stepIntoBackground
    {
        if (NSAppKitVersionNumber < NSAppKitVersionNumber10_7) return;
        if (counter == 0) return;

        if (counter == 1) {
            ProcessSerialNumber psn = {0, kCurrentProcess};
            OSStatus osstatus = TransformProcessType(&psn, kProcessTransformToUIElementApplication);
            if (osstatus == 0) {
                --counter;
            } else {
                //..
            }
        }
    }

問題は次のとおりです。

  • Dock アイコンもあります (大したことではありません)。
  • メニューもありますが、これも大したことではありませんが、常に表示されるわけではありません。

メニューをまったく無効にする方法、または常に前景に表示する方法はありますか? 前もって感謝します。

4

3 に答える 3

21

これは私たちのやり方です。(動作 10.7+)

  1. アプリの plist で LSBackgroundOnly も LSUIElement も使用しないでください
  2. メニューと NSStatusBar メニューを追加して初期化します
  3. アプリが初期化された後、まだ表示されていないウィンドウがあれば、最初のウィンドウを表示したい場所に移動します。applicationDidFinishLaunching を使用します。

    • アプリの初期化後にまだウィンドウを表示したくない場合は、使用します

      [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];

      10.9では、そうでなければはるかに正しいものをついに使用できます

      [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];

    • アプリの初期化が完了した後にウィンドウを開く必要がある場合は、単にメイン ウィンドウを表示するよりも

  4. ウィンドウのリストを維持する

  5. 最後のウィンドウが閉じている場合は、呼び出します

    [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];

    10.9では、そうでなければはるかに正しいものをついに使用できます

    [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];

  6. 次回最初のウィンドウが表示されたら、呼び出します

    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
    [NSApp activateIgnoringOtherApps:YES];
    [[self window] makeKeyAndOrderFront:nil];

少なくとも 1 つのアプリ ウィンドウが表示されている場合は、メニュー、状態が通知されたドック アイコン、アプリの cmd+tab 要素が表示されます。最後のアプリ ウィンドウが閉じている場合は、NSStatusBar 要素のみが残ります。

既知の問題点:

  • 最初のステップは重要です。これがないと、システム モーダル ダイアログによって起動が中断された場合 (アプリがネットからダウンロードされ、検疫された場合、セキュリティ設定によっては、最初の起動時に確認ダイアログが表示される場合があります)、メニューバーがユーザーによって所有されない可能性があるためです。最初のアプリ ウィンドウが表示された後のアプリ。

    回避策: 通常のアプリとして起動すると (手順 1.)、この問題は解決しますが、別の小さな問題が発生する可能性があります。ウィンドウを表示せずに起動したい場合でも、起動時にドックにアプリのアイコンが一瞬表示されることがあります。(しかし、これに対処することはできます。メニューバーを所有していないことは私たちにとってより大きな問題だったので、代わりにこれを選択しました)

  • NSApplicationActivationPolicyRegular と NSApplicationActivationPolicyAccessory (または 10.9 以下の OS では NSApplicationActivationPolicyProhibited) の間で変更すると、ステータス バー メニュー要素のツールチップが強制終了されます。ツールチップは最初に表示されますが、NSApplicationActivationPolicyAccessory の 2 回目の呼び出し後は表示されません -> NSApplicationActivationPolicyProhibited

    回避策: これに対する有効な回避策が見つからず、Apple にバグとして報告されました。

  • NSApplicationActivationPolicyRegular から NSApplicationActivationPolicyAccessory に変更すると、一部の OS バージョンで他の問題が発生することがあります。たとえば、表示されているアプリ ウィンドウにマウス イベントが表示されないことがあります。

    回避策: 最初に NSApplicationActivationPolicyProhibited に切り替えます (これにより、NSApplicationWillResignActiveNotification、NSWindowDidResignMainNotification などの不要なアプリ メッセージが表示されることに注意してください!)

  • NSApplicationActivationPolicyAccessory から NSApplicationActivationPolicyRegular への変更は、一部の OS バージョンのように偽物です

    • アプリのメイン メニューは、最初のアプリ フロント ステータスが変更されるまで凍結されます
    • このポリシーの後にアクティブ化されたアプリは、アプリケーションの順序で常に先頭に配置されるとは限りません

    回避策: 最初に NSApplicationActivationPolicyProhibited に切り替えます。目的の NSApplicationActivationPolicyRegular への最後の切り替えを遅らせる必要があることに注意してください。fe dispatch_async などを使用してください。

于 2012-10-19T19:23:34.820 に答える
1

plistファイルでアプリの「アプリケーションはエージェント(UIElement)です」をYESに設定できます。

編集:

これを行うにはいくつかのハックがあると思います。しかし、それは本来あるべき姿ではありません。Cmd+tab はアプリケーションをフォアグラウンドにするためのものですが、メニュー バーがない場合、ユーザーにはフォアグラウンドのようには見えません。

アプリにアクセスするためのメニューバーを作成したいと思います。

于 2012-10-18T07:12:31.930 に答える