一.什麼是窗口類
在Windows中運行的程序,大多數都有一個或幾個可以看得見的窗口,而在這些窗口被創建起來之前,操作系統怎麼知道該怎樣創建該窗口,以及用戶操作該窗口的各種消息交給誰處理呢?所以VC在調用Windows的API(CreateWindow或者CreateWindowEx)創建窗口之前,要求程序員必須定義一個窗口類(不是傳統C++意義上的類)來規定所創建該窗口所需要的各種信息,主要包括:窗口的消息處理函數、窗口的風格、圖標、 鼠標、菜單等。其定義如下:
typedef struct tagWNDCLASSA(注:該結構為ANSII版本)
{
UINT style ;
WNDPROC lpfnWndProc ;
int cbClsExtra ;
int cbWndExtra ;
HINSTANCE hInstance ;
HICON hIcon ;
HCURSOR hCursor ;
HBRUSH hbrBackground ;
LPCSTR lpszMenuName ;
LPCSTR lpszClassName ;
}
WNDCLASSA, * PWNDCLASSA, NEAR * NPWNDCLASSA, FAR * LPWNDCLASSA ;
style 表示該類窗口的風格,如style = CS_VREDRAW|CS_HREDRAW表示窗口在運動或者調整大小時需要重畫,關於其它風格可在 MSDN中查到。
lpfnWndProc為一指針,指向用戶定義的該窗口的消息處理函數。
cbClsExtra 用於在窗口類結構中保留一定空間,用於存在自己需要的某些信息。
cbWndExtra用於在Windows內部保存的窗口結構中保留一定空間。
hInstance 表示創建該窗口的程序的運行實體代號(WinMain的參數之一)。
hIcon、hCursor、hbrBackground、lpszMenuName分別表示該窗口的圖標、鼠標形狀、背景色以及菜單。
lpszClassName表示該窗口類別的名稱,即標識該窗口類的標志。
從上面可以看出一個窗口類就對應一個WNDCLASSA結構(這裡以ANSII為例),當程序員將該結構按自己要求填寫完成後,就可以調用RegisterClass(或RegisterClassEx)函數將該類注冊,這樣以後凡是要創建該窗口,只需要以該類名(lpszClassName中指定)為參數調用CreateWindow,你看多方便呀,真是一舉多得啊!
二.傳統SDK中的窗口類
既然我們知道了什麼是窗口類,那我們就將它放到一個傳統的SDK程序中,看看是怎樣運行的。
#include
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
WNDCLAS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
......
wndclass.lpszClassName = szAppName ;
RegisterClass (&wndclass);
hwnd = CreateWindow( szAppName,...,NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
這是一個標准的Windows程序代碼,程序被啟動後,填寫一個窗口類,然後調用RegisterClass將該類注冊,接著創建該窗口,最後顯示窗口和進入消息循環。
三.MFC中的窗口類
當你看到這裡,也許你可能會感到奇怪:我在用MFC向導做程序時,並沒有進行什麼窗口類的填寫和注冊嗎?是的,你沒有,但是向導幫你做了。在展示向導是怎麼做的之前,請讓我先介紹一下預先知識。
在MFC系統中定義了五個默認的窗口類(這裡不包括AFX_WNDCOMMCTLS_REG),分別定義在AFXIMPL.h中:
#define AFX_WND_REG (0x0001)
#define AFX_WNDCONTROLBAR_REG (0x0002)
#define AFX_WNDMDIFRAME_REG (0x0004)
#define AFX_WNDFRAMEORVIEW_REG (0x0008)
#define AFX_WNDDOLECONTROL_REG (0x0020)
在WINCORE.cpp定義了這些窗口類對應的字符串名稱:
const TCHAR _afxWnd[] = AFX_WND;
const TCHAR _afxWndControlBar[] = AFX_WNDCONTROLBAR;
const TCHAR _afxWndMDIFrame[] = AFX_WNDMDIFRAME;
const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;
const TCHAR _afxWndOleControl[] = AFX_WNDOLERONTROL;
在AFXIMPL.h中定義了五個AFX_XXX對應的字符串:
#define AFX_WND AFX_WNDCLASS(“WND”)
#define AFX_WNDCONTROLBAR AFX_WNDCLASS(“ControlBar”)
#define AFX_WNDMDIFRAME AFX_WNDCLASS(“MDIFrame”)
#define AFX_WNDFRAMEORVIEW AFX_WNDCLASS(“FrameOrVIEw”)
#define AFX_WNDOLECONTROL AFX_WNDCLASS(“OleControl”)
看到這裡也許有些心急了,其實上面一堆代碼只是定義了五個默認窗口類的字符串名稱和二進制名稱,具體注冊行為在全局函數AfxDeferRegisterClass中 (待續)