Replacing desktop wallpaper / draw on the desktop

2020-06-24 06:36发布

问题:

I'd like to do some custom drawing to my windows desktop such that it appears to replace the desktop background (wallpaper). My first try was to get a DC for desktopListView and draw to it:

IntPtr desktopDC = GetWindowDC(desktopListView);
Graphics g = Graphics.FromHwnd(desktopDC); //<-- fails on out of memory error

I then tried to create a NativeWindow and capture the WM_PAINT message by assigning the native window's handle to the desktop and do my own drawing, but I was unable to see any messages to the desktop.

Ideally I'd like to do this in WPF and not windows forms at all. Any clue how to create a WPF window that I can draw to that sits beneath the desktop icons but on top of the wallpaper such that it ignores any mouse messages and the desktop continues to work normally?

回答1:

If you get the window handle of the desktop, you can create a new window and add your own custom window as a child of that. Putting it behind the list view may give you the result you need, though I'm not 100% sure how well the transparency will work.

Found some code - Most of what you need is in the first part if you don't need to deal with multiple screens that change shape.

    public void SetDesktopWindows()
    {
        Thread.Sleep(0);
        while (this.Count < Screen.AllScreens.Length)
        {
            OrangeGuava.Desktop.DesktopWindow.DesktopControl dtc = new OrangeGuava.Desktop.DesktopWindow.DesktopControl();
            User32.SetParent(dtc.Handle, User32.FindWindow("ProgMan", null));
            this.Add(dtc);

        }

        int minx = 0;
        int miny = 0;

        foreach (Screen screen in Screen.AllScreens)
        {               
            if (screen.Bounds.Left < minx) minx = screen.Bounds.Left;
            if (screen.Bounds.Top < miny) miny = screen.Bounds.Top;
        }

        for (int i = Screen.AllScreens.Length; i < Count; i++)
        {
            OrangeGuava.Desktop.DesktopWindow.DesktopControl dtc = (OrangeGuava.Desktop.DesktopWindow.DesktopControl)this[i];
            dtc.Hide();
        }

        for (int i = 0; i < Screen.AllScreens.Length; i++)
        {
            OrangeGuava.Desktop.DesktopWindow.DesktopControl dtc = (OrangeGuava.Desktop.DesktopWindow.DesktopControl)this[i];
            dtc.DeviceId = i.ToString();


            Rectangle r = Screen.AllScreens[i].WorkingArea;
            r.X -= minx;
            r.Y -= miny;



            dtc.SetBounds(r.X, r.Y, r.Width, r.Height);

            dtc.displaySettingsChanged(null, null);


        }

    }


回答2:

I've done this by having my window respond to the WM_WINDOWPOSCHANGING message by setting WINDOWPOS.hWndInsertAfter = HWND_BOTTOM. This says to the OS: make sure my window is underneath all other windows, and makes it appear as though your window is glued to the desktop.