2010-02-23 11 views
15

Obecnie przy pomocy swt, czasami chcę, aby program arbitralnie pojawił się na pierwszym planie (jak może to być budzik).Jak wymusić program java swt, aby "przesunął się na pierwszy plan"?

Zwykle następujące prace (jruby):

@shell.setMinimized(false) 
@shell.forceActive 

to przywrócenie powłoki do przodu, jeśli został zminimalizowany.

Tworzenie nowej powłoki w dowolnym momencie powoduje również przeniesienie (nowej powłoki) na wierzch.

Do tej pory jednak, jeśli powłoka jest , a nie zminimalizowana, powyższy kod miga (mruga) ikonę aplikacji na pasku zadań. Dobrze, że po raz pierwszy uruchomisz go na pierwszym planie. Następnie po prostu miga na pasku zadań. To są okna. W Linuksie wydaje się tylko migać na pasku zadań (domyślnie ubuntu).

Czy ktoś wie na temat sposobu, w jaki można uzyskać dostęp aplikacji na pierwszy plan w swt?

Wygląda na to, że nie ma inkantacji forceActive setActive setMinimized (false) setFocus forceFocus i setVisible mogą to osiągnąć.

Jestem prawie pewien, że jest to możliwe (przynajmniej w oknach), jak robi to edytor tekstu. Cóż, to nie jest SWT, ale przynajmniej inne aplikacje have been known to do it.

Myślę, że może to jest swt bug 192036?

Wielkie dzięki.

pokrewne:

+0

Wygląda jak błąd SWT, z którym połączono ** dokładnie ** opisuje twój problem, i wygląda na to, że nie będzie w stanie go naprawić. –

+0

Myślę, że to rzeczywiście problem dla Windows - dobry połów. Na razie należy jak najszybciej zminimalizować powłokę, a następnie ją unminimize (lub użyć kodu natywnego [przez ffi lub jni], aby wymusić na nim ForceForeGround). W Linuksie nie jestem do końca pewien, na czym polega problem (po prostu miga na pasku zadań). To * może * być naprawione w nowszych wersjach pliku swt.jar> = 3.5 https://bugs.eclipse.org/bugs/show_bug.cgi?id = 244597 – rogerdpack

Odpowiedz

5

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

pokazuje jak to zrobiłem w oknach, w każdym razie (przy użyciu FFI).

Kilka przydatnych sztuczek „może” być

dodać sen „0,1” po BringToFront.SetForegroundWindow (chciał) call (mam nadzieję, że to nie jest rzeczywiście konieczne).

dodaj shell.set_active po położyłeś okno na pierwszym planie. Z jakiegoś powodu forceActive nie wywołuje funkcji setActive.

Należy pamiętać, że setActive wykonuje wywołanie user32.dll BringWindowToTop i należy to zrobić przed odłączeniem wejścia wątku.

Należy również zauważyć, że wydaje się, jeżeli można to zrobić ty wywołuje we właściwej kolejności może nie trzeba używać hack wejściowego wątek w ogóle (?)

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

(zawiera kilka dobrych wskazówek na temat faktycznie zrobić to prawo)

w systemie Linux forceActive robi pracę - ale tylko do momentu przejścia do kolejnych kilku okien ,, po czym miga na pasku zadań po to (tylko). Zgadywanie błędu swt. [1]

związane również:

How to bring a window to the front?

http://github.com/jarmo/win32screenshot/blob/master/lib/win32/screenshot/bitmap_maker.rb#L110 "set_foreground", który wydaje się działać z zarówno XP i Windows 7

[1] Need to bring application to foreground on Windows i https://bugs.eclipse.org/bugs/show_bug.cgi?id=303710

4

ten jest właściwie funkcją systemu Windows, którą można włączyć za pomocą pluszowej myszki Tweak UI (przynajmniej w Windows XP). Po włączeniu O/S celowo uniemożliwia, aby okno nie stało się oknem skupionym, aby zatrzymać "kradzież fokusa". W związku z tym akcja przechwytywania ostrości jest zmieniana tak, aby migała ikona paska zadań - ponieważ O/S świadomie konwertuje akcję na żądanie użytkownika, nic nie da się z tym zrobić (i to dobrze).

Było to (prawdopodobnie) zrobione, ponieważ , tak więc wiele aplikacji nadużywało interfejsu API "bring-to-front", a zachowanie zarówno irytowało użytkowników, jak i powodowało ich wprowadzanie do niewłaściwej aplikacji.

+0

Jeśli użyjesz go w serwisie forceForeGround, zobaczysz pracę na lepsze lub na gorsze (zakładam, że jest to metoda używana w metodzie toFront, której nie widać). Zgadzam się, że forceActive powinno być używane oszczędnie :) – rogerdpack

+1

Ugh, tak, wciąż jest zbyt wiele aplikacji, które pojawiają się z tła, kradnąc wejście, gdy byłeś zajęty wpisywaniem w coś innego. Wcześniej doświadczyłem utraty danych. Aplikacja w tle wyskakuje "Czy chcesz usunąć blah?" podczas gdy ja wpisuję coś innego, co zawiera selektor "Tak". Argh. –

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

ten pracował dla mnie na Windows 7 i Ubuntu:

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

Bug 192036 - Shell.forceActive doesn't raise a window above all other windows

@rogerdpack's query on Eclipse bug tracker odpowiedział z następującym dirty workaround robi to, czego potrzebujemy.

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

Istnieje sposób na to, aby działało z tym, co początkowo próbowałeś. Musisz zadzwonić pod numer shell.setMinimized(false), a następnie shell.setActive(), aby przywrócić poprzedni stan shell. Jednak, który działa tylko wtedy, gdy shell był naprawdę w stanie zminimalizowanym. Oto moje ostateczne rozwiązanie, które sztucznie minimalizuje wartość shell, jeśli nie zostało już zminimalizowane. Koszt jest szybką animacją, jeśli minimalizacja musi zostać wykonana.

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

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