java 你如何强制一个java swt 程序“将自己移到前台”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2315560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:34:56  来源:igfitidea点击:

How do you force a java swt program to "move itself to the foreground"?

javashelluser-interfaceswtforeground

提问by rogerdpack

Currently with swt, I sometimes want a program to arbitrarily come to the foreground (like an alarm clock might).

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

Typically the following works (jruby):

通常以下工作(jruby):

@shell.setMinimized(false)
@shell.forceActive

This brings the shell to the front if it was minimized.

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

Creating a new shell at any time also brings the (new shell) to the front.

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

So far so good, however, if the shell is notminimized, the above code just flashes (blinks) the app's icon in the taskbar. Well actually the first time you run it, it brings it to the front. After that, it just blinks in the taskbar. That's windows. On Linux it appears to only blink in the taskbar (ubuntu default).

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

Does anybody know of a cross platform way of getting the app to come to the front, in swt?

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

It seems that no incantation of forceActive setActive setMinimized(false) setFocus forceFocus and setVisible can accomplish this thing.

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

I'm pretty sure it is possible (at least in windows), as the E Text Editor does it. Well, that's not swt, but at least some other apps have been known to do it.

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

I'm thinking maybe this is swt bug 192036?

我在想这可能是swt bug 192036吗?

Many thanks.

非常感谢。

Related:

有关的:

采纳答案by rogerdpack

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

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

shows how I did it in windows, anyway (using ffi).

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

A couple of helpful tricks "may" be

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

add a 'sleep 0.1' after the BringToFront.SetForegroundWindow(wanted) call (hopefully this one isn't actually necessary).

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

add a shell.set_active afteryou have brought the window to the foreground. For some reason forceActive doesn't call setActive.

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

NB that setActive does a user32.dll BringWindowToTop call, and needs to be done before you detach thread input.

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

Note also that it appears if you can do you calls in the right order you may not need to use the thread input hack at all (?)

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

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

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

(contains several good hints on how to actually do this right)

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

On Linux, forceActive doeswork--but only until you move to another few windows,, then it blinks in the taskbar after that (only). Guessing swt bug. [1]

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

Also related:

还相关:

How to bring a window to the front?

如何把窗户放在前面?

http://github.com/jarmo/win32screenshot/blob/master/lib/win32/screenshot/bitmap_maker.rb#L110"set_foreground" which seems to work with bothxp and windows 7

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 Windowsand https://bugs.eclipse.org/bugs/show_bug.cgi?id=303710

[1]需要在 Windowshttps://bugs.eclipse.org/bugs/show_bug.cgi?id=303710上将应用程序置于前台

回答by Manuel

This worked for me on Windows 7 and Ubuntu:

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

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

回答by Lawrence Dol

This is actually a feature of Windows, which can be enabled via the Tweak UI power toy (at least for Windows XP). When enabled the O/S deliberately prevents a window from forcing itself to be the focused window to stop it "stealing focus". As such, the action to grab focus is changed to just flashing the taskbar icon - since the O/S is deliberately converting the action at the user's request, there will be nothing you can do about it (and this is a good thing).

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

This was (probably) done because somany applications abused the bring-to-front API and the behavior both annoyed users and caused them to input into the wrong application.

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

回答by Basilevs

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

错误 192036 - Shell.forceActive 不会在所有其他窗口之上提升一个窗口

@rogerdpack's query on Eclipse bug trackerwas answered with the following dirty workarounddoing what we need.

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

回答by dklovedoctor

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

回答by milez

There is a way to make it work with what you initially tried. You actually need to call shell.setMinimized(false)and after that shell.setActive()to restore the previous state of the shell. However, that only works if the shellwas truely in the minimized state. So here is my final solution, which artificially minimizes the shellif it was not minimized already. The cost is a quick animation if the minimization has to be done.

有一种方法可以使其与您最初尝试的内容一起使用。您实际上需要调用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();
    }
});