2

アプリケーションで「現在再生中」の情報を示すツールチップとして小さなウィンドウを使用しました。確かに私Topmost = "True"はウィンドウ宣言を設定し、新しい曲が再生を開始したら実行しますtooltip.Show()。問題は、フルスクリーンのアプリケーション (ゲームなど) にフォーカスがある場合に、.Show()フルスクリーンのウィンドウが非フルスクリーンのウィンドウになり、境界線とトップバーが表示され (Alt + Enter を押したかのように)、フォーカスが失われたように見えることです。 . したがって、全画面表示に戻すには、ウィンドウをクリックしてフォーカスし、手動で Alt-Enter を押す必要があります。 ShowActivatedに設定"False"済みです。したがって、次の 3 つの解決策があります。

1) どういうわけかTopmostフォーカスを奪わないようにするオプションを作る.Show()

2) いくつかの回避策を使用して、ツールチップ ウィンドウをオプションなしで「常に最前面」にしTopmostます (D3D または OpenGL を介して描画できる (そしておそらく描画される) ため、フルスクリーン アプリケーション上にツールチップをポップアップする必要はありません)。

3) システムが全画面ウィンドウにフォーカスしているかどうかを検出し、ツールチップを表示しようとしません。

このオプションのいずれかで動作を修正する方法がわかりません。または、もっとエレガントなものがありますか?

4

2 に答える 2

1

だから...誰かが興味を持っている場合は、ここに私の「研究」があります。

解決策 1) 失敗しました。この動作に関するいくつかの議論を見つけました。これはバグだと言う人もいれば、機能だと言う人もいますが、いずれもマネージ コードでは解決できないと想定しています。また、シェリダンの答えから試してみましたが、うまくいきませんでした。

解決策 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()なり、ウィンドウが一番上にあることが実際にわかりますが、問題は解決せず、フルスクリーンがエスケープします。内部でどのように動作するか、および P/Invoke で WPF ウィンドウを表示する方法を誰かが知っている場合.Show()は、お知らせください。

解決策 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()ない場合ですIsFullscreen() == 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 に答える