In light of a recent discussion on Meta complaining that questions like this one have "not been properly answered", I'm going to try and give answering this one a whirl. Not to imply that I think meklarian's answer is bad—in fact, far from it. But it's clearly been deemed unsatisfactory, so perhaps I can fill in some of the additional details.
Your problem results from a fairly widespread confusion over what the desktop window actually is. The GetDesktopWindow
function does precisely what it's documented to do: it returns a handle to the desktop window. This, however, is not the same window that contains the desktop icons. That's a completely different window that appeared for the first time in Windows 95. It's actually a ListView
control set to the "Large Icons" view, with the actual desktop window as its parent.
Raymond Chen, a developer on the Windows Shell team provides some additional detail in the following Windows Confidential article: Leftovers from Windows 3.0
[ . . . ] While in Windows 3.0, icons on the desktop represented minimized windows, in Windows 95, the desktop acted as an icon container.
The Windows 95 desktop was actually a window created by Explorer that covered your screen (but sat beneath all the other windows on your desktop). That was the window that displayed your icons. There was still a window manager desktop window beneath that (the window you get if you call GetDesktopWindow), but you never saw it because it was covered by the Windows 95 desktop—the same way that the wood paneling in the basement of my colleague’s house covered the original wall and the time capsule behind the wall.
[ . . . ]
This desktop design has remained largely unchanged since its introduction in Windows 95. On a typical machine, the original desktop is still there, but it’s completely covered by the Explorer desktop.
In summary, then, the window returned by the GetDesktopWindow
function is the actual desktop window, the only one we had way back in Windows 3.0. The Explorer desktop (the one that contains all your icons) is merely another window sitting on top of the desktop window (although one that completely covers the original) that wasn't added until Windows 95.
If you want to get a handle to the Explorer desktop window, you need to do some additional work beyond simply calling the GetDesktopWindow
function. In particular, you need to traverse the child windows of the actual desktop window to find the one that Explorer uses to display icons. Do this by calling the FindWindowEx
function to get each window in the hierarchy until you get to the one that you want. It has a class name of SysListView32
. You'll also probably want to use the GetShellWindow
function, which returns a handle to the Shell's desktop window, to help get you started.
The code might look like this (warning: this code is untested, and I don't recommend using it anyway!):
HWND hShellWnd = GetShellWindow();
HWND hDefView = FindWindowEx(hShellWnd, NULL, _T("SHELLDLL_DefView"), NULL);
HWND folderView = FindWindowEx(hDefView, NULL, _T("SysListView32"), NULL);
return folderView;
I noted there that I don't actually recommend using that code. Why not? Because in almost every case that you want to get a handle to the desktop window (either the actual desktop window, or the Explorer desktop), you're doing something wrong.
This isn't how you're supposed to interact with the desktop window. In fact, you're not really supposed to interact with it at all! Remember how you learned when you were a child that you're not supposed to play with things that belong to other people without their permission? Well, the desktop belongs to Windows (more specifically, to the Shell), and it hasn't given you permission to play with its toys! And like any good child, the Shell is subject to throwing a fit when you try to play with its toys without asking.
The same Raymond Chen has published another article on his blog that details a very specific case, entitled What's so special about the desktop window?
Beyond the example he gives, this is fundamentally not the way to do UI automation. It's simply too fragile, too problematic, and too subject to breaking on future versions of Windows. Instead, define what it is that you're actually trying to accomplish, and then search for the function that enables you to do that.
If such a function does not exist, the lesson to be learned is not that Microsoft simply wants to make life harder for developers. But rather that you aren't supposed to be doing that in the first place.