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

发布于 2024-08-22 12:22:47 字数 1703 浏览 10 评论 0原文

目前使用 swt,我有时想要一个程序任意进入前台(就像闹钟一样)。

通常执行以下操作 (jruby):

@shell.setMinimized(false)
@shell.forceActive

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

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

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

有谁知道在 swt 中让应用程序出现在前面的跨平台方法吗?

看来forceActive setActive setMinimized(false) setFocus forceFocus 和 setVisible 的咒语都不能完成这个事情。

我非常确定这是可能的(至少在 Windows 中),正如 E 文本编辑器所做的那样。好吧,这不是 swt,但至少还有一些其他应用程序 已知可以这样做

我想这可能是 swt bug 192036

非常感谢。

相关:

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

Typically the following works (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 not minimized, 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).

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

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

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.

I'm thinking maybe this is swt bug 192036?

Many thanks.

Related:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

鹤仙姿 2024-08-29 12:22:47

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

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

This worked for me on Windows 7 and Ubuntu:

private void bringToFront(final Shell shell) {
    shell.getDisplay().asyncExec(new Runnable() {
        public void run() {
            shell.forceActive();
        }
    });
}
离线来电— 2024-08-29 12:22:47

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

展示了我如何无论如何,都是在 Windows 中完成的(使用 ffi)。

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

在 BringToFront.SetForegroundWindow(wanted) 之后添加“sleep 0.1”
打电话(希望这实际上不是必要的)。

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

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

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

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

(包含一些关于如何实际执行此操作的好提示正确

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

另相关:

如何将窗口置于最前面?< /a>

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

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

shows how I did it in windows, anyway (using 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).

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

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

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

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

On Linux, forceActive does work--but only until you move to another few windows,, then it blinks in the taskbar after that (only). Guessing swt bug. [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 both xp and windows 7

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

琴流音 2024-08-29 12:22:47

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

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

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).

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

美羊羊 2024-08-29 12:22:47

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

@rogerdpack 对 Eclipse bug 跟踪器的查询得到了以下答复肮脏的解决方法做我们需要的事情。

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

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

@rogerdpack's query on Eclipse bug tracker was answered with the following dirty workaround doing what we need.

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);
  }
最后的乘客 2024-08-29 12:22:47
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();
            }
        }
    }
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();
            }
        }
    }
梦旅人picnic 2024-08-29 12:22:47

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

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 shell was truely in the minimized state. So here is my final solution, which artificially minimizes the shell if it was not minimized already. The cost is a quick animation if the minimization has to be done.

shell.getDisplay().syncExec(new Runnable() {

    @Override
    public void run() {
        if (!shell.getMinimized())
        {
            shell.setMinimized(true);
        }
        shell.setMinimized(false);
        shell.setActive();
    }
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文