我如何获得桌面的窗口句柄?

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

但我用Spy ++进行了testing,发现桌面的窗口句柄和“Windows桌面”的窗口句柄是不一样的。

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

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

一旦我得到窗口句柄,我想使用SendMessage()进行操作,如获取选定的文件名,select的文件数量等。

请给出你的意见。 我正在使用Windows SDk来做这件事

鉴于最近关于Meta抱怨的讨论 ,像这样的问题“没有得到妥善的回答”,我会试着回答这个问题。 不是暗示我认为麦克拉里安的答案是不好的,实际上是从它那里得到的。 但显然这被认为是不令人满意的,所以也许我可以填写一些额外的细节。

您的问题是由于对桌面窗口的实际情况相当普遍的混淆造成的。 GetDesktopWindow函数 正是它所做的记录:它返回桌面窗口的句柄。 但是,这与包含桌面图标的窗口不同。 这是第一次在Windows 95中出现的完全不同的窗口。它实际上是一个ListView控件设置为“大图标”视图,实际的桌面窗口作为其父项。

Windows Shell团队的开发人员Raymond Chen在下面的Windows机密文章中提供了一些额外的细节: 来自Windows 3.0的剩菜

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

Windows 95桌面实际上是由资源管理器创建的一个窗口,覆盖了您的屏幕(但位于桌面上所有其他窗口的下方)。 那是显示你的图标的窗口。 窗口下面还有一个窗口管理器桌面窗口(如果你打电话给GetDesktopWindow,你会得到一个窗口),但是你从来没有看到它,因为它被Windows 95的桌面覆盖 – 就像我同事家的地下室里的木板一样覆盖了原来的墙壁和墙后的时间胶囊。

[ ]

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

总而言之, GetDesktopWindow函数返回的窗口就是实际的桌面窗口,这是我们在Windows 3.0中唯一的返回窗口。 资源管理器桌面(包含所有图标的桌面)仅仅是桌面窗口顶部的另一个窗口(尽管完全覆盖了原来的窗口),直到Windows 95才被添加。

如果你想获得Explorer桌面窗口的句柄,除了调用GetDesktopWindow函数之外,还需要做一些额外的工作。 特别是,您需要遍历实际桌面窗口的子窗口,以查找Explorer用于显示图标的窗口。 通过调用FindWindowEx函数来获取层次结构中的每个窗口,直到找到所需的窗口。 它有一个类名为SysListView32 您也可能想要使用GetShellWindow函数 ,该函数返回Shell的桌面窗口句柄,以帮助您开始。

代码可能看起来像这样(警告:这个代码是未经测试的,我不推荐使用它!):

 HWND hShellWnd = GetShellWindow(); HWND hDefView = FindWindowEx(hShellWnd, NULL, _T("SHELLDLL_DefView"), NULL); HWND folderView = FindWindowEx(hDefView, NULL, _T("SysListView32"), NULL); return folderView; 

我在那里注意到,我实际上并不推荐使用该代码。 为什么不? 因为在几乎所有的情况下,你想要得到一个桌面窗口 (无论是实际的桌面窗口,或资源管理器桌面) 的句柄你做错了什么。

这不是你应该如何与桌面窗口交互。 事实上,你根本不应该与它互动! 还记得你小时候学过的东西,你不应该在没有得到他人同意的情况下玩弄属于他人的东西吗? 那么,桌面属于Windows(更具体地说就是“壳牌”),它并没有授权你玩玩具! 就像任何一个好孩子一样,当你试图玩弄玩具而不问。

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

除了他给出的例子之外,这从根本上不是UI自动化的方式。 它太脆弱了,太麻烦了,而且在未来的Windows版本上也会受到影响。 相反,定义你实际上想要完成的是什么,然后搜索使你能够完成的功能。

如果这样的功能不存在,那么要吸取的教训并不是微软只是想让开发人员更加难过。 但是,首先你不应该这样做

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

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

编辑(附加信息)

如果你正在寻找交互或放置在实际的外壳桌面上,你可能会更好地服务于其他的API。 这里有两个这样的API可以完成这个,取决于目标版本的Windows。

Windows边栏@ MSDN
这在Vista和Windows 7上可用

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