日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Window 窗口层次关系

發布時間:2025/3/12 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Window 窗口层次关系 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
相信在Window 下面編程的很多兄弟們都不是很清楚Window 中窗口的層次關系是怎么樣的,這個東西很久已經研究過一下,后來又忘記了,今天又一次遇到了這個問題,所以便整理一下。下面就說說Window 中桌面(Deskkop)以及頂層窗口,以及子窗口之間的關系。

??????????? 在Window 的圖形界面下,最基本顯示信息的元素就是窗口,每一個Window 窗口都管理著自己與其他窗口之間的關系和自身的一些信息,如:是否可見,窗口的所有者,窗口的父/子關系等等信息,當窗口創建、銷毀、顯示的時候,就會用到這些信息。

??????????? 在每一個窗口實例中,有四個元素被窗口管理器用來建立窗口管理鏈表。

  • Child : 指向窗口子窗口的句柄
  • Parent: 指向窗口父窗口的句柄
  • Owner: 指向窗口所有者的句柄
  • Next: 指向下一個同屬窗口的句柄

眾所周知當Window 初始化的時候,它創建桌面這個窗口,桌面覆蓋著整個窗口,窗口管理器用這個窗口作為窗口鏈表中第一個元素。因此桌面在窗口的層次關系中在最上層。

在窗口層次關系中,桌面窗口下一層窗口叫做頂層窗口,頂層窗口就是那些不是子窗口的窗口,頂層窗口不能夠有WS_CHILD 屬性。窗口管理器是如何把桌面窗口和頂層窗口聯系起來的呢?窗口管理器把頂層窗口都組織到一個鏈表中,而這個鏈表的頭存儲的就是桌面窗口的子窗口句柄,每一個子窗口通過Next 就可以找到鏈表中下一個窗口了。這個鏈表被稱為子窗口鏈表,在同一個子窗口鏈表中的窗口是互為同屬窗口,所有頂層窗口都是同屬窗口。窗口在子窗口鏈表中的次序,也表明了窗口距離距離桌面窗口的距離。頂層窗口所形成的子窗口鏈表構成了一個Z? 軸,窗口管理器就是根據Z 序列來覺得窗口的哪一部分是顯示的,哪一部分是被遮蓋的。

所有頂層窗口的父窗口都是指向桌面窗口的,這樣一來頂層窗口就好像是桌面窗口的子窗口,所有頂層窗口構成的鏈表是桌面窗口的子窗口鏈表。當頂層窗口創建的時候,窗口管理器把頂層窗口放在Z 軸的頂上,這樣使得整個窗口可見,窗口管理器把窗口插入到桌面窗口子窗口鏈表的前面。WS_EX_TOPMOST 這個屬性控制著窗口管理器創建頂層窗口,窗口管理器把沒有WS_EX_TOPMOST 屬性的窗口放在具有WS_EX_TOPMOST 屬性的窗口的后面,這樣就使得具有WS_EX_TOPMOST 屬性的窗口一直顯示在前面。

在頂層窗口之間還有另外一直關系,擁有或者屬于其他的頂層窗口,屬于其他窗口的窗口叫做歸屬窗口,擁有其他窗口叫做宿主窗口,在Z 軸中,歸屬窗口一定在他的宿主窗口的前面,如果一個宿主窗口最小化,那么歸屬他的窗口會隱藏掉,如果宿主窗口隱藏起來,歸屬他的窗口不會被隱藏掉。如果有三個窗口A、B、C ,A 擁有 B,B 擁有 C ,如果A 最小化,那么B 會隱藏,但是 C 還是可見的。怎么才能夠在窗口之間建立所有關系呢?方法是在調用CreateWindow或者CreateWindowEx 創建窗口的時候,指定hwndParent 參數。

桌面窗口是在窗口層次中的第一層,頂層窗口在窗口層次中的第二層,子窗口也就是那些創建的時候指定了WS_CHILD? 屬性的窗口占據了窗口層次的其他層。窗口和子窗口之間的聯系,就像桌面窗口和頂層窗口之間的關系一樣。

子窗口顯示在其父窗口的客戶區域,所有同一個窗口的子窗口同樣建立一個Z 軸,這個和頂層窗口是類似的,頂層窗口也是顯示在其父窗口――桌面窗口的客戶區域。

16 位和32 位窗口系統的區別

窗口之間的父子關系、歸屬所有關系、以及根據 Z 軸來顯示的這些規則在16 位和32 位窗口系統中都是相同的。這樣可以是在兩種窗口系統中高度的兼容。兩種窗口系統的區別在于安全和多線程。

