一、概述
Windows程式具有相對固定的結構,對編寫者而言,不需要書寫整個過程,大部分過程由系統完成。
程式中只要按一定的格式填寫系統留給客戶的那一小部分。
所需要完成的有:
視窗類別的定義、視窗的建立、訊息函數的書寫、訊息迴圈。
二、訊息處理函數
Windows程式是事件驅動的,對於一個視窗,它的大部分例行維護是由系統維護的。沒個視窗都有一個訊息處理函數。
在訊息處理函數中,對傳入的訊息進行處理。系統內還有它自己的預設訊息處理函數。
客戶寫一個訊息處理函數,在視窗建立前,將訊息處理函數與視窗關聯。這樣,每當有訊息產生時,就會去調用這個訊息處理函數。
通常情況下,客戶都不會處理全部的訊息,而是只處理自己感興趣的訊息,其他的,則送回到系統的預設訊息處理函數中去。
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case ... ... case ... ...} return DefWindowProc (hwnd, message, wParam, lParam) ; } |
三、視窗的建立
客戶需要自己建立視窗,建立後會得到系統返回的視窗控制代碼(HWND),後繼的針對視窗的操作都針對控制代碼進行。
1.註冊視窗類別
建立視窗前,需要制定好這個視窗的相關屬性,最主要的就是將自己定義的訊息處理函數與視窗關聯,其他的屬性還包括:菜單、表徵圖等等。
這個屬性指定步驟是通過指定"視窗類別"來完成的。
對於自己建立的視窗,這個"視窗類別"需要自己制定,也即自己填充一個WNDCLASS結構,然後向系統註冊。
對於一些特殊視窗,如按鈕等控制項,他們的行為是系統制定好了的,所以不需要自己註冊,直接使用對應的“視窗類別”名稱就行了。
2.建立視窗
建立視窗時,註冊的"視窗類別"名稱作為參數傳入。
這樣,當有針對該視窗的訊息時,將調用“視窗類別”中指定的訊息處理函數,在其中得到處理。
四、訊息迴圈
系統會將針對這個程式的訊息依次放到程式的“訊息佇列”中,由程式自己依次取出訊息,在分發到對應的視窗中去。
因此,建立視窗後,將進入一個迴圈。
在迴圈中,取出訊息、派發訊息,迴圈往複,直到取得的訊息是退出訊息。
迴圈退出後,程式即結束。
#include "stdafx.h" #include <windows.h>//一、訊息處理函數 //參數:視窗控制代碼,訊息,訊息參數,訊息參數 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { //處理感興趣的訊息 switch (message) { case WM_DESTROY: //當使用者關閉視窗,視窗銷毀,程式需結束,發退出訊息,以退出訊息迴圈 PostQuitMessage (0) ; return 0 ; } //其他訊息交給由系統提供的預設處理函數 return ::DefWindowProc (hwnd, message, wParam, lParam) ; } //二、應用程式主函數 //參數:執行個體控制代碼、前一個執行個體的控制代碼、命令列參數、視窗顯示方式 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { //1.註冊視窗類別 static TCHAR szAppName[] = TEXT ("HelloWin") ; //視窗類別名稱 //定製"視窗類別"結構 WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; //關聯訊息處理函數 wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; //執行個體控制代碼 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; //表徵圖 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; //游標 wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); //畫刷 wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName; //類名稱 //註冊 if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("RegisterClass Fail!"), szAppName, MB_ICONERROR) ; return 0 ; } //建立視窗 HWND hwnd ; hwnd = CreateWindow (szAppName, //視窗類別名稱 TEXT ("The Hello Program"), //視窗標題 WS_OVERLAPPEDWINDOW, //視窗風格 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, //執行個體控制代碼 NULL); ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; //訊息迴圈 MSG msg ; while (GetMessage (&msg, NULL, 0, 0)) //從訊息佇列中取訊息 { TranslateMessage (&msg) ; //轉換訊息 DispatchMessage (&msg) ; //派發訊息 } return msg.wParam ; } |