上一文中,我們介紹了windows系統三種視窗類別-系統視窗類別、全域視窗類別和局部視窗類別。每個視窗類別在作業系統中的作用域不同,而且每個作用域內註冊的視窗類別名稱是不能重複的。而建立視窗時往往會在系統、全域、局部範圍依照視窗類別名稱尋找,尋找過程總結如下:
(1)作業系統依照傳入的視窗類別名稱,現在局部視窗類別中進行查找,如果找到執行第2步,如果未找到執行第#3步驟。
(2)比較局部視窗類別和建立視窗時傳入的HINSTANCE變數。如果發現相等,表示建立和註冊的視窗在同一個模組,建立視窗返回。如果不相等,繼續執行第3步驟。
(3)在應用程式全域視窗類別中進行查找,如果找到,執行第4步,如果未找到執行第# 5步。
(4)使用找到的視窗類別的信息,建立視窗並返回。
(5)在系統視窗類別中查找,如果找到就建立窗口,找不到就是建立視窗失敗。
RegisterClass和RegisterClassEx 都能用於註冊視窗類,他們兩個的原型分別如下:
ATOM WINAPI RegisterClass( _In_ const WNDCLASS *lpWndClass ); ATOM WINAPI RegisterClassEx( _In_ const WNDCLASSEX *lpwcx );
從API原型上看可以看出,二者的差別主要在於接收的參數上,這個參數就是我們需要註冊的視窗類別。這兩個視窗類別宣告如下:
typedef struct tagWNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; } WNDCLASS, *PWNDCLASS;
typedef struct tagWNDCLASSEX { UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; HICON hIconSm; } WNDCLASSEX, *PWNDCLASSEX;
從上面的程式碼可以看到,兩個視窗類別結構體的主要差異在於WNDCLASSEX含有cbSize視窗的結構體大小和hIconSm視窗的小圖示句柄。其他參數的意義請自行參考MSDN。
GetClassInfo() API可以取得已註冊的視窗的訊息,其函數原型如下:
BOOL WINAPI GetClassInfo( _In_opt_ HINSTANCE hInstance, _In_ LPCTSTR lpClassName, _Out_ LPWNDCLASS lpWndClass );
hInstance—— 是設定查找的作用域,如果設為NULL,會從系統、全域和局部三個作用域中找出。
lpClassName —— 是要找的視窗類別名稱。
lpWndClass —— 傳入的WndClass結構體變數的位址,用於接收視窗類別資訊。
我們來尋找上文所建立的Button類別的視窗資訊:
WNDCLASS wc; if (GetClassInfo(NULL, "Button", &wc) == false) MessageBox(NULL,"GetClassInfo Faile",NULL,NULL);
我們來透過設定斷點,查看獲取的Button視窗類別的資訊:
我們可以透過UnregisterClass可以將已經註冊的視窗類別進行卸載,其原型如下:
BOOL WINAPI UnregisterClass( _In_ LPCTSTR lpClassName, _In_opt_ HINSTANCE hInstance );
lpClassName - 是要卸載的視窗類別名稱。
hInstance —— 是設定查找的作用域,如果設為NULL,會從系統、全域和局部三個作用域找到。
以下程式碼,將註冊的Button視窗類別進行卸載:
if (UnregisterClass("Button",NULL) == false) MessageBox(NULL, "UnregisterClass Faile", NULL, NULL);
以上是Win32 SDK基礎(六)之詳解視窗類別的查找過程與相關API的詳細內容。更多資訊請關注PHP中文網其他相關文章!