2010-02-23 64 views
15

目前有了swt,我有時候需要一個程序隨意來到前臺(就像鬧鐘一樣)。你如何強制一個java swt程序「移動到前臺」?

通常如下工程(jruby的):

@shell.setMinimized(false) 
@shell.forceActive 

這帶來的外殼到前,如果它是最小化。

隨時創建一個新的shell也會將(新的shell)帶到最前面。

不過,如果外殼是而不是最小化,上面的代碼只是閃爍(閃爍)應用程序在任務欄中的圖標。實際上,第一次運行它會將它帶到前面。之後,它只是閃爍在任務欄中。那是窗戶。在Linux上它似乎只在任務欄中閃爍(ubuntu默認)。

有誰知道跨平臺的方式讓應用程序來到前面,在SWT?

看來,沒有咒語forceActive setActive setMinimized(false)setFocus forceFocus和setVisible可以完成這件事情。

我很確定它是可能的(至少在Windows中),因爲E文本編輯器可以做到這一點。那麼,這不是swt,但至少有一些其他應用have been known to do it。我想這可能是swt bug 192036

非常感謝。

相關:

+0

看起來像你鏈接到**的SWT錯誤**描述了你的問題,聽起來好像他們不能修復它。 – 2010-02-23 02:11:24

+0

我認爲這確實是Windows的問題 - 很好的抓住。現在解決的辦法是首先將一個shell最小化,然後取消最小化(或者使用一些本地代碼[通過ffi或jni]來強制它覆蓋它)。在Linux中,我不太確定問題是什麼(只是在任務欄中閃爍)。它*可能*在新版本的swt.jar> = 3.5中修復 https://bugs.eclipse.org/bugs/show_bug.cgi?id = 244597 – rogerdpack 2010-02-23 17:52:53

回答

5

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

顯示我是如何做的在Windows,反正(使用FFI)。

幾個有用的技巧,「可能」是

添加BringToFront.SetForegroundWindow後「睡眠0.1」(想) 調用(希望這個人是不是確有必要)。

在之後添加一個shell.set_active 您已將窗口帶到前臺。由於某種原因,forceActive不會調用setActive。

注意,setActive執行user32.dll BringWindowToTop調用,並且需要在分離線程輸入之前完成。

還要注意,它似乎如果你能做到,你以正確的順序,你可能不需要使用線程輸入黑客在所有的(?)

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

(包含如何幾個很好的提示來電要真正做到這一點

在Linux上,forceActive 確實工作 - 但直到您移動到另一個幾個窗口,,然後在之後的任務欄(只)閃爍。猜swt bug。 [1]

另外相關:

How to bring a window to the front?

http://github.com/jarmo/win32screenshot/blob/master/lib/win32/screenshot/bitmap_maker.rb#L110 「set_foreground」,這似乎與 XP和Windows 7

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

4

此工作實際上是Windows的一項功能,可以通過Tweak UI電源玩具啓用(至少在Windows XP中)。啓用時,操作系統有意防止窗口強制自己成爲關注的窗口,以阻止它「竊取焦點」。因此,抓取焦點的動作改變爲只是閃爍任務欄圖標 - 因爲操作系統是根據用戶的請求故意轉換動作,所以對此無能爲力(這是件好事)。

這是(可能)完成,因爲所以許多應用程序濫用引入到前端的API和行爲都惱火的用戶,並導致他們輸入到錯誤的應用程序。

+0

如果你的谷歌for forceForeGround你會看到一個解決方案,好或壞(我認爲這是什麼awt用於它的toFront方法,其中swt似乎沒有)。我同意forceActive應該謹慎使用:) – rogerdpack 2010-02-24 16:34:44

+1

呃,是的,仍然有太多的應用程序從背景中彈出,在您忙於輸入其他內容時竊取輸入。我之前經歷過數據丟失。後臺應用彈出「你想刪除等等嗎?」而我輸入的其他東西恰好包含「是」的選擇器。哎呀。 – 2011-10-07 19:34:21

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

這爲我工作在Windows 7和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與下面dirty workaround回答做什麼,我們需要的。

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

有一種方法可以使它與您最初嘗試的方法一起工作。您實際上需要撥打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(); 
    } 
}); 
相關問題