你如何强制java swt程序“移动到前台”?

时间:2010-02-23 01:31:18

标签: java shell user-interface swt foreground

目前有了swt,我有时想让一个程序随意地走到前台(就像闹钟一样)。

通常以下作品(jruby):

@shell.setMinimized(false)
@shell.forceActive

如果它被最小化,它会将shell带到前面。

随时创建一个新shell也会将(新shell)带到前面。

到目前为止一切顺利,如果shell 最小化,上面的代码只是闪烁(闪烁)任务栏中的应用程序图标。实际上,当你第一次运行它时,它会把它带到前面。之后,它只是在任务栏中闪烁。那是窗户。在Linux上,它似乎只在任务栏中闪烁(默认为ubuntu)。

有没有人知道让应用程序走到前面的跨平台方式,在swt?

似乎没有强制使用forceActive setActive setMinimized(false)setFocus forceFocus和setVisible可以完成这件事。

我很确定它是可能的(至少在Windows中),就像E文本编辑器那样。嗯,这不是swt,但至少还有其他一些应用程序have been known to do it

我想也许这是swt bug 192036

非常感谢。

相关:

5 个答案:

答案 0 :(得分:6)

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

显示我是如何在Windows中完成的(使用ffi)。

一些有用的技巧“可能”是

在BringToFront.SetForegroundWindow(想要)之后添加'sleep 0.1' 打电话(希望这个实际上不是必需的)。

在之后添加一个shell.set_active ,您已将窗口置于前台。出于某种原因,forceActive不会调用setActive。

请注意,setActive会执行user32.dll BringWindowToTop调用,并且需要在分离线程输入之前完成。

另请注意,如果您可以按照正确的顺序进行调用,则可能根本不需要使用线程输入hack(?)

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

答案 1 :(得分:6)

这适用于Windows 7和Ubuntu:

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

答案 2 :(得分:4)

这实际上是Windows的一项功能,可以通过Tweak UI电源玩具启用(至少对于Windows XP)。当启用时,O / S故意阻止窗口强制自己成为聚焦窗口以阻止它“窃取焦点”。因此,抓取焦点的动作改为仅闪烁任务栏图标 - 因为操作系统是故意根据用户的请求转换动作,所以你无能为力(这是一件好事)。

这可能已经完成了,因为所以许多应用程序滥用了带到前面的API,这些行为都让用户烦恼并导致他们输入错误的应用程序。

答案 3 :(得分: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 :(得分: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);
  }