16

目前使用 swt,我有时希望一个程序任意出现在前台(就像闹钟一样)。

通常以下工作(jruby):

@shell.setMinimized(false)
@shell.forceActive

如果它被最小化,这会将外壳带到前面。

在任何时候创建一个新的 shell 也会把(新的 shell)带到前面。

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

有人知道在 swt 中让应用程序脱颖而出的跨平台方式吗?

似乎没有任何咒语 forceActive setActive setMinimized(false) setFocus forceFocus 和 setVisible 可以完成这件事。

我很确定这是可能的(至少在 Windows 中),就像 E 文本编辑器那样。好吧,这不是 swt,但至少已知其他一些应用程序可以做到这一点

我在想也许这是swt bug 192036

非常感谢。

有关的:

4

6 回答 6

6

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

无论如何(使用 ffi)显示了我在 Windows 中是如何做到的。

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

在 BringToFront.SetForegroundWindow(wanted) 调用之后添加一个“sleep 0.1”(希望这个实际上不是必需的)。

将窗口置于前台添加一个 shell.set_active 。由于某种原因 forceActive 不调用 setActive。

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

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

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

(包含有关如何正确执行此操作的几个很好的提示)

在 Linux 上,forceActive确实有效——但只有在您移动到另外几个窗口之前,它才会在任务栏中闪烁(仅)。猜测 swt 错误。[1]

还有相关的:

如何将窗户带到前面?

http://github.com/jarmo/win32screenshot/blob/master/lib/win32/screenshot/bitmap_maker.rb#L110 "set_foreground" 这似乎适用于xp和 windows 7

[1]需要在 Windows和https://bugs.eclipse.org/bugs/show_bug.cgi?id=303710上将应用程序带到前台

于 2010-02-23T23:43:20.507 回答
6

这在 Windows 7 和 Ubuntu 上对我有用:

private void bringToFront(final Shell shell) {
    shell.getDisplay().asyncExec(new Runnable() {
        public void run() {
            shell.forceActive();
        }
    });
}
于 2011-12-02T15:53:55.430 回答
4

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

之所以这样做(可能)是因为太多应用程序滥用了前置 API,而且这种行为既惹恼了用户,又导致他们输入了错误的应用程序。

于 2010-02-24T07:12:43.383 回答
3

错误 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);
  }
于 2014-05-14T11:25:28.793 回答
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();
            }
        }
    }
于 2011-10-07T19:30:05.173 回答
1

有一种方法可以使它与您最初尝试的内容一起工作。您实际上需要调用shell.setMinimized(false)and 之后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();
    }
});
于 2015-08-25T10:41:33.363 回答