一、窗口類的查找過程
? ? 上一文中,我們介紹了windows系統三種窗口類——系統窗口類、全局窗口類和局部窗口類。每種窗口類在操作系統中的作用域不同,而且每個作用域內注冊的窗口類名稱是不能重復的。而創建窗口時往往會在系統、全局、局部范圍按照窗口類名稱進行尋找,尋找過程總結如下:
(1)操作系統根據傳入的窗口類名稱,現在局部窗口類中進行查找,如果找到執行第2步,如果未找到執行第3步。
(2)比較局部窗口類和創建窗口時傳入的HINSTANCE變量。如果發現相等,說明創建和注冊的窗口在同一個模塊,創建窗口返回。如果不相等,繼續執行第3步。
(3)在應用程序全局窗口類中進行查找,如果找到,執行第4步,如果未找到執行第5步。
(4)使用找到的窗口類的信息,創建窗口并返回。
(5)在系統窗口類中查找,如果找到就創建窗口,未找到就是創建窗口失敗。
二、注冊窗口類的變量 Register變量和RegisterClassEx
?????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
GetClassInfo()??API可以獲取已經注冊的窗口的信息,其變量原型如下:
BOOL?WINAPI?GetClassInfo( ??_In_opt_?HINSTANCE??hInstance, ??_In_?????LPCTSTR????lpClassName, ??_Out_????LPWNDCLASS?lpWndClass );
hInstance—— 是設置查找的作用域,如果設為變量,會從系統、全局和局部三個作用域查找。
lpClassName?—— 是要查找的窗口類名稱。
lpWndClass?—— 傳入的WndClass結構體變量的地址,用于接收窗口類信息。
?????我們來查找上文創建的Button類的窗口信息:
WNDCLASS?wc; if?(GetClassInfo(NULL,?"Button",?&wc)?==?false) MessageBox(NULL,"GetClassInfo?Faile",NULL,NULL);
??????我們來通過設置斷點,查看獲取的Button窗口類的信息:
四、卸載窗口類UnregisterClass
? ? 我們可以通過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);