LRESULT CALLBACK WindowProc(HWND hwnd, <1>.隊列消息和非隊列消息 從消息的發(fā)送途徑上看,消息分兩種:隊列消息和非隊列消息,。 這里,,對消息隊列闡述如下:
從消息的來源來看,,可以分為:系統(tǒng)定義的消息和應(yīng)用程序定義的消息,。 系統(tǒng)消息ID的范圍是從0到WM_USER-1,或0X80000到0XBFFFF,;應(yīng)用程序消息從WM_USER(0X0400)到0X7FFF,,或0XC000到0XFFFF;WM_USER到0X7FFF范圍的消息 4.測試 while(GetMessage(&msg, NULL, 0, 0))
{ char buf[1024]; sprintf_s(buf, 1024, "hWnd:%d uMsg: %d WParam: %d LParam: %d\n", msg.hwnd, msg.message, msg.wParam, msg.lParam); std::cout<<buf; TranslateMessage(&msg); DispatchMessage(&msg); }
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: HDhdc = GetDC (hwnd) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; TextOut(hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1), szBuffer, wsprintf(szBuffer, szFormat, TEXT ("WM_COMMAND"), HIWORD(wParam), LOWORD(wParam), HIWORD(lParam), LOWORD(lParam)) ); ReleaseDC (hwnd, hdc) ; ValidateRect (hwnd, &rect) ; break ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } <2>.運行結(jié)果 一個窗口,,窗口上有一個按鈕子窗口,然后還有一個控制臺,,輸出消息循環(huán)中的每條消息,,當(dāng)父窗口收到 WM_COMMAND 消息時, 會在屏幕上輸出,。 (1). 當(dāng)鼠標(biāo)在父窗口上移動時: 可見父窗口 hWnd: 461982,,uMsg : 521 ( WM_MOUSEMOVE ),從線程消息隊列中取出的,。 (2). 當(dāng)鼠標(biāo)在按鈕子窗口上移動時: 可見按鈕 hWnd: 462118,,uMsg : 521 ( WM_MOUSEMOVE),從線程消息隊列中取出的,。 (3). 當(dāng)鼠標(biāo)在父窗口上點擊時: 父窗口收到了 513(WM_LBUTTONDOWN), 514(WM_LBUTTONUP) 消息,,從線程消息隊列中取出的。 (4). 當(dāng)鼠標(biāo)在按鈕窗口上點擊時: 按鈕窗口從線程的消息隊列中取出了 513(WM_LBUTTONDOWN), 514(WM_LBUTTONUP) 消息,,父窗口收到了WM_COMMAND 消息,,TextOut 繪制出 WM_COMMAND 文本。 我在 WM_COMMAND 的消息處理語句處打有斷點,,看下圖: 可見,,窗口過程是被系統(tǒng)調(diào)用的,調(diào)用時系統(tǒng)傳入的參數(shù)值為: hwnd: 0x00070c9e,,十進制就是461982,,父窗口句柄; message: 273 (WM_COMMAND) wParam: ... lParam: ... 具體是WinMain中的哪一個函數(shù)中最后調(diào)用了 窗口過程 WndProc 呢,,見下圖: 原來是在 DispatchMessage 函數(shù)中,,再看看參數(shù)的值: msg.hwnd: 0x00070d26,,十進制是462118,是按鈕窗口的句柄; msg.message: 514 ( WM_LBUTTONUP ) 哦~~~~,,原來是操作系統(tǒng)在從該線程的消息隊列中取出按鈕的 WM_LBUTTONUP (鼠標(biāo)左鍵釋放) 消息后,,調(diào)用 DispatchMessage 分派消息,DispatchMessage 會先將 WM_LBUTTONUP 消息分派到按鈕的窗口過程(系統(tǒng)默認(rèn)有),, 這里的分派到按鈕的窗口過程就是調(diào)用俺就的窗口過程,,然后又以 按鈕的父窗口的句柄為 窗口過程的第一個 參數(shù), WM_COMMAND 為窗口過程的第二個參數(shù) 調(diào)用了 父窗口的窗口過程,,也就是將 WM_COMMAND 消息分發(fā)到了父窗口,,從而使父窗口得到了通知。這些,,都是 Windows 來完成的,,應(yīng)用程序只需要在相應(yīng)的窗口 過程中處理相應(yīng)的消息。 從上面,,我們還可以看出,,WM_COMMAND 是非隊列消息,直接分派到目的窗口過程,,而不是放入到消息隊列中,, 讓消息循環(huán)去取。 總結(jié): 簡而言之,, 標(biāo)準(zhǔn)Windows消息發(fā)送到產(chǎn)生窗口,,通知消息(WM_COMMAND, WM_NOTIFY)發(fā)送到父窗口,這是Windows 的標(biāo)準(zhǔn)消息處理過程,,MFC對 Window API 進行了封裝,,有自己的一套消息處理流程, 消息順著一條路徑流動,,需要 處理的對象可以添加消息響應(yīng)函數(shù)處理之,,對于命令消息,它有 CView , CDocument, CMainFram , CWinApp 一系列處理 節(jié)點,,對于通知消息,,MFC還加入一種很好的機制:消息反射,就是父窗口收到子窗口發(fā)出的通知消息后,,會將此消息 發(fā)送給子窗口,,先讓子窗口處理,如果子窗口不處理,,父窗口再處理之,,這樣有利于將所有消息處理代碼都集成了子窗口 中,有利于控件的開發(fā),。MFC的消息處理,,我不予詳細(xì)討論了,,有興趣的可以參考侯捷的<<深入淺出MFC>>。 |
|