Windows程序所作的一切,都是回應(yīng)發(fā)送給窗口消息處理程序的消息。這是概念上的主要難點(diǎn)之一,在開始寫作Windows程序之前,必須先搞清楚。
窗口消息處理程序與窗口類別相關(guān),窗口類別是程序調(diào)用RegisterClass注冊(cè)的。依據(jù)該類別建立的窗口使用這個(gè)窗口消息處理程序來(lái)處理窗口的所有消息。Windows通過調(diào)用窗口消息處理程序?qū)Υ翱诎l(fā)送消息。
在第一次建立窗口時(shí),Windows調(diào)用WndProc。在窗口關(guān)閉時(shí),Windows也調(diào)用WndProc。窗口改變大小、移動(dòng)或者變成圖標(biāo)時(shí),從菜單中選擇某一項(xiàng)目、挪動(dòng)滾動(dòng)條、按下鼠標(biāo)按鈕或者從鍵盤輸入字符時(shí),以及窗口客戶區(qū)必須被更新時(shí),Windows都要調(diào)用WndProc。
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
所有這些WndProc調(diào)用都以消息的形式進(jìn)行。在大多數(shù)Windows程序中,程序的主要部分都用來(lái)處理消息。Windows可以發(fā)送給窗口消息處理程序的消息通常都以WM開頭的名字標(biāo)識(shí),并且都在WINUSER.H頭文件中定義。
窗口中發(fā)生的一切都以消息的形式傳給窗口消息處理程序。然后,窗口消息處理程序以某種方式回應(yīng)這個(gè)消息,或者將消息傳給DefWindowProc,進(jìn)行默認(rèn)處理。
讓我們來(lái)看一個(gè)例子。一旦窗口的客戶區(qū)大小發(fā)生了改變,Windows就調(diào)用窗口的窗口消息處理程序。窗口消息處理程序的hwnd參數(shù)是改變大小的窗口的句柄(請(qǐng)記住,一個(gè)窗口消息處理程序能處理依據(jù)同一個(gè)窗口類別建立的多個(gè)窗口的消息。參數(shù)hwnd讓窗口消息處理程序知道是哪個(gè)窗口在接收消息)。參數(shù)message是WM_SIZE。消息WM_SIZE的參數(shù)wParam的值是SIZE_RESTORED、SIZE_MINIMIZED、SIZE_MAXIMIZED、SIZE_MAXSHOW或SIZE_MAXHIDE (在WINUSER.H頭文件中分別定義為數(shù)字0到4)。也就是說,參數(shù)wParam表明窗口是非最小化還是非最大化,是最小化、最大化,還是隱藏。
lParam參數(shù)包含了新窗口的大小,新寬度和新高度均為16位值,合在一起成為32位的lParam。WINDEF.H中提供了幫助程序?qū)懽髡邚膌Param中取出這兩個(gè)值的宏.
原文:http://c.chinaitlab.com/vc/808874.html

WIN32的消息流程是很簡(jiǎn)單的,一個(gè)while,一個(gè)switch。。
MFC的消息處理流程,事實(shí)上和WIN32的一樣,不過MFC做了一下封裝。
具體的封裝很簡(jiǎn)單,但是難點(diǎn),也是它用到的一個(gè)關(guān)鍵的技術(shù),就是Thunk,Thunk是MFC之所以能夠把消息處理放到窗口類的私有函數(shù)進(jìn)行處理的關(guān)鍵技術(shù)。
MFC的消息處理內(nèi)幕基本上是這樣:
★要有一個(gè)能夠進(jìn)行消息處理的說明宏。DECLARE_MESSAGE_MAP(),這個(gè)宏事實(shí)上類似定義了一個(gè)數(shù)組。用來(lái)存儲(chǔ)你的消息映射。
★要有消息映射,ON_COMMAND、ON_MESSAGE等。這個(gè)宏就是往上面的數(shù)組中添加映射數(shù)據(jù)。
★在消息處理內(nèi)部:
for( int i; i < 數(shù)組大小; i++)
 if( msg == 數(shù)組[i].msg )
 call 數(shù)組[i].Proc;
