Как заставить программу java swt "переместиться на передний план"?

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

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

@shell.setMinimized(false)
@shell.forceActive

Это приносит оболочку на фронт, если она была сведена к минимуму.

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

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

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

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

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

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

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

по теме:

Ответ 1

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

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

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

добавьте "sleep 0.1" после BringToFront.SetForegroundWindow(требуется) звоните (надеюсь, это не на самом деле необходимо).

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

NB, что 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, так и с окнами 7

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

Ответ 2

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

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

Ответ 3

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

private void bringToFront(final Shell shell) {
    shell.getDisplay().asyncExec(new Runnable() {
        public void run() {
            shell.forceActive();
        }
    });
}

Ответ 4

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();
            }
        }
    }

Ответ 5

Ошибка 192036 - Shell.forceActive не поднимает окно над всеми другими окнами

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

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);
  }

Ответ 6

Есть способ заставить его работать с тем, что вы изначально пытались. Вам действительно нужно вызвать 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();
    }
});