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

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

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

@shell.setMinimized(false)
@shell.forceActive

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

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

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

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

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

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

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

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

Связанный:


person rogerdpack    schedule 23.02.2010    source источник
comment
Похоже, ошибка SWT, на которую вы ссылаетесь, точно описывает вашу проблему, и похоже, что они не смогут ее исправить.   -  person Mike Daniels    schedule 23.02.2010
comment
Я думаю, что это действительно проблема для окон - хороший улов. На данный момент обходной путь заключается в том, чтобы сначала свернуть оболочку, а затем развернуть ее (или использовать какой-либо собственный код [через ffi или jni], чтобы принудительно использовать ForeGround). В Linux я не совсем уверен, в чем проблема (просто мигает на панели задач). Это может быть исправлено в более новых версиях swt.jar ›= 3.5 bugs.eclipse.org/bugs/show_bug.cgi?id=244597   -  person rogerdpack    schedule 23.02.2010


Ответы (5)


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

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

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

добавьте «sleep 0.1» после вызова BringToFront.SetForegroundWindow(want) (надеюсь, это на самом деле не нужно).

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

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

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

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, так и с Windows 7

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

person rogerdpack    schedule 23.02.2010

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

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

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

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

person Lawrence Dol    schedule 24.02.2010
comment
Если вы погуглите forceForeGround, вы увидите обходной путь, к лучшему или к худшему (я предполагаю, что это то, что awt использует для своего метода toFront, из которого swt не появляется). Я согласен, что forceActive следует использовать экономно :) - person rogerdpack; 24.02.2010
comment
Тьфу, да, все еще слишком много приложений, которые всплывают из фона и крадут ввод, пока вы заняты вводом чего-то другого. Я испытал потерю данных из-за этого раньше. Всплывает фоновое приложение Вы хотите удалить бла? в то время как я печатаю что-то еще, что содержит селектор для Да. Арх. - person Brian Knoblauch; 07.10.2011

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

На @rogerdpack в системе отслеживания ошибок Eclipse был дан следующий ответ < href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=192036#c4" rel="nofollow">грязный обходной путь делает то, что нам нужно.

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);
  }
person Basilevs    schedule 14.05.2014
comment
К сожалению, этот обходной путь не работает на моей копии Windows 10. - person stippi; 20.03.2018

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