C# – DirectX Desktop

cdirectxwindows

I'd like to make an animated desktop background for Windows 7 using DirectX. I'm using C#, SlimDX and a couple of P/Invoke imports of Windows API functions. I'm not brilliant with native Windows programming, but I've had a poke around online and I believe what I need to do is either:

1) Find the handle of the window containing the dekstop wallpaper, hook it up to a DirectX device and draw into it.

2) Make a new output window, and insert it above the desktop wallpaper but below the desktop icons.

I've tried both these, but neither seems to work. If I navigate the Window heirarchy starting from the handle returned by GetDesktopWindow(), I can go Desktop -> WorkerW -> SHELLDLL_DefView -> SysListView32. If I hook up a DirectX device to this handle, I can draw over the entire desktop, but it also covers the icons. If I create a Windows form, set its parent to SHELLDLL_DefView using SetParent() and then use SetWindowPos to play with its Z-order I can only seem to get it to go either behind the desktop wallpaper or in front of the desktop + icons.

It looks as though the desktop wallpaper is background to the folder view containing the icons, and therefore what I am trying to do cannot work. The only solution then would be to not use the desktop for icons, or to find some alternative, e.g. overwriting the desktop then overlaying a transparent window containing a view of the contents of some folder.

Does anyone have any idea of what I should be doing, or even whether what I want to do is possible? It seems you can draw to the desktop background using the GDI (as I believe the wxSnow program does), and I've seen something similar to what I want done by VLC Media Player under Windows XP with its DirectX wallpaper mode (interestingly, I can't seem to get this option enabled on my system).

Thanks!

Best Answer

Looks like this might not be possible. See this link:

http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/69839cec-3424-4300-9ac3-486b8c2fe492

If you need to draw some controls between the desktop background and desktop icons, an alternative step is below:

  1. Create your user control in a windows control library.
  2. Embed the user control in an ActiveX control.
  3. Embed the ActiveX control in a web page.
  4. Enable active desktop and set the web page to be your desktop background.

This can only be done in XP since Vista doesn’t support active desktop.

Another post there suggests that you could possibly do this with the background of an explorer window - if you could get the handle of the window that constitutes it. Of course, if that's possible then it may be possible also to get the handle of the desktop window behind the icons.

Update: Well, so far the only thing I've found that could possibly "work" is just creating Bitmap files and changing the wallpaper over and over again (I suspect this would be slow, as you mentioned).

That full screen image must be resident in memory somewhere, but there may be no way to access it without some serious low-level memory hacking. I'm going to keep looking.

Update 2: This might work, but I'm not sure:

http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/4af734fb-d2c1-414b-a9f1-759b76692802

The meat of it is this:

HWND p = FindWindow("ProgMan", NULL);
HWND s = FindWindowEx(p, NULL, "SHELLDLL_DefView", NULL);
HWND dtw = FindWindowEx(s, NULL, "SysListView32", NULL);
HDC hdc = GetDC(dtw);

You're basically starting with the ProgMan window and drilling down from there to the desktop wallpaper ("SysListView32", I guess). I'm going to try this out.

Update 3: No go - the above code does get the desktop's DC, but it's above the icons so BitBlt draws over them. It's not drawing to the Screen, though, because I can draw underneath an open form without covering it, so that's progress at least.

I'm guessing that there's some window available other than "SysListView32" that is the desktop behind the icons, or there's more than one "SysListView32" window.

Update 4: I'm pretty sure something using this would work:

http://msdn.microsoft.com/en-us/library/bb761155(v=VS.85).aspx http://msdn.microsoft.com/en-us/library/bb774742(v=VS.85).aspx

Basically, it's an API method that you call, passing in a structure which include a bitmap handle. If the call is successful, that bitmap becomes the desktop.

Does DirectX expose frames as bitmap handles (GDI-compatible), or does it only expose the DC? In my case, my animation is already an array of GDI-compatible bitmaps, so I would have no trouble using this approach. If this is the only route, and DirectX doesn't expose the bitmap handles (and I don't think they would), then for each frame you would have to create a new GDI bitmap, which would slow things down quite a bit.

Actually, there might be an easier way, although I'm not sure it would work. Once you get the handle to the actual bitmap of the wallpaper, you can select it into a device context using SelectObject, and then just use that device context as the BitBlt destination. You might have to send a repaint instruction to the desktop, though, which might trigger the icons to be repainted every time.

How about you do some work here? :)

Related Topic