windows 如何获取桌面的窗口句柄?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1669111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:22:46  来源:igfitidea点击:

How do I get the window handle of the desktop?

c++windowswinapishelldesktop

提问by Sujay Ghosh

The Windows API provides an API GetDesktopWindow( )which returns the window handle

Windows API 提供了一个 API GetDesktopWindow(),它返回窗口句柄

But I tested with Spy++ and I find that the window handle of the desktop and the window handle of the "Windows Desktop" is not the same.

但是我用Spy++测试发现桌面的窗口句柄和“Windows桌面”的窗口句柄不一样。

As the "Windows Desktop" is a list view, do I need to do the following

由于“Windows 桌面”是列表视图,我是否需要执行以下操作

1) HANDLE hWnd = GetDesktopWindow() ;
2) FindWindow(hWnd, ..... ) with the SyslistView32 as the Window class.

Once I get the Window handle, I want to use SendMessage() for operations like getting selected file name, the number of files selected , etc.

获得 Window 句柄后,我想使用 SendMessage() 进行诸如获取所选文件名、所选文件数等操作。

Please give your opinions. I am doing this using the Windows SDk

请发表您的意见。我正在使用 Windows SDk 执行此操作

回答by Cody Gray

In light of a recent discussion on Metacomplaining 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 answeris bad—in fact, far from it. But it's clearly been deemed unsatisfactory, so perhaps I can fill in some of the additional details.

鉴于最近关于 Meta 的讨论抱怨像这样的问题“没有得到正确回答”,我将尝试回答这个问题。并不是暗示我认为meklarian 的回答不好——事实上,远非如此。但它显然被认为不令人满意,所以也许我可以补充一些额外的细节。

Your problem results from a fairly widespread confusion over what the desktop window actually is. The GetDesktopWindowfunctiondoes preciselywhat 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 ListViewcontrol set to the "Large Icons" view, with the actual desktop window as its parent.

您的问题是由于对桌面窗口的实际含义相当广泛的混淆造成的。该GetDesktopWindow功能确实恰恰就是它的文档做的事:它返回一个句柄到桌面窗口。然而,这不是包含桌面图标的同一个窗口。这是一个完全不同的窗口,第一次出现在 Windows 95 中。它实际上是一个ListView设置为“大图标”视图的控件,以实际的桌面窗口作为其父窗口。

Raymond Chen, a developer on the Windows Shell team provides some additional detail in the following Windows Confidential article: Leftovers from Windows 3.0

Windows Shell 团队的开发人员 Raymond Chen 在以下 Windows 机密文章中提供了一些其他详细信息: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 Get-Desktop-Window), 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.

[ . . . ]  在 Windows 3.0 中,桌面上的图标代表最小化的窗口,而在 Windows 95 中,桌面充当图标容器。

Windows 95 桌面实际上是由资源管理器创建的一个窗口,它覆盖了您的屏幕(但位于桌面上所有其他窗口的下方)。那是显示您的图标的窗口。在它下面仍然有一个窗口管理器桌面窗口(如果你调用 Get-Desktop-Window 就会得到这个窗口),但是你从来没有看到它,因为它被 Windows 95 桌面覆盖——就像地下室的木镶板一样我同事的房子覆盖了原来的墙和墙后的时间胶囊。

[ . . . ]

这种桌面设计自从在 Windows 95 中引入以来基本保持不变。在典型的机器上,原始桌面仍然存在,但它完全被 Explorer 桌面覆盖。

In summary, then, the window returned by the GetDesktopWindowfunction is the actualdesktop 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.

总之,该GetDesktopWindow函数返回的窗口是实际的桌面窗口,这是我们在 Windows 3.0 中唯一可用的窗口。资源管理器桌面(包含所有图标的桌面)只是位于桌面窗口(尽管完全覆盖原始窗口)顶部的另一个窗口,直到 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 GetDesktopWindowfunction. In particular, you need to traverse the child windows of the actualdesktop window to find the one that Explorer uses to display icons. Do this by calling the FindWindowExfunctionto 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 GetShellWindowfunction, which returns a handle to the Shell's desktop window, to help get you started.

如果您想获得资源管理器桌面窗口的句柄,除了简单地调用该GetDesktopWindow函数之外,您还需要做一些额外的工作。特别是需要遍历实际桌面窗口的子窗口,才能找到资源管理器用来显示图标的那个。为此,请调用FindWindowEx函数获取层次结构中的每个窗口,直到找到所需的窗口。它的类名是SysListView32. 您可能还想使用返回 Shell 桌面窗口句柄的GetShellWindow函数来帮助您入门。

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 actualdesktop 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.

这不是您应该与桌面窗口交互的方式。事实上,你根本不应该与它互动!还记得您小时候是如何学会未经他人许可不得玩弄属于他人的东西的吗?嗯,桌面属于 Windows(更具体地说,属于 Shell),它没有给你玩它的玩具的许可!就像任何一个好孩子一样,当您试图不经询问就玩它的玩具时,Shell 可能会感到不适。

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?

同一个 Raymond Chen 在他的博客上发表了另一篇文章,详细介绍了一个非常具体的案例,题为桌面窗口有什么特别之处?

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.

除了他给出的例子之外,这从根本上不是进行 UI 自动化的方式。它太脆弱,太有问题,而且太容易在未来版本的 Windows 上崩溃。相反,定义您实际尝试完成的任务,然后搜索使您能够做到这一点的功能。

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 thatin the first place.

如果这样的功能不存在,那么要吸取的教训不是微软只是想让开发人员的日子过得更艰难。而是说你一开始就不应该这样做

回答by meklarian

If you want the Desktop window as defined in GetDesktopWindow(), use that window handle. This is the window handle you should use to look for top-level windows and other related activities.

如果您想要在 GetDesktopWindow() 中定义的桌面窗口,请使用该窗口句柄。这是您应该用来查找顶级窗口和其他相关活动的窗口句柄。

What you're seeing in Spy++ is just the content drawn as the desktop in your session. If you use the auto-locate in Spy++, you'll see that the SysListView32-declared window is a child window of your explorer shell. It is quite infrequent for someone to need access to this window. Also, the existence of this window may be subject to changes between versions of windows.

您在 Spy++ 中看到的只是会话中作为桌面绘制的内容。如果您在 Spy++ 中使用自动定位,您将看到 SysListView32 声明的窗口是您的资源管理器外壳的子窗口。很少有人需要访问此窗口。此外,此窗口的存在可能会因窗口版本之间的变化而变化。

Edit (additional info)

编辑(附加信息)

If you are looking to interact or place things on the actual shell desktop, you may be better served by other APIs. Here are two such APIs that can accomplish this, depending on the target version of windows.

如果您希望在实际的 shell 桌面上进行交互或放置东西,其他 API 可能会更好地为您服务。这里有两个这样的 API 可以实现这一点,具体取决于 Windows 的目标版本。

Windows Sidebar @ MSDN
This is available on Vista and Windows 7

Windows Sidebar @ MSDN
这在 Vista 和 Windows 7 上可用

Using the Active Desktop @ MSDN
This is available on Windows 2000 and XP, although frequently disabled by users and sysadmins.

使用 Active Desktop @ MSDN
这在 Windows 2000 和 XP 上可用,但经常被用户和系统管理员禁用。