??????????? Window Nt 在原有的窗口層次關系中多增加了一層,每一個運行著Window NT 的系統中都有一個Window 工作站對象,這個對象是安全對象的第一層,是所有用戶安全對象的繼承之源,每一個Window 工作站對象可以擁有一些桌面對象,每一個桌面都擁有上面描述的那樣的窗口關系。Window Nt 用了兩個桌面窗口對象,一個是用來處理登陸界面、屏蔽、鎖住工作站等,一個是我們登陸之后進來操作的窗口了。J 通常用戶是不能夠創建和刪除桌面的,不過那是通常,實際上在Window 下面也可以實現類似 Linux 中的多個桌面的效果,每一個桌面都是一個獨立的世界。

兩種窗口系統還有兩位一個區別,在16 位窗口系統中不支持多線程,所以應用程序開發者在創建窗口的時候不必考慮線程的問題了。而在32 位窗口系統中由于又支持了窗口的父子關系,歸屬與擁有關系,同一個窗口下面的所有線程都擁有相同的一個輸入隊列,應用程序開發者應該明白輸入隊列是共享的,在同一個時刻只能有一個線程處理消息,其他的線程都在等待輸入隊列一直到GetMessage 或者PeekMessage 返回,而且必須注意的是父窗口和子窗口或者是歸屬與擁有窗口共用同一個線程。

在32 窗口系統中定義兩種新的窗口類型,前臺窗口和背景窗口,這兩種窗口沒有列到窗口的層次關系中,前臺窗口就是用戶當前操作的窗口,其他的所有窗口都是背景窗口。 32 位窗口系統中支持兩個函數來處理前臺窗口SetForegroundWindowGetForegroundWindow

操作窗口列表

下面是窗口列表操作的一些函數:

?????? EnumChildWindows

使用這個函數得到一個窗口的所有子窗口,包括子窗口的子窗口。不過在列舉的過程中這個函數不能夠列出正在創建的或者銷毀的窗口。

?????? EnumThreadWindows

使用這個函數可以列出所有屬于這個線程的窗口。在這個函數調用之后創建的窗口是不能夠被列舉出來的。

?????? EnumWindows

使用這個函數列舉出所有頂層窗口,不能夠列舉出子窗口,要列出所有的頂層窗口,使用這個函數比GetWindow安全。使用GetWindow 來列出所有的窗口,可能會導致程序無限循環,因為在調用GetWindow 的過程中,可能一些窗口已經銷毀了。EnumWindows 不能夠列舉出調用這個函數之后創建的頂層窗口。

?????? FindWindow

可以使用這個函數通過類名或者使用窗口的標題來找到頂層窗口,這個函數不能夠用來找子窗口,這個函數不區分參數的大小寫。這個函數在Z軸中尋找窗口,找到了之后,就會返回。

?????? GetDesktopWindow

得到桌面窗口句柄

?????? GetNextWindow

使用這個函數得到這個窗口的同屬窗口,在16 位窗口系統中GetNextWindow 和GetWindow是兩個不同的函數,在32 位系統中這個函數是通過GetWindow 來實現的。

?????? GetParent

如果一個窗口存在父窗口,那么可以通過這個函數得到窗口的父窗口,如果窗口是頂層窗口,則返回其所有者窗口句柄。

?????? GetThreadDesktop

這個函數用來得到指定線程的所屬的桌面窗口句柄,在win95 和 win98 下面由于不支持多桌面,每次調用該函數都返回同一個值。

?????? GetTopWindow

可以用這個函數來得到給定窗口的第一個子窗口的句柄,如果傳遞給函數的參數是NULL的話,那么這個函數將會返回最上面的頂層窗口。

?????? GetWindow

應用程序可以調用這個函數來在窗口列表中導航,這個函數有兩個參數,一個是窗口的句柄,另外是要得到的窗口句柄和這個窗口之間的關系。

  • GW_HWNDNEXT: 這個函數返回給定窗口的下一個同屬窗口
  • GW_HWNDFIRST: 返回給定窗口的前一個同屬窗口
  • GW_HWNDLAST: 返回給定窗口的最后一個同屬窗口
  • GW_HWNDPREV: 返回給定窗口的第一個同屬窗口
  • GW_OWNER: 返回給定窗口的所有者窗口句柄
  • GW_CHILD: 返回給定窗口的第一個子窗口句柄
????? IsChild

這個函數有兩個參數,兩個窗口句柄,判斷兩個窗口是否存在父子關系

