2

我有一个“控制工具栏”应用程序,它需要浮动在双显示器系统主屏幕上的所有其他内容之上。它将自己定位在主屏幕的顶部并设置 TopMost=true。

此控制工具栏可用于启动其他两个运行全屏但不是 TopMost 的进程,在双监视器系统的每个监视器上运行一个。通过将 BorderStyle 设置为 None 并将窗口的边界设置为完全适合屏幕尺寸,这些窗口被设置为全屏运行。全屏窗口覆盖任务栏没有问题,我可以整天专注于主显示器上的全屏窗口并与之交互,并且工具栏保持在顶部。

然而,在软件王国中,一切都不是那么美好 - 某些操作会使 TopMost 工具栏弹出非 TopMost 全屏窗口下。其中一项操作是将焦点放在辅助监视器上的全屏应用程序上,然后将焦点返回到主监视器上的全屏应用程序上。这是最容易重现的情况,因为每次我遵循此顺序时都会发生这种情况。我很难可靠地重现其他场景,但是如果我按 Windows 键来拉起开始菜单并开始在 Internet Explorer 中浏览,有时当我完成浏览并关闭 IE 并将焦点返回到主监视器全屏应用程序时弹出 TopMost 窗口。

知道如何将 TopMost 窗口保持在顶部,并且不允许它在非 TopMost 全屏窗口下弹出吗?我不介意每秒轮询一次 WindowFromPoint 以查看工具栏是否仍在顶部,如果没有,则以某种方式将其弹出,但我不想将注意力从全屏应用程序上移开,如果这是用户正在使用,因此 Activate() 不是一个特别好的解决方案。

我认为这并不重要,但工具栏是 WPF 窗口,全屏应用程序是 WinForms。

更新:

最简单的测试方法是按 F11 在每台显示器上的两个浏览器窗口中全屏显示,以模拟全屏应用程序,然后让 TopMost 窗口浮动在任何地方。在两个全屏窗口之间单击,您将看到它们下方弹出的 TopMost 窗口。我在一台显示器上打开 IE,在另一台显示器上打开 Chrome,因为 IE 不允许我做两个全屏窗口。

我现在实现了 Activate() hack,但它是一个相当丑陋的解决方案,因为它会激活工具栏应用程序,这会使全屏应用程序失去焦点,从而使任务栏弹出全屏应用程序。当您想要做的就是切换哪个全屏应用程序具有焦点时,这有点骇人听闻。

4

1 回答 1

3

好的,这就是我最终要做的……在我要放弃之前,我又想出了一个想法,而且效果很好。在工具栏窗口中,我有一个计时器,它每秒轮询一次工具栏区域上最顶部的窗口,如下所示:

var topMostHandle = WindowFromPoint((int)(Left + ActualWidth / 2), (int)ActualHeight / 2);

if (topMostHandle != new WindowInteropHelper(this).Handle)
{
    Topmost = false;
    Topmost = true;
}

所以我基本上只是在工具栏中间取一个点,测试一下工具栏是否在上面。如果不是,我将 TopMost 设置为 false 并返回 true,这似乎在激活它的情况下将它带回顶部。它消失一秒钟的闪光有点烦人,但我不希望这种情况经常发生。

感谢 Hans Passant 为 Win7 SP1 找到了解决该问题的修补程序:http: //support.microsoft.com/kb/2733420

我将我的 hack 保留在代码中,以防客户端不能/不运行修补程序作为解决方法。

于 2013-04-26T01:30:17.533 回答