Windows消息投递流程:一般窗口消息投递(WM_LBUTTONCLICK)

本例通过在单文档程序的视图中添加WM_LBUTTONCLICK消息处理函数,来解释一般窗口消息的投递流程。 基于VS 2005

BEGIN_MESSAGE_MAP(CMyView, CView) ON_WM_LBUTTONDBLCLK() END_MESSAGE_MAP() // ON_WM_LBUTTONDBLCLK宏展开 #define ON_WM_LBUTTONDBLCLK() / { WM_LBUTTONDBLCLK, 0, 0, 0, AfxSig_vwp, / (AFX_PMSG)(AFX_PMSGW) / (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > ( &ThisClass :: OnLButtonDblClk)) },

 

从上面的代码可以看出WM_LBUTTONCLICK消息的类型标签是AfxSig_vwp, 在afxmsg_.h中有一个枚举类型AfxSig,消息标签主要用于区分消息处理函数的类型。该类型中定义了AfxSig_vwp的值:

 

enum AfxSig { //... AfxSig_vWp = AfxSig_v_W_p //... }

 

 

在AfxWndProc中,将消息中的句柄映射成窗口类指针,这个指针指向CMyView。AfxWndProc调用AfxCallWndProc,AfxCallWndProc调用CWnd::WindowProc,CWnd::WindowProc调用CWnd::OnWndMsg,CWnd::OnWndMsg完成对消息的处理。

 

// wincore.cpp 1746 BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { // ... // GetMessageMap是个虚函数,因为当前指针是指向CMyView,所以取到的是CMyView的消息映射表 const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap(); UINT iHash; iHash = (LOWORD((DWORD_PTR)pMessageMap) ^ message) & (iHashMax-1); winMsgLock.Lock(CRIT_WINMSGCACHE); // 全局消息散列缓存,查找缓存 AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash]; const AFX_MSGMAP_ENTRY* lpEntry; if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap) { // cache hit lpEntry = pMsgCache->lpEntry; winMsgLock.Unlock(); if (lpEntry == NULL) return FALSE; // cache hit, and it needs to be handled if (message < 0xC000) goto LDispatch; // 系统消息? else goto LDispatchRegistered; // 已注册消息? } else { // not in cache, look for it pMsgCache->nMsg = message; pMsgCache->pMessageMap = pMessageMap; for (/* pMessageMap already init'ed */; pMessageMap->pfnGetBaseMap != NULL; pMessageMap = (*pMessageMap->pfnGetBaseMap)()) { // Note: catch not so common but fatal mistake!! // BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd) ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)()); if (message < 0xC000) { // constant window message if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries, message, 0, 0)) != NULL) { pMsgCache->lpEntry = lpEntry; winMsgLock.Unlock(); goto LDispatch; } } else { // registered windows message lpEntry = pMessageMap->lpEntries; while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL) { UINT* pnID = (UINT*)(lpEntry->nSig); ASSERT(*pnID >= 0xC000 || *pnID == 0); // must be successfully registered if (*pnID == message) { pMsgCache->lpEntry = lpEntry; winMsgLock.Unlock(); goto LDispatchRegistered; } lpEntry++; // keep looking past this one } } } pMsgCache->lpEntry = NULL; winMsgLock.Unlock(); return FALSE; } // ... LDispatch: mmf.pfn = lpEntry->pfn; switch (lpEntry->nSig) { //... case AfxSig_v_u_p: // 消息标签 { CPoint point(lParam); (this->*mmf.pfn_v_u_p)(static_cast<UINT>(wParam), point); } break; //... } //... LDispatchRegistered: // for registered windows messages ASSERT(message >= 0xC000); ASSERT(sizeof(mmf) == sizeof(mmf.pfn)); mmf.pfn = lpEntry->pfn; lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam); } // 消息处理函数类型枚举 union MessageMapFunctions { AFX_PMSG pfn; // generic member function pointer // ... LRESULT (AFX_MSG_CALL CWnd::*pfn_l_w_l)(WPARAM, LPARAM); }; 

 

 

你可能感兴趣的:(windows,cache,function,null,文档)