WPF最上面的选项使全屏应用程序退出

本文关键字:应用程序 退出 选项 WPF | 更新日期: 2023-09-27 18:30:07

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

1) 以某种方式使Topmost选项不会导致在.Show() 上窃取焦点

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

3) 现在检测系统是否有全屏窗口,不要试图显示工具提示。

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

WPF最上面的选项使全屏应用程序退出

所以。。。如果有人感兴趣,这里是我的"研究"。

解决方案1)失败我发现了一些关于这种行为的讨论,一些人说这是一个bug,另一些人说它是一个功能,但他们中的任何人都认为它无法在托管代码中解决。我还尝试了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)成功我在这里用谷歌搜索找到了工作代码,并稍微缩短了它:

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

因此,如果IsFullscreen() == true

,最后一步就是不调用.Show()

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

tooltip.Owner = referenceToParentWindow;

如果你从MainWindow.xaml.cs启动这个,那么你会使用这个:

tooltip.Owner = this;

如果你从MainWindow.xaml.cs文件之外启动这个,那么你可以(也许)使用这个:

tooltip.Owner = Application.Current.MainWindow;