TopMost窗口有时会在非TopMost全屏窗口后面

时间:2013-04-26 00:47:41

标签: c# .net wpf winforms

我有一个“控制工具栏”应用程序需要浮动在双显示器系统的主屏幕上的其他所有内容上。它将自己定位在主屏幕的顶部并设置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,但这是一个相当丑陋的解决方案,因为它激活了工具栏应用程序,该应用程序取消了全屏应用程序,这反过来使任务栏弹出全屏应用程序。当你想要做的就是切换哪个全屏应用有焦点时,有点hacky。

1 个答案:

答案 0 :(得分:1)

好的,这就是我最终做的......在我放弃之前我想出了一个更多的想法,这很有效。在工具栏窗口中,我有一个计时器,每秒轮询一次工具栏区域的最顶层窗口,如下所示:

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代码,以防客户端无法/不运行此修补程序作为解决方法。