2

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

1)以某种Topmost方式选择不引起窃取注意力.Show()

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

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

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

4

2 回答 2

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*/or 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);
        }

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

于 2013-09-04T20:35:59.163 回答
0

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

tooltip.Owner = referenceToParentWindow;

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

tooltip.Owner = this;

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

tooltip.Owner = Application.Current.MainWindow;
于 2013-09-04T09:10:04.410 回答