首页 文章

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

提问于
浏览
1

我有一个“控制工具栏”应用程序需要漂浮在双显示器系统的主屏幕上的其他所有内容上 . 它将自己定位在主屏幕的顶部并设置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 回答

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

相关问题