Windows程序具有相對固定的結構。與以前的DOS程序不同。Windows程序和操作系統結合更緊密??梢哉f(shuō)應用程序的在運行時(shí)絕大多數時(shí)間都在等待操作系統的消息。我們編寫(xiě)一個(gè)Windows程序其實(shí)很簡(jiǎn)單。需要做的工作是:注冊窗口類(lèi),創(chuàng )建窗口對象,編寫(xiě)窗口過(guò)程,消息循環(huán)。
一、注冊窗口類(lèi)
Windows的窗口類(lèi)定義了一個(gè)窗口的風(fēng)格,而類(lèi)中定義的窗口過(guò)程決定了窗口的行為。每個(gè)類(lèi)都有一個(gè)自己的名字,在Windows中所有的窗口都屬于一個(gè)窗口類(lèi)。如果我們需要創(chuàng )建一個(gè)自己的窗口,則必須注冊一個(gè)窗口類(lèi)。Win32系統提供了一些全局類(lèi)。這些類(lèi)無(wú)需注冊就可以使用。比如:Windows的一些通用控件。對話(huà)框類(lèi)。等等。下面是一個(gè)注冊窗口類(lèi)的代碼:
WNDCLASS wc;
memset(&wc,0,sizeof(WNDCLASS)); //未使用到的成員函數默認為0
wc.style = CS_HREDRAW|CS_VREDRAW |CS_DBLCLKS ; //這里定義窗口風(fēng)格
wc.lpfnWndProc = (WNDPROC)MainWndProc; //窗口過(guò)程,是一個(gè)函數地址,必須編寫(xiě)。
wc.hInstance = hInst; //模塊句柄
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); //背景顏色刷子
wc.lpszClassName = "MyWndClass"; //窗口類(lèi)名
wc.lpszMenuName = MAKEINTRESOURCE(IDMAINMENU); //窗口菜單
wc.hCursor = LoadCursor(NULL,IDC_ARROW); //窗口光標,
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); //窗口圖標
if (!RegisterClass(&wc)) //調用RegisterClass注冊窗口類(lèi)
return FALSE;
上面的代碼 WNDCLASS 是一個(gè)結構體,我們通過(guò)設置它的成員的值來(lái)設定窗口類(lèi)的風(fēng)格和屬性。然后將這個(gè)結構體傳遞給系統,申請注冊窗口類(lèi)。成功返回非0值,失敗返回0.如果注冊成功。我們就可以利用該類(lèi)名來(lái)創(chuàng )建窗口了。
二、創(chuàng )建窗口
創(chuàng )建窗口就比較簡(jiǎn)單了。我們只需要調用CreateWindow函數,就可以創(chuàng )建它。用戶(hù)要注意的是,在這里要了解每個(gè)參數的作用。
HWND CreatemdiWndClassWnd(void)
{
HWND hwnd=CreateWindow("MyWndClass","MDI 多文檔",//這兩個(gè)參數,第一個(gè)為類(lèi)名,就是我們前面注冊的窗口類(lèi)名,第二個(gè)為窗口標題 。
WS_MINIMIZEBOX|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZEBOX|WS_CAPTION|WS_BORDER|WS_SYSMENU|WS_THICKFRAME,//這里是窗口風(fēng)格,我們可以在這里指定窗口是否有最大化按鈕,是否有標題欄,是否可調整邊框等等一些風(fēng)格
CW_USEDEFAULT,0,CW_USEDEFAULT,0,//這里是指定窗口的坐標和尺寸
NULL,
NULL,
hInst,//實(shí)例句柄
NULL);
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
return hwnd;
}
通過(guò)上面這個(gè)函數,我們已經(jīng)創(chuàng )建了一個(gè)窗口,創(chuàng )建完畢后還不能顯示,需要調用ShowWindow()函數窗口就會(huì )正常顯示出來(lái)。
三、窗口過(guò)程
窗口過(guò)程是我們處理消息的關(guān)鍵。前面我們說(shuō)過(guò),我們的應用程序的大部分工作都由操作系統完成,我們只要懸在我們感興趣的事件由我們自己處理即可。在注冊窗口類(lèi)的一節我們看到過(guò)了。窗口過(guò)程是一個(gè)函數,它在注冊窗口類(lèi)的時(shí)候被傳遞。
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch (msg) {
case WM_CREATE: //這里是窗口創(chuàng )建完畢的消息,每一個(gè)窗口創(chuàng )建完畢都會(huì )產(chǎn)生次事件
//do something 做我們需要做的工作。完了要break;
break;
case WM_CLOSE: //當用戶(hù)點(diǎn)擊關(guān)閉按鈕的時(shí)候會(huì )觸發(fā)這個(gè)事件。
DestroyWindow(hWin);
return TRUE;
case WM_DESTROY:
PostQuitMessage(NULL);
break;
default:
return DefWindowProc(hWin,uMsg,wParam,lParam);//我說(shuō)了。大部分工作由系統處理吧,不感興趣的消息。統統交給默認窗口過(guò)程。
}
return 0;
}
上面的窗口過(guò)程很簡(jiǎn)單吧。窗口過(guò)程是一個(gè)回調函數,頁(yè)就是說(shuō)。它是由操作系統調用的。當我們點(diǎn)擊一個(gè)鼠標或者按下一個(gè)鍵后,操作系統會(huì )將消息發(fā)送給前臺窗口,應用程序接收到此消息后,會(huì )調用對應的窗口過(guò)程。這個(gè)時(shí)候窗口過(guò)程被執行。
四、消息循環(huán)
消息循環(huán)顧名思義,就是循環(huán)等待消息的到來(lái)。
while (GetMessage (&msg, NULL, 0, 0)) //從消息隊列中取消息
{
TranslateMessage (&msg) ; //轉換消息
DispatchMessage (&msg) ; //派發(fā)消息
}
return msg.wParam;
這里是一個(gè)最簡(jiǎn)單的消息循環(huán)了。GetMessage 是從消息隊列種取得一條消息,如果消息隊列中沒(méi)有消息,這個(gè)函數就等待,直到有消息到達才會(huì )返回。當然如果收到WM_QUIT 消息,這個(gè)函數會(huì )返回假,循環(huán)跳出,這個(gè)時(shí)候就宣告應用程序關(guān)閉了。窗口過(guò)程中的 PostQuitMessage() 就是發(fā)送這個(gè)消息。通知退出消息循環(huán)。TranslateMessage () 函數的功能是對一些原始消息進(jìn)行預處理,比如按鍵消息..DispatchMessage ()函數則是負責分派消息,它會(huì )將消息的參數做為調用參數,調用該窗口的窗口過(guò)程

