Windows系统中owner-owned 关系和 parent-child关系

1、概念

  • 在windows系统中,每一个窗口对象都对应有一个数据结构,造成一个list链表。系统的窗口管理器经过这个list来获取窗口信息和管理每一个窗口。这个数据结构中有四个数据用来构建list,即child、sibling、parent、owner四个域。
  • 因此咱们能够看到,窗口之间的关系有两种:owner-owned 关系parent-child关系。前者称之为拥有/被拥有关系,后者称之为父/子关系。
  • 窗口之间的关系,决定了窗口的外在表现。好比显示、销毁等。
  • 若是一个窗口数据的owner域(m_hWndOwner)非NULL,则它和该窗口创建了owner-owned 关系,拥有关系决定了:windows

    • 被拥有的窗口永远显示在拥有它的那个窗口的前面;
    • 当全部者窗口最小化的时候,它所拥有的窗口都会被隐藏;
    • 当全部者窗口被销毁的时候,它所拥有的窗口都会被销毁。
  • 注意!最小化全部者窗口并不会影响它所拥有的窗口的可见状态
  • 若是一个窗口的parent域(m_hParent)非NULL,则它和该窗口之间就创建了parent-child关系。父子关系决定了:数据结构

    • 窗口在屏幕上面的显示位置。父窗口提供了用来定位子窗口的坐标系统,一个子窗口只能显示在它的父窗口的客户区中,以外的部分将被裁减。
    • 当父窗口被最小化时,它的全部子窗口也都被隐藏。
    • 当父窗口被销毁的时候,它所拥有的子窗口也都会被销毁。
  • 注意!最小化父窗口不会影响子窗口的可见状态,子窗口会随着父窗口被最小化,可是它的WS_VISIBLE属性不会变
  • Windows系统使用两种关系是为了更加灵活的管理窗口。父窗口会限制子窗口显示区域,而拥有者窗口则不会限制被拥有窗口显示区域。这是他们最大的区别。
  • 另外,窗口之间消息的传递也和窗口关系有关,一般,一个窗口会把本身的通知消息发送给它的父窗口,但不全是这样,这样窗口之间的消息传递也能够灵活控制。

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

  • 控制台窗口(desktop window)。这是系统最先建立的窗口。能够认为它是全部WS_OVERLAPPED类型窗口的全部者和父窗口。当系统初始化的时候,它首先建立控制台窗口,大小覆盖整个屏幕。全部其它窗口都在这个控制台窗口上面显示。窗口管理器所用的窗口list中第一个就是这个控制台。它的下一层窗口叫作顶级窗口(top-level),顶级窗口是指全部非child窗口、没有父窗口,或者父窗口是desktop的窗口,它们没有WS_CHILD属性。
  • WS_OVERLAPPED类型的窗口能够显示在屏幕的任何地方。它的全部者窗口是控制台。Overlapped的窗口属于顶级窗口,通常做为应用程序的主窗口。不管是否给出了WS_CAPTION、WS_BORDER属性,这类窗口建立后都有标题栏和边框。全部overlapped窗口都有WS_CLIPSIBLINGS属性。当系统关闭的时候,它将销毁全部overlapped类型的窗口。
  • WS_POPUP类型的窗口能够显示在屏幕任何地方,通常没有父窗口,可是若是明确调用SetParent,这类窗口也能够有父窗口。和WS_OVERLAPPED类型的窗口相似,WS_POPUP类型的窗口的全部者是在CreateWindow或者CreateWindowEx函数中经过设置hWndParent参数给定的,若是hWndParent不是子窗口,则该窗口就成为这个新的弹出式窗口的owner,不然,系统从hWndParent的父窗口向上找,直到找到第一个非子窗口,把它做为该弹出窗口的owner。在这种状况下,参数hwndParent被保存在新建窗口的parent域中,而它的全部者窗口句柄则保存在owner域中。当owner窗口销毁的时候,系统自动销毁这个弹出窗口。
  • WS_POPUP类型的窗口也属于顶级窗口,它和WS_OVERLAPPED窗口的主要区别是WS_POPUP窗口不须要有标题栏,也没必要有边框。
  • 全部者窗口只能是WS_OVERLAPPED或者WS_POPUP类型的窗口,子窗口不能是全部者窗口,而且全部者窗口也能够被拥有。
  • 缺省状况下,对话框和消息框属于owned窗口,除非在建立它们的时候明确给出了WS_CHILD属性,(好比对话框中嵌入对话框的情形)不然由系统负责给它们指定owner窗口。须要注意的是,一旦建立了owned类型的窗口,就没法再改变其全部关系,由于Win32没有没有提供改变窗口全部者的方法。并且在Win32中,因为有多线程的存在,因此要注意保证parent-child窗口或者owner-owned窗口要同属于一个线程。
  • WS_CHILD类型的窗口的父窗口就是它的全部者窗口。一个子窗口的父窗口也是在CreateWindow函数中用hWndParent参数指定的。子窗口只能在父窗口的客户区中显示,并随父窗口一块儿销毁。子窗口必须有一个父窗口,这是它和WS_OVERLAPPED以及WS_POPUP窗口之间的主要区别。父窗口能够是顶级窗口,也能够是其它子窗口。

3、几个相关函数的说明

  • 获取全部者窗口GetWindow(hWnd, GW_OWNER)永远返回窗口的全部者(owner)。对于子窗口,函数返回NULL,由于Windows系统没有维护子窗口的全部者信息。
  • 获取/设置父窗口,Win32 API给出了函数GetParent和SetParent。对于SetParent,msdn里面说明了父子窗口必须是同一个进程的。可是因为窗口句柄是系统全局惟一的,不属于同一个进程的状况下,也能够成功调用,可是后果未知。GetParent的返回值比较复杂,对于WS_OVERLAPPED类型的窗口,它返回0,对于WS_CHILD类型,它返回其父窗口,对于WS_POPUP类型,它返回其全部者窗口。
  • GetWindowWord(hWnd, GWW_HWNDPARENT)返回一个窗口的父窗口,若是没有,则返回其全部者。
  • ShowOwnedPopups(hWnd,fShow)函数能够将owner窗口全部拥有的窗口一块儿显示或者隐藏。
相关文章
相关标签/搜索