16

現在、swt では、プログラムを任意に前面に表示させたいことがあります (目覚まし時計のように)。

通常、次のように動作します (jruby):

@shell.setMinimized(false)
@shell.forceActive

シェルが最小化されている場合、これによりシェルが前面に表示されます。

いつでも新しいシェルを作成すると、(新しいシェル) が前面に表示されます。

これまでのところは問題ありませんが、シェルが最小化されていない場合、上記のコードはタスクバーのアプリのアイコンを点滅 (点滅) させるだけです。実際、初めて実行すると、前面に表示されます。その後、タスクバーで点滅するだけです。それが窓です。Linux では、タスクバーでのみ点滅しているように見えます (ubuntu のデフォルト)。

swt でアプリを前面に出すためのクロス プラットフォームの方法を知っている人はいますか?

forceActive setActive setMinimized(false) setFocus forceFocus および setVisible の呪文は、このことを達成できないようです。

E Text Editor が行うように、(少なくとも Windows では) それが可能であると確信しています。まあ、それはswtではありませんが、少なくともいくつかの他のアプリがそれを行うことが知られています.

おそらくこれはswt bug 192036だと思いますか?

どうもありがとう。

関連している:

4

6 に答える 6

6

http://github.com/rdp/redcar/commit/d7dfeb8e77f13e5596b11df3027da236f23c83f0

とにかく、私がWindowsでそれをどのように行ったかを示しています(ffiを使用)。

役立つトリックのいくつかは「かもしれない」

BringToFront.SetForegroundWindow(wanted)呼び出しの後に「sleep0.1」を追加します(これは実際には必要ないことを願っています)。

ウィンドウを前面に移動した後、shell.set_activeを追加します。何らかの理由で、forceActiveはsetActiveを呼び出しません。

setActiveがuser32.dllBringWindowToTop呼び出しを実行することに注意してください。これは、スレッド入力をデタッチする前に実行する必要があります。

また、正しい順序で呼び出すことができれば、スレッド入力ハックをまったく使用する必要がない可能性があることにも注意してください(?)

http://betterlogic.com/roger/?p=2950

(実際にこれを正しく行う方法に関するいくつかの良いヒントが含まれています)

Linuxでは、forceActive機能しますが、別のいくつかのウィンドウに移動するまでは機能し、その後はタスクバーで点滅します(のみ)。swtのバグを推測します。[1]

関連する:

窓を前面に出す方法は?

http://github.com/jarmo/win32screenshot/blob/master/lib/win32/screenshot/bitmap_maker.rb#L110"set_foreground "これはxpとwindows7の両方で機能するようです

[1] Windowsおよびhttps://bugs.eclipse.org/bugs/show_bug.cgi?id=303710でアプリケーションをフォアグラウンドにする必要があります

于 2010-02-23T23:43:20.507 に答える
6

これは、Windows 7 と Ubuntu でうまくいきました。

private void bringToFront(final Shell shell) {
    shell.getDisplay().asyncExec(new Runnable() {
        public void run() {
            shell.forceActive();
        }
    });
}
于 2011-12-02T15:53:55.430 に答える
4

これは実際には Windows の機能であり、Tweak UI パワー トイ (少なくとも Windows XP の場合) を介して有効にすることができます。有効にすると、O/S は意図的にウィンドウが強制的にフォーカスされたウィンドウになるのを防ぎ、「フォーカスを盗む」ことを防ぎます。そのため、フォーカスを取得するアクションは、タスクバー アイコンを点滅させるだけに変更されます。O/S はユーザーの要求に応じて意図的にアクションを変換しているため、それに対してできることは何もありません (これは良いことです)。

これは (おそらく)非常に多くのアプリケーションが前面に表示する API を悪用し、その動作がユーザーを苛立たせ、間違ったアプリケーションに入力する原因となったために行われました。

于 2010-02-24T07:12:43.383 に答える
3

バグ 192036 - Shell.forceActive がウィンドウを他のすべてのウィンドウの上に上げない

Eclipse バグ トラッカーに関する @rogerdpack のクエリには、必要なことを行う次の汚い回避策で回答がありました。

public void forceActive(Shell shell) {
    int hFrom = OS.GetForegroundWindow();

    if (hFrom <= 0) {
      OS.SetForegroundWindow(shell.handle);
      return;
    }

    if (shell.handle == hFrom) {
      return;
    }

    int pid = OS.GetWindowThreadProcessId(hFrom, null);
    int _threadid = OS.GetWindowThreadProcessId(shell.handle, null);

    if (_threadid == pid) {
      OS.SetForegroundWindow(shell.handle);
      return;
    }

    if (pid > 0) {
      if ( !OS.AttachThreadInput(_threadid, pid, true)) {
        return;
      }
      OS.SetForegroundWindow(shell.handle);
      OS.AttachThreadInput(_threadid, pid, false);
    }

    OS.BringWindowToTop(shell.handle);
    OS.UpdateWindow(shell.handle);
    OS.SetActiveWindow(shell.handle);
  }
于 2014-05-14T11:25:28.793 に答える
2
private static void onTop(Shell shell) {
        int s = -1;
        Shell[] shells = display.getShells();
        for (int i = 0; i < shells.length; ++i) {
            if (!shells[i].equals(shell)) {
                shells[i].setEnabled(false);
                shells[i].update();
            } else {
                s = i;
            }
        }
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        for (int i = 0; i < shells.length; ++i) {
            if (i != s) {
                shells[i].setEnabled(true);
                shells[i].update();
            }
        }
    }
于 2011-10-07T19:30:05.173 に答える
1

最初に試したことで動作させる方法があります。の以前の状態を復元するには、実際にshell.setMinimized(false)andを呼び出す必要があります。ただし、それはが本当に最小化された状態である場合にのみ機能します。したがって、これが私の最終的な解決策です。これは、まだ最小化されていない場合に人為的に最小化します。最小化を行う必要がある場合、コストは簡単なアニメーションです。shell.setActive()shellshellshell

shell.getDisplay().syncExec(new Runnable() {

    @Override
    public void run() {
        if (!shell.getMinimized())
        {
            shell.setMinimized(true);
        }
        shell.setMinimized(false);
        shell.setActive();
    }
});
于 2015-08-25T10:41:33.363 に答える