Как заставить программу 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();
}
});