条件查找映射 MFC中大量使用了BEGIN_XXX_MAP这样的宏,以及映射进行查找优化,例如消息映射,OLE命令映射,以及接口等等。每个映射包含一个指向基类的映射的指针。这样,当一个类需要根据一定的条件查找一个对象时,它会查找本类对象,如果没有找到,那么会查找基类,直到根基类。这类查找包含Windows消息,命令,事件和OLE命令的分发,和对象实现的接口的查询等等。
下面是函数BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)的部分代码,演示了如何根据消息的ID查找处理函数。
const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap(); UINT iHash; iHash = (LOWORD((DWORD_PTR)pMessageMap) ^ message) & (iHashMax-1); AfxLockGlobals(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; AfxUnlockGlobals(CRIT_WINMSGCACHE); 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;
#ifdef _AFXDLL for (/* pMessageMap already init'ed */; pMessageMap->pfnGetBaseMap != NULL; pMessageMap = (*pMessageMap->pfnGetBaseMap)()) #else for (/* pMessageMap already init'ed */; pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMap) #endif { // Note: catch not so common but fatal mistake!! // BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd) #ifdef _AFXDLL ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)()); #else ASSERT(pMessageMap != pMessageMap->pBaseMap); #endif
|