Win32窗口的Owner和Parent有什么区别?

56

在Win32编程中,一个窗口的父窗口和一个窗口的所有者之间有什么区别?我以为我已经理解了,然后我看到了这段代码:

SetWindowLong(handle, GWL_HWNDPARENT, foo);

实际上,这设置的是窗口的所有者而不是父窗口 - 尽管使用了GWL_HWNDPARENT。 父/所有者这些术语是否可以互换,或者它们之间实际上存在区别?


完整解释请参见 msdn - Danra
Raymond Chen 写了一篇关于“窗口可以有父窗口或所有者,但不能同时拥有两者”的文章。链接 - Uli Gerhardt
雷蒙德·陈(Raymond Chen)文章的更新URL: https://devblogs.microsoft.com/oldnewthing/20100315-00/?p=14613 - Darrin Cullop
请取消当前已接受的答案。它是不正确的。 - IInspectable
4个回答

30

所有权是两个顶级窗口之间的关系,而父子关系则是指顶级窗口和WS_CHILD之间的关系,或者是WS_CHILD和另一个WS_CHILD之间的关系。

按钮的父级是其所在的表单,而消息框由显示它的表单拥有。

阅读微软的这篇文章《Win32窗口层次和样式》,可以更加清晰地了解所有权、父子关系、ZOrder、SetWindowLong、GetWindow以及创建窗口关系的Win32 API的所有其他棘手细节。

编辑:看起来微软已经删除了该内容,这里有另一份所有权/父子关系总结


4
啊,微软已经将那个内容下架了。:( - Dave Markle
6
http://web.archive.org/web/20100318062734/http://msdn.microsoft.com/en-us/library/ms997562.aspx - rtxndr

20

Owner(所有者)是一个控件或对话框的 Window*,负责创建/销毁窗口等操作。

Parent(父级)是与一个控件或对话框在窗口链中相邻且比其高级的窗口,但并不实际负责该控件或对话框(不一定关心其生命周期等)。 一个窗口的父级也可以是它的所有者。

*Window vs window:Window 是屏幕上显示的实际窗口;window 是任何具有 HWND 的对象(包括按钮、面板等)。


4
谢谢你提供有关“窗户 vs 窗口”的提示,有时与他人讨论这些事情时会有些混淆。我将确保翻译准确且易于理解,但不会改变原意。 - Jon Tackabury
38
这不正确。一个窗口可以有一个父窗口或拥有者,但不能同时拥有两者。 - Raymond Chen
4
Raymond,我认为混淆的一部分在于 Spy++ 和 GetAncestor(GA_PARENT) 即使对于顶层的 owned HWNDs 也会返回一个“在 HWND 树中向上一级的下一个窗口”,因此俗语地说,它们有一个“父窗口”,即使内部并没有以这种方式跟踪。实际上,HWND 树有两种基本看法:朴素的“以桌面为根的单一树形结构”视图,可以在 Spy++ / GetAncestor / EnumChildWindows / GetWindow(GA_FIRST/NEXT) 中看到;还有一种“内部导向”视图,其中每个 HWND 都有一个单独的插槽,取决于 WS_CHILD,可以是父或所有者。 - BrendanMcK
6
是的。不幸的是,人们往往在术语上比较马虎,这只会加剧混乱。(而且在内部实际上有两个插槽,但 API 设计是“聪明”的,它将它们作为一个参数公开,根据上下文选择两个插槽之一。) - Raymond Chen

1

Chen的博客文章是值得一读的。对我来说关键点是子窗口必须使用WS_CHILD样式。您可以尝试创建一个子窗口并将父句柄传递给CreateWindow(),但如果没有设置WS_CHILD样式,则两个窗口将具有所有者关系,而不是父/子关系。


0

这很简单:代码有问题,故事就到此为止了。

是的,某些窗口可能会对这样的调用做出积极反应 - 某些不知道更好的人可能已经实现了对它的支持。根据文档(而且这是旧的文档)- 您不能使用GWL_HWNDPARENT索引调用SetWindowLong来更改子窗口的父级。而是使用SetParent函数。

所以,一切都很简单:你遇到了有缺陷的代码,将其更改为SetParent或重构为其他操作,然后继续前进?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接