简体   繁体   中英

Make WPF Window Ignore Show Desktop (Win+D)

So there are various questions on this topic already (from 4-5 years ago) and I have followed them to come up with the following solution to avoid my window reacting to Win+D (Show Desktop) Command:

public partial class MainWindow : Window
{

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindowEx(IntPtr hP, IntPtr hC, string sC, string sW);
    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    public MainWindow()
    {
        InitializeComponent();
        Loaded += OnWindowLoaded;
    }

    private void OnWindowLoaded(object sender, RoutedEventArgs e)
    {
        IntPtr nWinHandle = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Progman", null);
        nWinHandle = FindWindowEx(nWinHandle, IntPtr.Zero, "SHELLDLL_DefView", null);
        SetParent(new WindowInteropHelper(this).Handle, nWinHandle);
    }
}

However this does not seem to work for me (the above code is in a brand new project).

Can anyone explain if there has been any change to the WinAPI, should this still work? This is the answer I come across on almost every question I find on this topic.

I am running:

  • Edition: Windows 10 Pro
  • Version: 21H2
  • Build: 19044.1645
  • Experience: Windows Feature Experience Pack 120.2212.4170.0,

Ok so I found the solution that works for me, I know setting the window as a child of the desktop has its problems/risks, but for people that still need to do it, here is what I found:

The "SHELLDLL_DefView" desktop window is not always a child of "Progman", sometimes it is a child of a "WorkerW" window instead. This is why the code in my original question didn't work for me.

So rather than finding the "Progman" window and finding the "SHELLDLL_DefView" child, you instead need to enumerate through all windows and find the window which has "SHELLDLL_DefView" as a child.

This is done with the EnumWindows function ( https://www.pinvoke.net/default.aspx/user32.enumwindows )

The below code is a mashup of the one of the examples from the pinvoke.net link above and the following 2 answers:


    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr hP, IntPtr hC, string sC, 
    string sW);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumWindows(EnumedWindow lpEnumFunc, ArrayList 
    lParam);

    public delegate bool EnumedWindow(IntPtr handleWindow, ArrayList handles);

    public static bool GetWindowHandle(IntPtr windowHandle, ArrayList 
    windowHandles)
    {
        windowHandles.Add(windowHandle);
        return true;
    }

    private void SetAsDesktopChild() 
    {
        ArrayList windowHandles = new ArrayList();
        EnumedWindow callBackPtr = GetWindowHandle;
        EnumWindows(callBackPtr, windowHandles);

        foreach (IntPtr windowHandle in windowHandles)
        {
            IntPtr hNextWin = FindWindowEx(windowHandle, IntPtr.Zero,     
            "SHELLDLL_DefView", null);
            if (hNextWin != IntPtr.Zero)
            {
                var interop = new WindowInteropHelper(_window);
                interop.EnsureHandle();
                interop.Owner = hNextWin;
            }
        }
    }

Now my WPF stays on the desktop after Show Desktop/Win+D as intended.

There are some Windows operations that cannot be overridden by the developer, such as:

  • Always showing your tray icon on the main taskbar
  • Overriding the Win+D to always show your window on the desktop
  • Forcing notifications to always be shown

These are policies of the Windows operating system to ensure the user is always in control, and not the developer.

Having said that, you can try another approach to making your "widget" visible. Might I suggest the following:

A 1-second delay to show your widget is a small cost to your UX, in my opinion.

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