窗口的屬性

當應用程序調用CreateWindow 創建窗口的時候,我們必須為窗口指定屬性,下面簡要的介紹一下窗口的屬性。

WS_OVERLAPPED

交迭屬性是頂層窗口的一種屬性,使用這種屬性創建的窗口,會被鏈接到桌面窗口的子窗口鏈表中,應用程序通常使用這種屬性的窗口作為應用程序的主窗口,具有交迭屬性的窗口通常具有有標題欄,即使是WS_CAPTION 這個屬性沒有指定。具有交迭屬性的窗口通常都是有邊框的,具有交迭屬性的窗口可以擁有自己的頂層窗口,也可以所屬其他的頂層窗口,所有的這類窗口都具有WS_CLIPSIBLINGS 屬性,即使是沒有給窗口指定這個屬性。

WS_POPUP

彈出屬性也是應用到頂層窗口的一種屬性,使用這種屬性創建的窗口會被鏈接到桌面窗口的子窗口鏈表中,應用程序通常為對話框窗口設置這個屬性,彈出屬性和交迭屬性的主要區別在于具有彈出屬性的窗口不是一定要有標題欄的,而具有交迭屬性的窗口則是一定要具有標題欄,具有彈出屬性的窗口可以沒有邊框。和具有交迭屬性的窗口一樣,具有彈出屬性的窗口可以有自己的頂層所屬窗口,也可以所屬其他的頂層窗口。所有具有彈出屬性的窗口必須具有WS_CLIPSIBINGS 屬性,即使是用戶沒有指定這個屬性。具有彈出屬性的窗口在創建的時候,它的大小和位置不能夠使用CW_USEDEFAULT 值。

WS_CHILD

子窗口必須具有這個屬性,子窗口只能夠出現在父窗口的客戶區域,這是子窗口和具有交迭屬性的窗口以及彈出屬性的窗口的主要區別,創建子窗口的時候,位置和大小不能夠使用CW_USEDEFAULT 這個值,否則是不能夠創建窗口的。

WS_CAPTION

當窗口被設置這個屬性的時候,窗口的最上頭會有標題欄,應用程序可以通過SetWindowText這個函數來改變標題欄的標題,通常具有標題欄的窗口還具有最大、最小、關閉按鈕,和系統菜單。如果一個窗口沒有標題欄,那么Window 是不會創建這些東西的,即使是用戶指定了這些屬性,系統菜單是依賴標題欄窗口的存在而存在的,如果沒有標題欄那么是一定不會有系統菜單的存在的。具有標題欄的窗口通常具有單線的邊界具有可以改變窗口大小的屬性,通常具有標題欄的窗口是不能具有對話框的邊界屬性的,除非為窗口設置WS_EX_DLGMODALFRAME 屬性。?

WS_MINIMIZEBOX

當為窗口設置這個屬性的時候,窗口的標題欄上會有一個最小化的按鈕,其實對于Window來實現這個屬性的時候,只是在標題欄上面放置了一個最小化的位圖,當用戶點擊這個最小化位圖的時候,窗口最小化,如果最大化位圖最在,那么最小化位圖被放置在最大化位圖的左邊。沒有這個屬性的窗口是不能夠最小化的。

WS_MAXIMIZEBOX

當為窗口設置這個屬性的時候,窗口的標題欄的右上會被放置一個最大化的位圖,如果窗口設置了這個屬性,用戶可以點擊最大化的位圖或者是通過系統菜單來實現窗口的最大化,沒有這個屬性的窗口是不能夠被最大化的。

WS_SYSMENU

如果為窗口指定這個屬性,那么就會在窗口的左上角上放置系統菜單位圖,系統菜單為用戶提供了操作窗口的接口,通常系統菜單會有下面這些系統命令:

  • 恢復最小化的窗口
  • 使用鍵盤移動窗口
  • 使用鍵盤改變窗口的大小
  • 最小化窗口
  • 最大化窗口
  • 關閉窗口
  • 切換到其他的任務

如果一個窗口有系統菜單,用戶可以通過點擊系統菜單圖標來調用系統菜單,或者通過Alt+空格的快捷鍵調出系統菜單,或者通過點擊任務欄上窗口的圖標來調出系統菜單,如果一個窗口沒有系統菜單,那么用戶不能夠通過鍵盤來實現系統命令,除非應用程序自身提供了這樣的接口。系統菜單對于最大化的窗口也是很有用處的,最大化的窗口覆蓋了整個屏幕,這樣的窗口不能夠被移動,除非恢復到不是最大化的狀態,如果這個最大化的窗口有了系統菜單,則就不必一定恢復到非最大化的狀態才能夠移動。

