Как вы заставляете программу Java SWT "переместиться на передний план"? - PullRequest
16 голосов
/ 23 февраля 2010

В настоящее время с помощью SWT я иногда хочу, чтобы программа произвольно выходила на передний план (как, например, будильник).

Обычно следующие работы (jruby):

@shell.setMinimized(false)
@shell.forceActive

Выносит оболочку на фронт, если она была свернута.

Создание новой оболочки в любое время также выводит (новую оболочку) на передний план.

Пока все хорошо, но если оболочка не свернута, приведенный выше код просто мигает (мигает) значком приложения на панели задач. Ну, на самом деле, когда вы запускаете его в первый раз, он выводит его на передний план. После этого он просто мигает на панели задач. Это окна. В Linux он только мигает на панели задач (Ubuntu по умолчанию).

Кто-нибудь знает о кроссплатформенном способе заставить приложение выйти на первый план, в SWT?

Кажется, что никакое заклинание forceActive setActive setMinimized (false) setFocus forceFocus и setVisible не могут выполнить эту задачу.

Я почти уверен, что это возможно (по крайней мере, в Windows), как это делает E Text Editor. Ну, это не SWT, но, по крайней мере, некоторые другие приложения , как известно, делают это .

Я думаю, может быть, это SWT ошибка 192036 ?

Большое спасибо.

Связанный:

Ответы [ 6 ]

6 голосов
/ 02 декабря 2011

Это сработало для меня в Windows 7 и Ubuntu:

private void bringToFront(final Shell shell) {
    shell.getDisplay().asyncExec(new Runnable() {
        public void run() {
            shell.forceActive();
        }
    });
}
6 голосов
/ 24 февраля 2010

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

показывает, как я это делал в Windows, в любом случае (используя ffi).

Пара полезных трюков "может" быть

добавить 'sleep 0.1' после BringToFront.SetForegroundWindow (требуемый) позвоните (надеюсь, это на самом деле не нужно).

добавить shell.set_active после того, как вы вывели окно на передний план. По некоторым причинам forceActive не вызывает setActive.

Обратите внимание, что setActive выполняет вызов user32.dll BringWindowToTop и должен быть выполнен до отсоединения ввода потока.

Обратите также внимание, что если вы можете делать звонки в правильном порядке, вам вообще может не понадобиться взломать поток ввода (?)

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

(содержит несколько хороших советов о том, как на самом деле это сделать правильно )

В Linux forceActive работает - но только до тех пор, пока вы не перейдете к другим нескольким окнам, после этого (только) он мигает на панели задач. Угадай ошибку. [1]

Также связано:

Как вывести окно на фронт?

http://github.com/jarmo/win32screenshot/blob/master/lib/win32/screenshot/bitmap_maker.rb#L110 "set_foreground", который, кажется, работает с и xp и windows 7

[1] Необходимо вывести приложение на передний план в Windows и https://bugs.eclipse.org/bugs/show_bug.cgi?id=303710

4 голосов
/ 24 февраля 2010

На самом деле это особенность Windows, которую можно включить с помощью мощной игрушки Tweak UI (по крайней мере, для Windows XP). При включении O / S сознательно не позволяет окну заставить себя быть сфокусированным окном, чтобы остановить его «кражу фокуса». Таким образом, действие по захвату фокуса заменено простым миганием значка панели задач - поскольку O / S намеренно преобразует действие по запросу пользователя, вы ничего не сможете с этим поделать (и это хорошо).

Это (вероятно) было сделано, потому что так многие приложения злоупотребляли API-интерфейсом и поведением, что раздражало пользователей и вызывало их ввод в неправильное приложение.

3 голосов
/ 14 мая 2014

Ошибка 192036 - Shell.forceActive не поднимает окно над всеми остальными окнами

На запрос @ rogerdpack на Eclipse bug tracker был дан ответ грязный обходной путь делает то, что нам нужно.

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);
  }
2 голосов
/ 07 октября 2011
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();
            }
        }
    }
1 голос
/ 25 августа 2015

Есть способ заставить его работать с тем, что вы изначально пробовали. Вам на самом деле нужно позвонить shell.setMinimized(false) и после этого shell.setActive(), чтобы восстановить предыдущее состояние shell. Однако , это работает, только если shell действительно находился в свернутом состоянии. Итак, вот мое окончательное решение, которое искусственно минимизирует shell, если оно еще не было минимизировано. Стоимость - быстрая анимация, если минимизация должна быть выполнена.

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

    @Override
    public void run() {
        if (!shell.getMinimized())
        {
            shell.setMinimized(true);
        }
        shell.setMinimized(false);
        shell.setActive();
    }
});
...