Windows 消息機制
編寫Windows程序有兩年了,但當別人問起Windows消息機制總覺得很難形容清楚。在這篇中,集合了很多我從網絡中搜集來的一些知識,這里只是匯總一下。
我們編寫的Windows程序是以事件為驅動,消息機制為基礎的。對于每一個正在執行的Windows應用程序,Windows為其建立一個“消息隊列”,即應用程序隊列,用來存放該程序可能創建的各種窗口的消息。應用程序中含有一段稱作“消息循環”的代碼,用來從消息隊列中檢索這些消息并把它們分發到相應的窗口函數中。
一、消息循環
首先我們來看一下Windows消息循環。
while(GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
MSG結構在頭文件中定義如下:
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG;
其數據成員的具體意義如下:
hwnd:消息將要發送到的那個窗口的句柄,用這個參數可以決定讓哪個窗口接收消息。
message:消息號,它唯一標識了一種消息類型。每種消息類型都在Windows文件進行了預定義。
wParam:一個32位的消息參數,這個值的確切意義取決于消息本身。
lParam:同上。
time:消息放入消息隊列中的時間,在這個域中寫入的并非當時日期,而是從Windows啟動后所測量的時間值。Windows用這個域來使用消息保持正確的順序。
pt:消息放入消息隊列時的鼠標坐標。
消息循環以GetMessage調用開始,它從消息隊列中取出一個消息。然后解釋和分發消息。
二、消息類型
消息主要分為兩種:一是系統定義消息;二是自定義消息。
1、系統定義消息(System-Defined Messages)
在SDK中事先定義好的消息,非用戶定義的,其范圍在[0x0000, 0x03ff]之間, 可以分為以下三類:
1>窗口消息(Windows Message)
與窗口的內部運作有關,如創建窗口,繪制窗口,銷毀窗口等。可以是一般的窗口,也可以是Dialog,控件等。
如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL...
2>命令消息(Command Message)
與處理用戶請求有關, 如單擊菜單項或工具欄或控件時, 就會產生命令消息。
WM_COMMAND, LOWORD(wParam)表示菜單項,工具欄按鈕或控件的ID。如果是控件, HIWORD(wParam)表示控件消息類型
3> 控件通知(Notify Message)
控件通知消息, 這是最靈活的消息格式, 其Message, wParam, lParam分別為:WM_NOTIFY, 控件ID,指向NMHDR的指針。NMHDR包含控件通知的內容, 可以任意擴展。
2、 程序定義消息(Application-Defined Messages)
用戶自定義的消息, 對于其范圍有如下規定:
WM_USER: 0x0400-0x7FFF (ex. WM_USER+10)
WM_APP(winver>4.0): 0x8000-0xBFFF (ex.WM_APP+4)
RegisterWindowMessage: 0xC000-0xFFFF
三、隊列化消息和非隊列化消息
消息被分成隊列化消息和非隊列化消息。
隊列化消息是由Windows放入程序消息隊列中的。在程序的消息循環中,重新傳回并分配給窗口消息處理程序。非隊列化消息是在Windows的窗口過程中直接發送給窗口的消息處理程序。簡單的說,隊列化的消息被發送給消息隊列,而非隊列化的消息則發送給窗口消息處理程序。在任何情況下,窗口消息處理程序都將獲得窗口的所有消息——包括隊列化的和非隊列化的。窗口消息處理程序是窗口的消息中心。隊列化消息基本上是使用者輸入的結果,如WM_KEYDOWN、WM_KEYUP、WM_CHAR、WM_MOUSEMOVE、WM_LBUTTONDOWN 、WM_TIMER、WM_PAINT、WM_QUIT。非隊列化消息則是其他消息。在許多情況下,非隊列化的消息來自呼叫特定的windows函數。
四、SendMessage與PostMessage的區別
SendMessage與PostMessage是在編程過程中使用頻率較高的兩個函數。
SendMessage是同步的操作,它將消息發送給窗口,除非消息處理完畢,否則該函數不會返回。其返回值表示其他程序處理消息后的返回值。
PostMessage是異步的操作,將一個消息放到與指定窗口創建的線程相關的消息隊列中,不等線程處理消息就返回。其返回值表示PostMessage是否執行成功。
五、GetMessage和PeekMessage的區別
區別一:
peekmessage不管消息隊列里有沒有消息都會馬上返回,有消息返回消息,沒消息返回空值,
getmessage等待到有消息的時候才返回,
區別二:
peekmessage可以根據參數決定是否將消息保留在隊列中,
PM_NOREMOVE:該參數指示保留消息
PM_REMOVE:該參數指示移去消息
而getmessage獲得消息后回把消息從消息隊列中刪去。
PeekMessage是一個異步的操作,而GetMessage則是一個同步的操作。
六、TranslateMessage
功能描述:將虛擬鍵消息轉換為字符消息。字符消息被送到調用線程的消息隊列中,在下一次線程調用函數GetMessage或PeekMessage時被讀出。
返回值:
如果消息被轉換(即,字符消息被送到線程的消息隊列中),返回非零值。
如果消息是 WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, 或 WM_SYSKEYUP,返回非零值,不考慮轉換。
如果消息沒有轉換(即,字符消息沒被送到線程的消息隊列中),返回值是零。
備注:
TranslateMessage函數不修改由參數lpMsg指向的消息。
TtanslateMessage僅為那些由鍵盤驅動器映射為ASCII字符的鍵產生WM_CHAR消息。
如果應用程序為其它用途而處理虛擬鍵消息,不應調用TranslateMessage函數。例如,如果TranslateAccelerator函數返回一個非零值,則應用程序將不調用TranslateMessage函數。
Windows CE:Windows CE不支持掃描碼或擴展鍵標志,因此,它不支持由TranslateMessage函數產生的WM_CHAR消息中的lKeyData參數(lParam)16-24的取值。
TranslateMessage函數只能用于轉換由GetMessage或PeekMessage函數接收到的消息。
出處沒有記載,簡單匯總
posted on 2009-04-29 08:02
Sandy 閱讀(881)
評論(0) 編輯 收藏 引用 所屬分類:
Windows Mobile