简体   繁体   中英

How can I stick a window to top of Desktop in WPF?

I have a dock like application (a few images in a grid, like a widget) which needs to stay on top of Desktop only when Desktop is the current foreground window.

I'm currently using unmanaged code which I've collected here and there to get the name of the foreground window when the foreground window changes. I'm using Topmost to bring my app window to the front when ActiveWindowTitle() == null because when switching to Desktop the foreground window becomes null. The problem is that other applications return null windows every now and then too.

How can I make sure that the current foreground window is Desktop and not some other program?

    delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
    private static WinEventDelegate stickyDelegate = null;

    [DllImport("user32.dll")]
    static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

    private const uint WINEVENT_OUTOFCONTEXT = 0;
    private const uint EVENT_SYSTEM_FOREGROUND = 3;

    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

    public static void ActivateStickToDesktop()
    {
        stickyDelegate = new WinEventDelegate(WinEventProc);
        IntPtr m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, stickyDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
    }

    private static string GetActiveWindowTitle()
    {
        const int nChars = 256;
        IntPtr handle = IntPtr.Zero;
        StringBuilder Buff = new StringBuilder(nChars);
        handle = GetForegroundWindow();

        if (GetWindowText(handle, Buff, nChars) > 0)
        {
            return Buff.ToString();
        }
        return null;
    }

    public static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
    {
        activeWindowName = GetActiveWindowTitle();
        Console.WriteLine("Current active window name: " + activeWindowName);

        if(string.IsNullOrEmpty(activeWindowName))
        {
            AppWindow.Topmost = true;
        } else
        {
            AppWindow.Topmost = false;
            SendToBottom(AppWindow);
        }

        Console.WriteLine("Is Topmost: " + AppWindow.Topmost);
    }

To make window always stay on top make the changes I am suggesting. add Topmost="True" in Mainwindow.xaml, also add Deactivated="Window_Deactivated" in mainwindow.xaml. inside Mainwindow.xaml.cs add

private void Window_Deactivated(object sender, EventArgs e)
    {
        Window window = (Window)sender;
        window.Topmost = true;
    }

this will work for most of the cases

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM