What's so special about the desktop window? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20040224-00/?p=40493
Raymond Chen 2004年02月24日
简介
桌面窗口在 Windows 编程中具有特殊的地位,因为它代表整个桌面环境。滥用桌面窗口句柄(例如,将其作为模态对话框的所有者或父窗口)可能导致系统级别的问题,如禁用所有窗口,从而导致系统挂起。在没有可用窗口句柄的情况下,应传递 NULL 作为父窗口句柄,这通常意味着创建一个无主窗口,或者在 Shell 中表示不显示用户界面。然而,这种做法在多窗口环境中仍需谨慎,以避免潜在的模态问题和用户体验上的混乱。
正文
由 GetDesktopWindow() 得到的窗口句柄非常特殊,我经常看到人们在各种地方滥用它。
例如,Shell 中的许多函数接受一个窗口句柄参数,以防需要显示用户界面。例如 IShellFolder::EnumObjects。如果你传递 GetDesktopWindow(),会发生什么?
如果确实需要显示用户界面,你将挂起系统。
为什么?
- 模态对话框会禁用其所有者。
- 每个窗口都是桌面的子窗口。
- 当一个窗口被禁用时,其所有子窗口也会被禁用。
将这些放在一起:如果模态对话框的所有者是桌面,那么桌面就会被禁用,这会禁用其所有子窗口。换句话说,它会禁用系统中的每个窗口。甚至是你正试图显示的那个!
你也不想将 GetDesktopWindow() 作为你的 hwndParent 传递。如果你创建一个其父窗口为 GetDesktopWindow() 的子窗口,你的窗口现在就粘在了桌面窗口上。如果你的窗口随后调用了像 MessageBox() 这样的东西,那么这是一个模态对话框,那么上述规则就会生效,桌面被禁用,机器就完蛋了。
所以如果你没有窗口,你应该传递哪个窗口?
传递 NULL。
对于窗口管理器来说,NULL 的父窗口意味着“创建一个没有所有者的窗口”。对于 Shell 来说,NULL 的 UI 窗口通常意味着“不显示 UI”,这很可能是你本来就想要的。
不过要小心:如果你的线程确实有一个顶层无主窗口,那么模态地创建第二个这样的窗口,如果用户切换到并交互第一个窗口,将会造成很大的混乱。如果你有一个窗口,那么请使用它。