Windows系統是一個訊息驅動的OS,什麼是訊息呢?我很難說得清楚,也很難下一個定義,我下面從不同的幾個方面講解一下,希望大家看了後有一點瞭解。
1、訊息的組成:一個訊息由一個訊息名稱(UINT),和兩個參數(WPARAM,LPARAM)。當使用者進行了輸入或是視窗的狀態發生改變時系統都會發送訊息到某一個視窗。例如當菜單轉中之後會有WM_COMMAND訊息發送,WPARAM的高字中(HIWORD(wParam))是命令的ID號,對菜單來講就是菜單ID。當然使用者也可以定義自己的訊息名稱,也可以利用自訂訊息來發送通知和傳送資料。
2、誰將收到訊息:一個訊息必須由一個視窗接收。在視窗的過程(WNDPROC)中可以對訊息進行分析,對自己感興趣的訊息進行處理。例如你希望對菜單選擇進行處理那麼你可以定義對WM_COMMAND進行處理的代碼,如果希望在視窗中進行圖形輸出就必須對WM_PAINT進行處理。
3、未處理的訊息到那裡去了:M$為視窗編寫了預設的視窗過程,這個視窗過程將負責處理那些你不處理訊息。正因為有了這個預設視窗過程我們才可以利用Windows的視窗進行開發而不必過多關注視窗各種訊息的處理。例如視窗在被拖動時會有很多訊息發送,而我們都可以不予理睬讓系統自己去處理。
4、視窗控制代碼:說到訊息就不能不說視窗控制代碼,系統通過視窗控制代碼來在整個系統中唯一標識一個視窗,發送一個訊息時必須指定一個視窗控制代碼表明該訊息由那個視窗接收。而每個視窗都會有自己的視窗過程,所以使用者的輸入就會被正確的處理。例如有兩個視窗共用一個視窗過程代碼,你在視窗一上按下滑鼠時訊息就會通過視窗一的控制代碼被發送到視窗一而不是視窗二。
5、樣本:下面有一段虛擬碼示範如何在視窗過程中處理訊息
LONG yourWndProc(HWND hWnd,UINT uMessageType,WPARAM wP,LPARAM) { switch(uMessageType) {//使用SWITCH語句將各種訊息分開 case(WM_PAINT): doYourWindow(...);//在視窗需要重新繪製時進行輸出 break; case(WM_LBUTTONDOWN): doYourWork(...);//在滑鼠左鍵被按下時進行處理 break; default: callDefaultWndProc(...);//對於其它情況就讓系統自己處理 break; } } |
接下來談談什麼是訊息機制:系統將會維護一個或多個訊息佇列,所有產生的訊息都回被放入或是插入隊列中。系統會在隊列中取出每一條訊息,根據訊息的接收控制代碼而將該訊息發送給擁有該視窗的程式的訊息迴圈。每一個啟動並執行程式都有自己的訊息迴圈,在迴圈中得到屬於自己的訊息並根據接收視窗的控制代碼調用相應的視窗過程。而在沒有訊息時訊息迴圈就將控制權交給系統所以Windows可以同時進行多個任務。下面的虛擬碼示範了訊息迴圈的用法:
while(1) { id=getMessage(...); if(id == quit) break; translateMessage(...); } |
當該程式沒有訊息通知時getMessage就不會返回,也就不會佔用系統的CPU時間。 圖示訊息投遞模式
在16位的系統中系統中只有一個訊息佇列,所以系統必須等待當前任務處理訊息後才可以發送下一訊息到相應程式,如果一個程式陷如死迴圈或是耗時操作時系統就會得不到控制權。這種多任務系統也就稱為協同式的多任務系統。Windows3.X就是這種系統。
而32位的系統中每一啟動並執行程式都會有一個訊息佇列,所以系統可以在多個訊息佇列中轉換而不必等待當前程式完成訊息處理就可以得到控制權。這種多任務系統就稱為搶先式的多任務系統。Windows95/NT就是這種系統。