上一篇 | 下一篇

分析MFC中的映射

发布: 2008-6-26 14:12 | 作者: admin | 来源: | 查看: 4次

条件查找映射

  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(CR99v_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(CR99v_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

   if (message < 0xC000)

   {

   // constant window message

   if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,

   message, 0, 0)) != NULL)

   {

   pMsgCache->lpEntry = lpEntry;

   AfxUnlockGlobals(CR99v_WINMSGCACHE);

   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;

   AfxUnlockGlobals(CR99v_WINMSGCACHE);

   goto LDispatchRegistered;

   }

   lpEntry++; // keep looking past this one

   }

   }

   }

字号: | 推荐给好友

31/3123>

评分:0

我来说两句

网络推荐