一,消息映射機(jī)制
1,消息響應(yīng)函數(shù):(例:在CDrawView類(lèi)響應(yīng)鼠標(biāo)左鍵按下消息)
1)在頭文件(DrawView.h)中聲明消息響應(yīng)函數(shù)原型。
//{{AFX_MSG(CDrawView) //注釋宏
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
//}}AFX_MSG //注釋宏
說(shuō)明:
在注釋宏之間的聲明在VC中灰色顯示。afx_msg宏表示聲明的是一個(gè)消息響應(yīng)函數(shù)。
這個(gè)注釋宏為的是讓ClassWizard能夠分辨出哪些代碼是它生成的,哪些是你自己寫(xiě)的。
你自己寫(xiě)的代碼要在這個(gè)注釋之外,這樣ClassWizard再修改消息映射的時(shí)候就不會(huì)管你的代碼了。
限于以前的硬件速度,ClassWizard比較傻冒,所以需要這些注釋宏來(lái)定位。從7.0開(kāi)始,就不再需
要了。新的屬性頁(yè)能夠自動(dòng)分析你的代碼,為你添加或者刪除代碼,而無(wú)需什么特殊標(biāo)記的幫忙。
因此注釋宏已經(jīng)是歷史產(chǎn)物了。
2)在源文件(DrawView.cpp)中進(jìn)行消息映射。
BEGIN_MESSAGE_MAP(CDrawView, CView)
//}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
說(shuō)明:
在宏BEGIN_MESSAGE_MAP()與END_MESSAGE_MAP()之間進(jìn)行消息映射。
宏ON_WM_LBUTTONDOWN()把消息WM_LBUTTONDOWN與它的響應(yīng)函數(shù)OnLButtonDown()相關(guān)聯(lián)。這樣一旦有消息的產(chǎn)生,就會(huì)自動(dòng)調(diào)用相關(guān)聯(lián)的消息響應(yīng)函數(shù)去處理。
宏ON_WM_LBUTTONDOWN()定義如下:
#define ON_WM_LBUTTONDOWN()
{ WM_LBUTTONDOWN, 0, 0, 0, AfxSig_vwp,
(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT, CPoint))&OnLButtonDown },
3)源文件中進(jìn)行消息響應(yīng)函數(shù)處理。(DrawView.cpp中自動(dòng)生成OnLButtonDown函數(shù)輪廓,如下)
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonDown(nFlags, point);
}
說(shuō)明:
可見(jiàn)當(dāng)增加一個(gè)消息響應(yīng)處理,在以上三處進(jìn)行了修改。可在消息響應(yīng)函數(shù)里添加消息處理代碼完成對(duì)消息的響應(yīng)、處理。
2,消息響應(yīng)的方式:
1)
在基類(lèi)中針對(duì)每種消息做一個(gè)虛函數(shù),當(dāng)子類(lèi)對(duì)消息響應(yīng)時(shí)候,只要在子類(lèi)中重寫(xiě)這個(gè)虛函數(shù)即可。缺點(diǎn):MFC類(lèi)派生層次很多,如果在基類(lèi)對(duì)每個(gè)消息進(jìn)行虛函
數(shù)處理,那么從基類(lèi)派生的每個(gè)子類(lèi)都將背負(fù)一個(gè)龐大的虛表,這樣浪費(fèi)內(nèi)存,故MFC沒(méi)有采取這中方式而采取消息映射方式。
2)消息映射方式:
MFC在后臺(tái)維護(hù)了一個(gè)句柄和C++對(duì)象指針對(duì)照表,當(dāng)收到一個(gè)消息后,通過(guò)消息結(jié)構(gòu)里資源句柄(查對(duì)照表)就可找到與它對(duì)應(yīng)的一個(gè)C++對(duì)象指針,然后
把這個(gè)指針傳給基類(lèi),基類(lèi)利用這個(gè)指針調(diào)用WindowProc()函數(shù)對(duì)消息進(jìn)行處理,WindowProc()函數(shù)中調(diào)用OnWndMsg()函數(shù),
真正的消息路由及處理是由OnWndMsg()函數(shù)完成的。由于WindowProc()和OnWndMsg()都是虛函數(shù),而且是用派生類(lèi)對(duì)象指針調(diào)用
的,由多態(tài)性知最總終調(diào)用子類(lèi)的。在OnWndMsg()函數(shù)處理的時(shí)候,根據(jù)消息種類(lèi)去查找消息映射,判斷所發(fā)的消息有沒(méi)有響應(yīng)函數(shù),具體方式是到相關(guān)
的頭文件和源文件中尋找消息響應(yīng)函數(shù)聲明(從注釋宏//}AFX_MSG之間尋找),消息映射(從宏BEGIN_MESSAGE_MAP(...)....END_MESSAGE_MAP()之間尋找),最終找到對(duì)應(yīng)的消息處理函數(shù)。當(dāng)然,如果子類(lèi)中沒(méi)有對(duì)消息進(jìn)行處理,則消息交由基類(lèi)處理。
說(shuō)明:
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);