2010-02-23 19 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(); 
    } 
}); 
相关问题