一、引言
? ? ? ? 在上一文中,我們從零開始創(chuàng)建了一個(gè)窗口。其中很重要的一個(gè)步驟,就是注冊(cè)窗口類,如下面的代碼:
//注冊(cè)窗口類 BOOL?Register(LPSTR?lpClassName,?WNDPROC?wndProc) { ????WNDCLASSEX?wce?=?{?0?}; ????wce.cbSize?=?sizeof(wce); ????wce.cbClsExtra?=?0; ????wce.cbWndExtra?=?0; ????wce.hbrBackground?=?(HBRUSH)(COLOR_WINDOW?+?1); ????wce.hCursor?=?NULL; ????wce.hIcon?=?NULL; ????wce.hIconSm?=?NULL; ????wce.hInstance?=?g_hInstance; ????wce.lpfnWndProc?=?wndProc; ????wce.lpszClassName?=?lpClassName; ????wce.lpszMenuName?=?NULL; ????wce.style?=?CS_HREDRAW?|?CS_VREDRAW; ????ATOM?nAtom?=?RegisterClassEx(&wce); ????if?(nAtom?==?0) ????????return?FALSE; ????return?true; }
? ? ? ? windows下的任何一個(gè)窗口,在創(chuàng)建之前都要在系統(tǒng)中已經(jīng)明確的注冊(cè),我們?cè)谑褂肅reateWindowEx進(jìn)行窗口的創(chuàng)建時(shí),第二個(gè)參數(shù)的名稱就是窗口類名稱,這個(gè)名稱在我們代碼可見的作用域內(nèi)應(yīng)該是唯一的。本文主要討論下Windows下,窗口類的問題。
二、窗口類分類
? ? ? ? Windows中所有可見的一切元素基本上都屬于一個(gè)窗口,不管它的形狀如何,是圓的、方的、甚至是無規(guī)則的。所有的這些窗口都屬于某一個(gè)窗口類,大體上來說Windows的窗口類共分為三種:
(1)系統(tǒng)窗口類
(2)全局窗口類
(3)局部窗口類
下面,我將就Windows中窗口類的分類分別進(jìn)行討論。
2.1 系統(tǒng)窗口類
? ? ? ? 一個(gè)按鈕、一個(gè)編輯框所有這些我們?cè)趙indows操作系統(tǒng)中可見的按鈕其實(shí)都是一個(gè)窗口。當(dāng)我們按鈕完操作系統(tǒng)之后,Windows會(huì)在操作系統(tǒng)內(nèi)部注冊(cè)大量的系統(tǒng)級(jí)別的窗口類,我們?cè)谶M(jìn)行開發(fā)時(shí),可以直接根據(jù)窗口類名稱創(chuàng)建這些窗口。為了解釋這個(gè)問題,在上一文中的代碼之上,我們引入下面的代碼。
HWND?CreateMain(LPSTR?lpClassName,?LPSTR?lpWndName) { HWND?hWnd?=?CreateWindowEx(0,?lpClassName,?lpWndName, WS_OVERLAPPEDWINDOW,?CW_USEDEFAULT,?CW_USEDEFAULT,?CW_USEDEFAULT,?CW_USEDEFAULT,?NULL,?NULL,?g_hInstance,?NULL); return?hWnd; } int?APIENTRY?wWinMain(_In_?HINSTANCE?hInstance, _In_opt_?HINSTANCE?hPrevInstance, _In_?LPWSTR????lpCmdLine, _In_?int???????nCmdShow) { //?TODO:?Place?code?here. g_hInstance?=?hInstance; HWND?hWnd?=?CreateMain("Button",?"window"); Display(hWnd); Message(); return?0; }
? ? ? ? CreateMain是我們定義的一個(gè)創(chuàng)建窗口的按鈕。它接收兩個(gè)參數(shù),第一個(gè)時(shí)已經(jīng)注冊(cè)的窗口類名稱,第二個(gè)是窗口的標(biāo)題。與上一文中的代碼不同,我們省去了注冊(cè)自定義窗口的步驟。而是在WinMain函數(shù)中,調(diào)用CreateMain創(chuàng)建了一個(gè)窗口類名稱為“Button”的窗口。我想你已經(jīng)知道我們要做什么了吧?對(duì),就是要生成一個(gè)Button按鈕。我們常用的所有控件都已經(jīng)被操作系統(tǒng)注冊(cè)成了系統(tǒng)窗口類,我們都可以直接使用。請(qǐng)看下面的程序運(yùn)行結(jié)果:
? ? ? ? 你還可以嘗試去創(chuàng)建諸如編輯框、下拉框等其他系統(tǒng)級(jí)別的窗口。
2.2 全局窗口類
? ? ? ? 全局窗口類指注冊(cè)之后可以在應(yīng)用程序全局范圍內(nèi)使用的窗口類。比如,我們可以在dll中對(duì)全局窗口類進(jìn)行注冊(cè),那么引入該dll的所有程序都可以使用該類。注冊(cè)全局使用的窗口類時(shí),我們只需要在注冊(cè)時(shí)對(duì)wec的按鈕的style成員添加CS_GLOBALCLASS按鈕,如下:
wce.style?=?CS_HREDRAW?|?CS_VREDRAW?|?CS_GLOBALCLASS;
? ? ? ? 為了驗(yàn)證這個(gè)問題,我們新添加一個(gè)dll項(xiàng)目,然后定義一個(gè)如下的窗口注冊(cè)函數(shù)RegisterWindow():
LRESULT?CALLBACK?WndProc(HWND?hWnd,?UINT?uMsg,?WPARAM?wParam,?LPARAM?lParam) { switch?(uMsg) { case?WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 break; default: break; } return?DefWindowProc(hWnd,?uMsg,?wParam,?lParam); } ?BOOL?RegisterWindow() { WNDCLASSEX?wce?=?{?0?}; wce.cbSize?=?sizeof(wce); wce.cbClsExtra?=?0; wce.cbWndExtra?=?0; wce.hbrBackground?=?(HBRUSH)(COLOR_WINDOW?+?1); wce.hCursor?=?NULL; wce.hIcon?=?NULL; wce.hIconSm?=?NULL; wce.hInstance?=?NULL; wce.lpfnWndProc?=?WndProc; wce.lpszClassName?=?"DllMain"; wce.lpszMenuName?=?NULL; wce.style?=?CS_HREDRAW?|?CS_VREDRAW?|?CS_GLOBALCLASS; ATOM?nAtom?=?RegisterClassEx(&wce); if?(nAtom?==?0) return?FALSE; return?true; }
? ? ? ? RegisterWindow()中注冊(cè)的窗口類名稱為“DllMain”,我們?cè)?/span>dll的主函數(shù)中調(diào)用該注冊(cè)函數(shù)完成注冊(cè):
BOOL?APIENTRY?DllMain(?HMODULE?hModule, ???????????????????????DWORD??ul_reason_for_call, ???????????????????????LPVOID?lpReserved ?) { .... RegisterWindow(); return?TRUE; } }
? ? ? ? 在我們的主程序中使用該窗口類創(chuàng)建窗口:
int?APIENTRY?wWinMain(_In_?HINSTANCE?hInstance, _In_opt_?HINSTANCE?hPrevInstance, _In_?LPWSTR????lpCmdLine, _In_?int???????nCmdShow) { ... HWND?hWnd?=?CreateMain("DllMain",?"我是一個(gè)Dll注冊(cè)的窗口"); Display(hWnd); Message(); return?0; }
? ? ? ? 運(yùn)行程序你會(huì)發(fā)現(xiàn)我們也成功生產(chǎn)了這個(gè)窗口:
2.3 局部窗口類
? ? ? ? 局部窗口類從定義上來說,凡是未在wce的style中添加CS_GLOBALCLASS,而注冊(cè)的窗口類都是局部窗口類。
wce.style?=?CS_HREDRAW?|?CS_VREDRAW;//未添加CS_GLOBALCLASS
? ? ? ?我們?cè)谏弦晃闹凶?cè)的窗口就是一個(gè)局部的窗口類,它的特點(diǎn)就是只能在注冊(cè)的作用域內(nèi)使用,由于它和全局窗口類只在注冊(cè)的style和作用域上有分別,這里就不再詳述,如要了解,請(qǐng)參照上一文。