起因
在看操作系統消息機制的時候,看到一句化:全局消息隊列把消息發送到窗口所在的線程消息隊列。突然就懷疑起了窗口的意思。於是就有這邊基類。
文章來源:https://docs.microsoft.com/zh-cn/windows/win32/learnwin32/what-is-a-window-
正文
看名字( Window )就知道,窗口是 Windows 編程開發的核心,但是什么是窗口?你的大腦中可能浮現如下畫面:
這種類型的窗口叫做應用程序窗口(application window)或者主窗口( main window)。典型的主窗口框架通常包括標題欄、最小化按鈕和最大化按鈕以及一些其它的 UI 組件。這個框架本身叫做窗口的非客戶區(non-client area)。
Windows 操作系統負責管理非客戶區的響應操作,例如拖拽,改變大小,最大化最小化等等。框架之外剩余的區域,叫做客戶區(client area),這部分是由程序自身負責管理的。
下面是另一種類型的窗口:
你可能驚訝於 UI 控件也是一種窗口。UI 控件的類型很多,包括按鈕、編輯框、下拉列表等等。 UI 控件一般不能單獨存在,大多都是依附於窗口之上。
當你拖拽一個窗口的時候,窗口上的 UI 控件一樣會跟隨移動,並保持在窗口的相對位置不變。控件和窗口之間是可以互相通訊的(例如,窗口可以接收到按鈕的點擊事件)。
知道上面的信息后,再次提及窗口的時候,你不應該簡單的把窗口想象為典型的主窗口,而是要把它看做一種包含若干特點的數據結構:
- 其占據屏幕的某個部分。
- 在特定的時候可以隱藏。
- 知道如何繪制自身。
- 對來自用戶或操作系統的事件能做成響應。
1. 父窗口(Parent Windows)和附屬窗口(Owner Windows)
當存在 UI 控件的時候,控件窗口被認為是應用程序窗口的子窗口,應用程序窗口被認為是控件窗口的父窗口。通過父窗口的坐標系可以定位子窗口的位置,並且子窗口的樣式等一些屬性會受到父窗口的影響。例如,超出父窗口范圍的子窗口默認會被裁剪掉。
除了父子關系另一種關系存在於應用程序窗口和模態窗口之間。當一個應用程序顯示一個模態窗口,這個應用程序窗口被稱為擁有者窗口(owner window),而這個模態窗口叫做被擁有者窗口(owned window),可以把模態窗口叫做應用程序窗口的附屬窗口。
被擁有者窗口總是出現在應用窗口之前,當擁有者窗口最小化或者銷毀的時候,被擁有者窗口會自動隱藏。
下圖顯示一個應用程序窗口和一個包含兩個按鈕的模態對話框窗口。
這個應用程序窗口擁有這個對話框窗口,而對話框窗口是兩個按鈕的父窗口,整個關系如下圖所示:
2. 窗口句柄
窗口句柄
Windows是對象,它們同時具有代碼和數據,但它們不是 C++ 類。 相反,程序通過使用名為句柄 的值來引用 窗口。 句柄是不透明類型。 實質上,它只是操作系統用來標識對象的數字。 可以想象Windows創建的所有窗口都有一個大表。 它使用此表按其句柄查找窗口。 (它內部的工作方式是否完全相同都很重要。) 窗口句柄的數據類型是 HWND, 這通常發音為"aitch-wind"。 窗口句柄由創建窗口的函數返回 :CreateWindow 和 CreateWindowEx。
若要對窗口執行運算,通常會調用一些采用 HWND 值作為參數的函數。 例如,若要重新定位屏幕上的窗口,請調用 MoveWindow 函數:
BOOL MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);
第一個參數是要移動的窗口的句柄。 其他參數指定窗口的新位置以及是否應該重新繪制窗口。
請記住,句柄不是指針。 如果 hwnd 是包含句柄的變量,則嘗試通過寫入取消引用句柄 *hwnd
是一個錯誤。
3. 屏幕坐標和窗口坐標
坐標是用像素表示的,這里的像素(pixels)一般是獨立於設備的,術語用 device-independent pixels 表示,其實說簡單一些就是這些像素是抽象的,獨立於設備之外的,以后的文章會仔細討論這部分內容的含義。
根據需求的不同,坐標系可以相對於屏幕建立,也可以相對於窗口(包含框架)建立,還可以相對於窗口客戶區建立。對於同一個物體雖然位置不變,但對於不同的坐標系,表示的坐標位置是不同的。
如下圖所示,同一個(0,0)點坐標,對於不同坐標系,表示對位置是不同的。