WS_HSCROLL

如果窗口被指定了這個屬性,那么窗口會有一個水平的滾動條,窗口是不會自動的滾動滾動條的,如果應用程序要支持滾動條,那么必須自己處理WM_HSCROLL 消息,這個屬性通常是在窗口創建的時候,被指定的。

WS_VSCROLL

如果窗口被指定了這個屬性,那么窗口會有一個豎直的滾動條,窗口不會自動的滾動滾動條,應用程序必須自己處理WM_VSCROOL 消息來處理滾動條滾動的消息,這個屬性通常是在窗口被創建的時候指定的。

WS_BORDER

如果窗口被指定了這個屬性,那么窗口會有一個單線的邊在窗口的周圍,如果沒有指定這個屬性,但是窗口具有標題欄,那么窗口會自動的擁有這個屬性,如果窗口沒有這個屬性,擁有這個屬性的窗口不能夠通過鍵盤或者是鼠標改變窗口的大小。

WS_DLGFRAME

如果窗口被指定了這個屬性,那么窗口具有對話框的邊框,這個屬性通常是用在對話框窗口的,只能夠用在窗口沒有標題欄的情況下,如果一個不是對話框的窗口使用了這個窗口,那么窗口必須被指定WS_EX_DLGMODALFRAME 屬性。使用這個屬性創建的窗口,不能夠通過鍵盤和鼠標改變窗口的大小。

WS_THICKFRAME

當窗口被指定了這個屬性,那么窗口會有一個可以改變大小的邊框,這種屬性通常用在程序的主窗口,具有這種屬性的窗口的大小可以通過鍵盤或者鼠標來改變。

WS_CLIPCHILDREN

這個屬性用在具有子窗口的窗口,使用這個屬性,可以使Window 把子窗口所占的區域拷貝到父窗口,而不是甴父窗口直接的畫子窗口所屬的區域,如果窗口沒有指定這個屬性,那么那么父窗口會覆蓋子窗口的區域。在一些圖片顯示或者OpenGL 顯示的窗口中,指定這個屬性是很重要的。

WS_CLIPSIBLINGS

當窗口賦予這個屬性,窗口在自繪的時候,不會繪制到同屬的子窗口,所有具有交迭屬性和彈出屬性的窗口都具有這個屬性,所有的頂層窗口都具有這個屬性,這樣一來頂層窗口在自繪的時候,不會繪制在到其他的頂層窗口。

WS_VISIBLE

當窗口被設置這個屬性的時候,窗口是可見的,默認的情況下,應用程序必須自己調用ShowWindow 來顯示窗口。

WS_DISABLED

當窗口被設置這個屬性的時候,創建的窗口不能夠接受用戶的輸入,除非應用程序自身提供方法來輸入。這個屬性通常用在Window 控件上面。

WS_CHILDWINDOW

這個屬性同WS_CHILD。

WS_OVERLAPPEDWINDOW

這個屬性同WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,這個屬性通常用在應用程序的主窗口。

WS_POPUPWINDOW

這個屬性同WS_POPUP | WS_BORDER | WS_SYSMENU,盡管這個屬性中包含了WS_SYSMENU 屬性,如果窗口沒有 WS_CAPTION 屬性,那么窗口也不會有系統菜單。

WS_EX_DLGMODALFRAME

當窗口設置了這個屬性的時候,窗口具有對話框的邊框,這個屬性通常用在對話框窗口,不過任何窗口都可以使用這個屬性來獲得對話框的邊框。

WS_EX_NOPARENTNOTIFY

這個屬性是用在子窗口上的,當子窗口設置了這個屬性,Window 不發送WM_NOTIFY 消息給子窗口的父窗口,默認情況下,Window 會在子窗口創建或者銷毀的時候發送WM_NOTIFY 消息給子窗口的父窗口。

WS_EX_TOPMOST

這個屬性僅用在頂層窗口,對于子窗口設置這個屬性是被忽略的,如果窗口設置了這個屬性,那么窗口會一直在其他窗口的上面。

WS_EX_ACCEPTFILES

窗口設置了這個屬性,那么窗口可以接受拖放的對象。

WS_EX_TRANSPARENT

這個屬性能夠使窗口透明,設置了這個屬性的窗口的背景使可以被看到的,透明窗口對于鼠標和鍵盤的消息事件并不是透明的


總結

以上是生活随笔為你收集整理的Window 窗口层次关系的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。