2024年5月10日发(作者:)

MFC子窗口和父窗口(SetParent, SetOwner)

一、概念和区别

在windows系统中,每个窗口对象都对应有一个数据结构,形成一个list链表。系统

的窗口管理器通过这个list来获取窗口信息和管理每个窗口。这个数据结构中有四个数据

用来构建list,即child、sibling、parent、owner四个域。

所以我们可以看到,窗口之间的关系有两种:owner-owned 关系和 parent-child

关系。前者称之为拥有/被拥有关系,后者称之为父/子关系。在这篇文字中,我把owner

窗口称之所有者窗口。换句话说,一个窗口在有一个父窗口(parent)的同时,还可能被不

同的窗口拥有(owner),也可以有自己的子窗口(child)。在MFC 的CWnd类中,所有者

窗口保存在m_hWndOwner成员变量中,父窗口则保存在m_hParent中,但是这两个值

并不一定和窗口对象数据结构中的值相对应。

窗口之间的关系,决定了窗口的外在表现。比如显示、销毁等。

如果一个窗口数据的owner域非NULL,则它和该窗口建立了owner-owned 关系,

拥有关系决定了:

(1)被拥有的窗口永远显示在拥有它的那个窗口的前面;

(2)当所有者窗口最小化的时候,它所拥有的窗口都会被隐藏;

(3)当所有者窗口被销毁的时候,它所拥有的窗口都会被销毁。

需要注意的是,隐藏所有者窗口并不会影响它所拥有的窗口的可见状态。比如:如果

窗口 A 拥有窗口B,窗口B拥有窗口C,则当窗口A最小化的时候,窗口B被隐藏,但是窗

口 C还是可见。

如果一个窗口的parent域非NULL,则它和该窗口之间就建立了parent-child关系。

父子决定了:

(1)窗口在屏幕上面的显示位置。父窗口提供了用来定位子窗口的坐标系统,一个子

窗口只能显示在它的父窗口的客户区中,之外的部分将被裁减。这个裁减法则决定了如果

父窗口不可见,则子窗口肯定不可见。如果父窗口移动到了屏幕之外,子窗口也一样。

(2)当父窗口被隐藏时,它的所有子窗口也被隐藏。

(3)父窗口被销毁的时候,它所拥有的子窗口都会被销毁。

注意!最小化父窗口不会影响子窗口的可见状态,子窗口会随着父窗口被最小化,但

是它的WS_VISIBLE属性不会变。

Windows系统为什么要使用两种关系呢?这是为了更加灵活的管理窗口。举个例子:

组合框(combobox)的下拉列表框(list box)可以超出组合框的父窗口的客户区,这样

有利于显示,因此系统创建该list box的时候,是作为控制台窗口(desktop window)

的子窗口,它的父窗口hWndParent是NULL,这样,list box的显示区域是限制在整个

屏幕内,但是该list box的所有者却是组合框的第一个非子窗口祖先(比如对话框),当它

的所有者窗口销毁后,该 list box自动销毁。