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?
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);
}
}
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.