首頁>技術>

1、Windows程式開發流程:

Windows 程式分為「程式程式碼」和「UI資源」兩大部分,透過RC編譯器整合為一個完整的EXE 檔案。

所謂UI 資源是指功能選單、對話方塊外貌、程式圖示、游標形狀等等東西。

這些UI 資源的實際內容(二進位制程式碼)系藉助各種工具產生,並以各種副檔名存在,如.ico、.bmp、.cur 等等。程式設計師必須在一個所謂的資源描述檔(.rc)中描述它們。

RC 編譯器(RC.EXE)讀取RC 檔的描述後將所有UI資源檔集中製作出一個.RES 檔,再與程式程式碼結合在一起,這才是一個完整的Windows可執行檔案。

2、Windows程式與作業系統之間的關係

Windows 程式的進行系依靠外部發生的事件來驅動。換句話說,程式不斷等待(利用一個while 迴路),等待任何可能的輸入,然後做判斷,然後再做適當的處理。上述的「輸入」是由作業系統捕捉到之後,以訊息形式(一種資料結構)進入程式之中。

3、Windows視窗生命週期如下:

1.程式初始化過程中呼叫CreateWindow,為程式建立了一個視窗,作為程式的螢幕舞臺。CreateWindow產生視窗之後會送出 wM_CREATE直接給視窗函式,後者於是可以在此時做些初始化操作(例如配置記憶體、開啟檔案、讀初始資料……)。

2在程式活著的過程中,不斷以 GetMessage從訊息佇列中抓取訊息。如果這個訊息是WM_oUIT,GetMessage會傳回0而結束while迴圈,進而結束整個程式。

3.DispatchMessage透過Windows USER模組的協助與監督,把訊息分派至視窗函式。訊息將在該處被判別並處理。

4.程式不斷進行第2步和第3步的操作。

5.當使用者按下系統選單中的Close命令項時,系統送出WM_CLOSE。通常程式的視窗函式不攔截此訊息,於是 DefWindowProc處理它。

6.DefWindowProc收到 WM_CLOSE後,呼叫 DestroyWindow把視窗清除。Destroy Window本身又會送出WM_DESTROY。

7.程式對WM_DESTROY的標準反應是呼叫PostQuitMessage。

8.PostQuitMessage沒什麼其它操作,就只送出 WM_QUIT 訊息,準備讓訊息迴圈中的GetMessage取得,如步驟2,結束訊息迴圈。

3.Windows窗體原理

Windows的三大核心繫統:負責視窗物件產生和訊息分發的USER模組,負責影象顯示繪製的GDI模組,負責記憶體、程序、IO管理的KERNEL模組。

試想象一下如何在一個畫素陣列上產生視窗物件,其實就是使用GDI繪製視窗,不停的以一定的頻率重新整理顯示在螢幕上,這就是圖形介面,如果由在DOS或Windows DOS模擬器下編寫圖形介面的經驗這個比較好理解。所以說其實USER模組中的視窗產生是依靠GDI模組的(包括選單、捲軸等都是使用GDI來繪製的)。

那麼,下面我們就從USER模組和GDI模組來說說Windows 的窗體原理。

如果接觸過Win32 SDK程式設計的知道一個標準Windows窗體的產生過程:

設計視窗類、註冊視窗類、建立視窗、顯示視窗、啟動訊息迴圈泵迴圈獲取訊息分發到窗體過程函式處理。

貼上一個標準Windows窗體的產生程式碼:

