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窗口全部擁有的窗口一塊兒顯示或者隱藏。
相關文章
相關標籤/搜索