【问题标题】:WPF topmost option makes fullscreen app to escapeWPF topmost 选项使全屏应用程序逃脱
【发布时间】:2013-09-03 21:28:44
【问题描述】:

我使用小窗口作为工具提示,在我的应用程序中显示“正在播放”信息。当然,我在窗口声明中设置了Topmost = "True",当新歌开始播放时,我设置了tooltip.Show()。问题是当我关注全屏应用程序(例如游戏)时,.Show() 调用使全屏窗口变为非全屏、窗口化、带有边框和顶栏(就像我按 Alt + Enter 一样),它看起来像也失去焦点。因此,要恢复全屏,我需要在窗口中单击以将其聚焦并手动按 Alt-Enter。 ShowActivated 已设置为 "False"。 所以,我看到了三个解决方案:

1) 以某种方式使Topmost 选项不会引起对.Show() 的关注

2) 使用一些变通方法使工具提示窗口“始终位于顶部”而不使用 Topmost 选项(我不需要在全屏应用程序上弹出工具提示,因为它可以(并且可能会)通过 D3D 或 OpenGL 绘制)

3) 检测系统现在是否有全屏窗口焦点并且不要尝试显示工具提示。

我不知道如何使用这些选项来修复行为,或者也许有更优雅的东西?

【问题讨论】:

    标签: c# wpf fullscreen


    【解决方案1】:

    所以...如果有人感兴趣,这是我的“研究”。

    解决方案 1) 失败。 我发现了一些关于此行为的讨论,有些人说这是一个错误,其他人说这是一个功能,但其中任何一个都认为它无法在托管代码中解决。我还尝试了 Sheridan 的回答,但没有成功。

    解决方案 2) 失败。 我对 P/Invoke 有一些经验,但如果出现问题,我通常会失败。在这种特殊情况下,我尝试使用

    this.Handle = new WindowInteropHelper(this).Handle;
    SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
    

    正如它在网络上所建议的那样。此代码不显示窗口。所以我试着用

    来展示它
    ShowWindow(this.Handle, 4); // I also tried SHOW_NORMAL and few other flags
    

    但窗口仍然不可见

    如果我执行this.Visibility = /*visible*/this.Show(),它就会变得可见,并且我确实看到该窗口位于最上面,但它不能解决问题并且全屏转义。如果有人知道.Show() 在内部如何工作以及如何使用 P/Invoke 显示 WPF 窗口,请告诉我。

    解决方案 3) 成功。 我在谷歌上搜索了一下here 并稍微缩短了它:

        internal class FullscreenCheck
        {
            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }
    
            [DllImport("user32.dll")]
            private static extern IntPtr GetForegroundWindow();
            [DllImport("user32.dll")]
            private static extern IntPtr GetDesktopWindow();
            [DllImport("user32.dll")]
            private static extern IntPtr GetShellWindow();
            [DllImport("user32.dll", SetLastError = true)]
            private static extern int GetWindowRect(IntPtr hwnd, out RECT rc);
    
            // I hope this handles never changes
            private static IntPtr hndlDesktop = GetDesktopWindow();
            private static IntPtr hndlShell   = GetShellWindow();
    
            public static bool IsFullscreen()
            {
                var hndlForeground = GetForegroundWindow();
                if (hndlForeground == null || hndlForeground == IntPtr.Zero || hndlForeground == hndlDesktop || hndlForeground == hndlShell)
                {
                    return false;
                }
    
                RECT appBounds;
                GetWindowRect(hndlForeground, out appBounds);
                var screenBounds = System.Windows.Forms.Screen.FromHandle(hndlForeground).Bounds;
    
                return ((appBounds.Bottom - appBounds.Top) == screenBounds.Height && (appBounds.Right - appBounds.Left) == screenBounds.Width);
            }
    

    所以最后一步就是不调用.Show() if IsFullscreen() == true

    【讨论】:

      【解决方案2】:

      我对此并不完全确定,但试试这个怎么样?:

      tooltip.Owner = referenceToParentWindow;
      

      如果您从 MainWindow.xaml.cs 启动它,那么您将使用它:

      tooltip.Owner = this;
      

      如果您从 MainWindow.xaml.cs 文件外部启动它,那么您可以(也许)使用它:

      tooltip.Owner = Application.Current.MainWindow;
      

      【讨论】:

      • 不,遗憾的是没有区别。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多