#include <windows.h> LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){    static TCHAR szAppName[] = TEXT ("視窗類名稱");    HWND         hwnd;    MSG          msg;    WNDCLASSEX   wndclassex = {0}; 	//設計視窗類    wndclassex.cbSize        = sizeof(WNDCLASSEX);    wndclassex.style         = CS_HREDRAW | CS_VREDRAW;    wndclassex.lpfnWndProc   = WndProc;    wndclassex.cbClsExtra    = 0;    wndclassex.cbWndExtra    = 0;    wndclassex.hInstance     = hInstance;    wndclassex.hIcon         = LoadIcon (NULL, IDI_APPLICATION);    wndclassex.hCursor       = LoadCursor (NULL, IDC_ARROW);    wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);    wndclassex.lpszMenuName  = NULL;    wndclassex.lpszClassName = szAppName;    wndclassex.hIconSm       = wndclassex.hIcon;		//註冊視窗類    if (!RegisterClassEx (&wndclassex))    {        MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);        return 0;    } 	//產生視窗    hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW, 		                  szAppName,         		          TEXT ("視窗名稱"),                		  WS_OVERLAPPEDWINDOW,		                  CW_USEDEFAULT,         		          CW_USEDEFAULT,                 		  CW_USEDEFAULT, 		                  CW_USEDEFAULT,         		          NULL,                 		  NULL, 		                  hInstance,        		          NULL); 				//顯示視窗    ShowWindow (hwnd, iCmdShow);    UpdateWindow (hwnd);		//啟動訊息迴圈泵迴圈獲取訊息分配到窗體過程函式處理    while (GetMessage (&msg, NULL, 0, 0))    {        TranslateMessage (&msg);        DispatchMessage (&msg);    }     return msg.wParam;} //窗體過程函式LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){    HDC hdc;    PAINTSTRUCT ps;     switch (message)    {    case WM_CREATE:        return (0);		    case WM_PAINT:        hdc = BeginPaint (hwnd, &ps);        EndPaint (hwnd, &ps);        return (0);		    case WM_DESTROY:        PostQuitMessage (0);        return (0);    }     return DefWindowProc (hwnd, message, wParam, lParam);}

需要明白的是,所有Windows的窗體及控制元件歸根結底都是使用CreateWindow或CreateWindowEx來建立的,他們都需要標準Windows窗體的產生過程。

普通的窗體好理解,主要需要弄清楚是對話方塊及控制元件的產生和訊息分派處理流程。

對話方塊及其子控制元件的管理依靠Windows內建的對話方塊管理器,對話方塊管理器的工作包括:

1.根據我們在資源設計器中設計的對話方塊及子控制元件產生的.rc檔案來自動生成對話方塊和子控制元件(如果有手動編寫.rc檔案的經歷的話,知道編寫RC檔案其實就是指定視窗和子控制元件大小、型別、樣式等引數,對話方塊管理器將這些引數傳入CreateWindow函式產生窗體)

2.模態對話方塊直接顯示窗體,非模態對話方塊訊息指明WS_VISIBLE屬性的話,需要呼叫ShowWindow來顯示窗體。

3.維護一個訊息迴圈泵,對於模態對話方塊來說這個訊息泵的訊息不經過父視窗,所以表現為模態;對於非模態對話方塊這個訊息泵訊息經過主視窗,必須由主視窗傳給非模態對話方塊,表現為非模態。

4.維護一個內建的窗體過程函式,對於對話方塊來說會處理對話方塊的關閉開啟及子視窗的焦點、tab等,對於子控制元件也是一樣,每個子控制元件會有自己型別的窗體過程函式,窗體過程函式處理子控制元件的獲得或失去焦點、按下或彈起、建立等表現樣式和行為。

對於對話方塊來說,他會開放一個對話方塊過程函式,讓部分訊息先透過對話方塊管理函式處理,如果對話方塊過程函式不處理才交給預設的內建過程函式處理,對於子控制元件來說,他們並沒有開放過程函式,而是由內建窗體函式將要處理的訊息發給父視窗處理。

那麼對話方塊管理器完成了標準Windows窗體的產生中後半部分工作,至於設計視窗類和註冊視窗類這是由Windows自己預先做好了的,如常見的“button”、“listbox”、“edit”類等等。

那麼既然所有的窗體(包括對話方塊和控制元件)產生過程一樣,那麼我們就可以將對話方塊管理器的部分工作替換掉:

1.不使用對話方塊讀取.rc模板的方式,直接將引數傳遞給CreateWindow函式來建立對話方塊和控制元件,這就是常見的動態建立控制元件原理

2.設定控制元件自繪製如BS_OWNDRAW屬性,開放控制元件的WM_DRAWITEM訊息給父視窗,由父視窗來繪製按鈕樣式,這就是常見的控制元件重繪原理

3.替換內建的窗體函式,將訊息傳到自定義的窗體過程函式處理,這就是常見的控制元件子類化原理

下一節講:MFC對話方塊原理

18
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 用.net釋出一個簡單的webservice