至于為什么MFC能把消息處理放到類的成員函數(shù)中,關(guān)鍵的Thunk技術(shù):
Thunk事實(shí)上是一個(gè)結(jié)構(gòu),他被創(chuàng)建在堆中,堆的屬性是,可讀、可寫、可執(zhí)行,第三條可執(zhí)行是關(guān)鍵。MFC創(chuàng)建一個(gè)thunk,這個(gè)thunk里面存儲(chǔ)的事實(shí)上是一段代碼,這段代碼可以把Windows消息處理函數(shù)的第一個(gè)參數(shù),就是hWnd,替換成類的this指針,然后進(jìn)行一個(gè)jmp,用這個(gè)this指針去調(diào)用類的成員函數(shù),同時(shí)thunk被轉(zhuǎn)換為WINPROC類型,因此消息過程事實(shí)上先去執(zhí)行thunk代碼,然后再去執(zhí)行靜態(tài)的WINPROC,但此時(shí)第一個(gè)參數(shù)已經(jīng)是this指針了,然后就可以去調(diào)用類的成員函數(shù)。支持虛擬,繼承等。。“我”的空間里有詳細(xì)的Thunk技術(shù)討論。 http://hi.baidu.com/sdhexu/blog/category/thunk%BC%BC%CA%F5%D1%D0%BE%BF

首先,你必須已經(jīng)建立了一個(gè)窗口。這時(shí),你在這個(gè)窗口內(nèi)點(diǎn)了一下鼠標(biāo)左鍵,Windows系統(tǒng)會(huì)將這個(gè)“消息(或者說事件)”放入到系統(tǒng)消息隊(duì)列里。之后它會(huì)自動(dòng)分辨出這是哪個(gè)窗口所接收的消息,并將這個(gè)消息放入到該窗口所對(duì)應(yīng)的應(yīng)用程序消息隊(duì)列里。
第二,你的應(yīng)用程序主函數(shù):WinMain()執(zhí)行到消息循環(huán)后,代碼是:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GetMessage()函數(shù)從應(yīng)用程序消息隊(duì)列里邊接收“單擊鼠標(biāo)左鍵”這一消息,返回值不為0,所以進(jìn)入循環(huán)體,第二個(gè)函數(shù)用來(lái)轉(zhuǎn)換某些鍵盤消息,而我們點(diǎn)的是鼠標(biāo),所以在此直接跳過;第三個(gè)函數(shù),將該消息發(fā)送回Windows。
Windows接收到DispatchMessage()函數(shù)發(fā)送的消息后,它會(huì)自動(dòng)找到應(yīng)把消息發(fā)往的窗口過程。并把消息向其傳遞。之后,進(jìn)入WndProc函數(shù)。你會(huì)感到這是“Windows調(diào)用了WndProc()”,所以WndProc()才被稱為“回調(diào)函數(shù)”。
進(jìn)入WndProc()之后,通過switch()邏輯檢測(cè)接收的信息并做出相應(yīng)的處理和操作。例如,單擊鼠標(biāo)左鍵,由WndProc()函數(shù)掌管的窗口應(yīng)該進(jìn)行怎樣的變化……這些東西要我們自己來(lái)寫嘍。但其中有些東西幾乎是固定的。比如收到WM_DESTROY消息后,一般調(diào)用PostQuitMessage(0)發(fā)送WM_QUIT消息,用來(lái)結(jié)束消息循環(huán),但也不一定,前不久我才寫過一個(gè)雙窗口的程序,當(dāng)關(guān)掉一個(gè)窗口后,你應(yīng)當(dāng)保證另一個(gè)窗口不被關(guān)閉……
當(dāng)WndProc()處理完畢后,DispatchMessage()函數(shù)才返回,這時(shí),又要從GetMessage()函數(shù)開始新一輪的循環(huán)啦~