Win32-子窗口-父窗口-窗口所有者

34 篇文章 1 订阅
本文详细阐述了Windows系统中窗口之间的owner-owned和parent-child关系,包括窗口显示位置、隐藏与销毁行为。窗口类型如桌面窗口、WS_OVERLAPPED、WS_POPUP和WS_CHILD各有特点和限制。此外,讨论了相关函数如GetWindow和SetParent的使用,并强调了线程一致性的重要性。
摘要由CSDN通过智能技术生成


  在windows系统中,每个窗口对象都对应有一个数据结构,形成一个list链表。系统的窗口管理器通过这个list来获取窗口信息和管理每个窗口。这个数据结构中有四个数据用来构建list,即child、sibling、parent、owner四个域。

1.窗口关系

  窗口之间的关系有两种: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属性不会变。

2.窗口类型的说明和限制

  (1)控制台窗口(desktop window)。这是系统最早创建的窗口。可以认为它是所有 WS_OVERLAPPED 类型窗口的所有者和父窗口。
  (2)WS_OVERLAPPED类型的窗口可以显示在屏幕的任何地方。它们的所有者窗口是控制台。 当系统 shuts down的时候,它将销毁所有overlapped类型的窗口。
  (3)WS_POPUP类型的窗口可以显示在屏幕任何地方,它们一般没有父窗口,但是如果明确调用SetParent,这类窗口也可以有父窗口。 WS_POPUP类型的窗口的所有者是在CreateWindow函数中通过设置hWndParent参数给定的,如果hWndParent不是子窗口,则该窗口就成为这个新的弹出式窗口的owner,否则,系统从hWndParent的父窗口向上找,直到找到第一个非子窗口,把它作为该弹出窗口的owner。当owner窗口销毁的时候,系统自动销毁这个弹出窗口。
  (4)所有者窗口(owner)只能是 overlapped 或者 pop-up 类型的窗口,子窗口不能是所有者窗口,也就是说子窗口不能拥有其它窗口。overlapped 或者 pop-up 类型的窗口在拥有其它窗口的同时,也可以被拥有。在使用CreateWindowEx创建 WS_OVERLAPPED 或者 WS_POPUP类型的窗口时,可以在 hwndParent 参数中给出它的所有者窗口的句柄。如果 hwndParent 给出的是一个child 类型的窗口句柄,则系统自动将新创建窗口的所有权交给该子窗口的顶级父窗口。 在这种情况下,参数hwndParent被保存在新建窗口的parent域中,而它的所有者窗口句柄则保存在owner域中。
  (5)缺省情况下,对话框和消息框属于 owned 窗口,除非在创建它们的时候明确给出了WS_CHILD属性,(比如对话框中嵌入对话框的情形)否则由系统负责给它们指定owner窗口。需要注意的是,一旦创建了owned类型的窗口,就无法再改变其所有关系,因为WIN32没有没有提供改变窗口所有者的方法。 而且在Win32中,由于有多线程的存在,所以要注意保证父子窗口或者owner/owned 窗口要同属于一个线程。
  (6)对于 WS_CHILD类型的窗口,它的父窗口就是它的所有者窗口。 一个子窗口的父窗口也是在CreateWindow函数中用hWndParent参数指定的。子窗口只能在父窗口的客户区中显示,并随父窗口一起销毁。

3.几个相关函数的说明

  GetWindow(hWnd, GW_OWNER)永远返回窗口的所有者(owner)。
  对于SetParent,msdn里面说明了父子窗口必须是同一个进程的。但是由于窗口句柄是系统全局唯一的,不属于同一个进程的情况下,也可以成功调用,但是后果未知。GetParent的返回值比较复杂,对于overlapped类型的窗口,它返回0,对于WS_CHILD类型,它返回其父窗口,对于WS_POPUP类型,它返回其所有者窗口,如果想得到创建它时所传递进去的那个hwndParent参数,应该用GetWindowWord(GWW_HWNDPARENT)函数。
  GetWindowWord(hWnd, GWW_HWNDPARENT)返回一个窗口的父窗口,如果没有,则返回其所有者。

4.作者答疑

  如有疑问,敬请留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值