一、窗口類的查找過程
? ? 上一文中,我們介紹了windows系統(tǒng)三種窗口類——系統(tǒng)窗口類、全局窗口類和局部窗口類。每種窗口類在操作系統(tǒng)中的作用域不同,而且每個作用域內(nèi)注冊的窗口類名稱是不能重復(fù)的。而創(chuàng)建窗口時往往會在系統(tǒng)、全局、局部范圍按照窗口類名稱進(jìn)行尋找,尋找過程總結(jié)如下:
(1)操作系統(tǒng)根據(jù)傳入的窗口類名稱,現(xiàn)在局部窗口類中進(jìn)行查找,如果找到執(zhí)行第2步,如果未找到執(zhí)行第3步。
(2)比較局部窗口類和創(chuàng)建窗口時傳入的HINSTANCE變量。如果發(fā)現(xiàn)相等,說明創(chuàng)建和注冊的窗口在同一個模塊,創(chuàng)建窗口返回。如果不相等,繼續(xù)執(zhí)行第3步。
(3)在應(yīng)用程序全局窗口類中進(jìn)行查找,如果找到,執(zhí)行第4步,如果未找到執(zhí)行第5步。
(4)使用找到的窗口類的信息,創(chuàng)建窗口并返回。
(5)在系統(tǒng)窗口類中查找,如果找到就創(chuàng)建窗口,未找到就是創(chuàng)建窗口失敗。
二、注冊窗口類的變量 Register變量和RegisterClassEx
?????RegisterClass和RegisterClassEx都能用于注冊窗口類,他們兩個的原型分別如下:
ATOM?WINAPI?RegisterClass( ??_In_?const?WNDCLASS?*lpWndClass ); ATOM?WINAPI?RegisterClassEx( ??_In_?const?WNDCLASSEX?*lpwcx );
?????從API原型上看可以看出,二者的區(qū)別主要在于接收的參數(shù)上,這個參數(shù)就是我們需要注冊的窗口類。這兩個窗口類聲明如下:
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;
? ? 從上面的代碼可以看到,兩個窗口類變量的主要區(qū)別在于WNDCLASSEX含有cbSize窗口的結(jié)構(gòu)體大小和hIconSm窗口的小圖標(biāo)句柄。其他參數(shù)的含義請自行參考MSDN。
三、獲取已注冊的窗口信息GetClassInfo
GetClassInfo()??API可以獲取已經(jīng)注冊的窗口的信息,其變量原型如下:
BOOL?WINAPI?GetClassInfo( ??_In_opt_?HINSTANCE??hInstance, ??_In_?????LPCTSTR????lpClassName, ??_Out_????LPWNDCLASS?lpWndClass );
hInstance—— 是設(shè)置查找的作用域,如果設(shè)為變量,會從系統(tǒng)、全局和局部三個作用域查找。
lpClassName?—— 是要查找的窗口類名稱。
lpWndClass?—— 傳入的WndClass結(jié)構(gòu)體變量的地址,用于接收窗口類信息。
?????我們來查找上文創(chuàng)建的Button類的窗口信息:
WNDCLASS?wc; if?(GetClassInfo(NULL,?"Button",?&wc)?==?false) MessageBox(NULL,"GetClassInfo?Faile",NULL,NULL);
??????我們來通過設(shè)置斷點,查看獲取的Button窗口類的信息:
四、卸載窗口類UnregisterClass
? ? 我們可以通過UnregisterClass可以將已經(jīng)注冊的窗口類進(jìn)行卸載,其原型如下:
BOOL?WINAPI?UnregisterClass( ??_In_?????LPCTSTR???lpClassName, ??_In_opt_?HINSTANCE?hInstance );
lpClassName?—— 是要卸載的窗口類名稱。
hInstance —— 是設(shè)置查找的作用域,如果設(shè)為NULL,會從系統(tǒng)、全局和局部三個作用域查找。
????以下代碼,將注冊的Button窗口類進(jìn)行卸載:
?if?(UnregisterClass("Button",NULL)?==?false) MessageBox(NULL,?"UnregisterClass?Faile",?NULL,?NULL);