一. 消息的概念
當(dāng)用戶單擊鼠標(biāo)、改變窗口大小或者按下鍵盤上的一個鍵等用戶動作時,會觸發(fā)點擊,按鍵等事件漱凝,而windows系統(tǒng)把這些事件轉(zhuǎn)化為特定的消息,并放置在應(yīng)用程序的消息列隊中(windows為當(dāng)前運行的每一個windows程序維護了一個消息列隊)等待應(yīng)用程序的處理诸迟,而應(yīng)用程序不斷從消息列隊中取出消息茸炒,并進(jìn)行響應(yīng)愕乎。所以說windows是基于消息的事件驅(qū)動模式。
二. 消息如何被處理壁公?(窗口過程)
按照一般寫程序的思維而言感论,我們希望傳給函數(shù)正確的參數(shù)來調(diào)用這個函數(shù)。而windows消息可以理解為指定了的函數(shù)的參數(shù)紊册,例如:用戶需要關(guān)閉某個窗口笛粘,點擊了右上角的X后,windows便把這個行為轉(zhuǎn)換為消息加入消息列隊湿硝,而這個消息可能包含了“需要關(guān)閉的是哪一個窗口(窗口句柄)”,“關(guān)閉窗口的信息”這樣的參數(shù)润努,應(yīng)用程序從消息列隊中讀取到了這個消息关斜,并把它交給“關(guān)閉窗口”這個函數(shù)來進(jìn)行處理,而這個函數(shù)就叫做“窗口過程”铺浇,這樣聽起來不好理解痢畜,可以加長的理解為“處理窗口消息的函數(shù)過程”。
而如果沒有對應(yīng)的函數(shù)來處理這個消息呢鳍侣?例如丁稀,拖動窗口。為此倚聚,windows會用默認(rèn)的消息處理函數(shù)(DefWindowProc)來進(jìn)行處理.
三. 消息的組成
消息結(jié)構(gòu)體長這樣
typedef struct tagMSG { HWND hwnd; //消息句柄线衫,理解為窗口的唯一標(biāo)志 UINT message; //消息類型,分為windows消息和用戶自己定義的消息 WPARAM wParam; //消息附加參數(shù) LPARAM lParam; //消息附加參數(shù) DWORD time; //消息產(chǎn)生時間愛你 POINT pt; //消息被發(fā)送時的光標(biāo)位置 } MSG;
四. 消息發(fā)送的方式
1. 投遞消息PostMessage
異步執(zhí)行惑折,發(fā)送到消息列隊后立即返回?zé)o序等待授账。
應(yīng)用程序一般是投遞一個消息來通知指定窗口完成某個任務(wù)
BOOL PostMessage( HWND hWnd, //目標(biāo)窗口句柄 UINT Msg, //消息類型 WPARAM wParam, //第一個消息參數(shù) LPARAM lParam //第二個消息參數(shù) );
2. 發(fā)送消息 SendMessage
同步執(zhí)行,需要等到消息的返回碼之后在繼續(xù)惨驶。
基本上所有的輸入類消息白热,都是以投遞的方式抵達(dá)應(yīng)用的,而其他的消息粗卜,則大部分是采取了發(fā)送方式屋确。
LRESULT SendMessage( HWND hWnd, //接收消息的目標(biāo)窗口 UINT Msg, //消息類型 WPARAM wParam, //第一個消息參數(shù) LPARAM lParam //第二個消息參數(shù) );
五. 消息循環(huán)實例
while(GetMessage (&msg, NULL, 0, 0)) //消息循環(huán),不斷從消息列隊取出消息
{
TranslateMessage (&msg) ; //翻譯鍵盤消息
DispatchMessage (&msg) ; //把消息發(fā)送給窗口過程
}
//消息過程是一個CALLBACK回調(diào)函數(shù)续扔,每處理一個消息會返回一個值給windows
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_CREATE:
PlaySound(TEXT("hello.wav"), NULL, SND_FILENAME | SND_ASYNC); //窗口創(chuàng)建的時候播放音樂
return 0;
case WM_DESTROY:
PostQuitMessage(0); //把退出窗口的消息插入消息列隊
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam); //默認(rèn)的消息處理函數(shù)
}