MFC

mfc 메시지 관련 좋은 자료

디버그정 2008. 8. 31. 13:49
첨부한 자료에 메시지 구분을 잘못한 부분이 있다.

queued message의 경우 키스트로크 (WM_KEYDOWN / WM_KEYUP등)과 키스트로크에 의한 문자(WM_CHAR), 마우스 이동(WM_MOUSEMOVE), 마우스 클릭(WM_LBUTTONDOWN), 타이머 메세지(WM_TIMER), 그리기 메세지 (WM_PAINT), 종료 메세지(WM_QUIT)가 있으며,

non-queued message는 그 외의 다른 모든 메시지가 되겠다.



가운데 메시지맵에서 찾는 부분에 빠진 부분이 있다. 중요한 루프 부분이다.
다음과 같다.

BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
 LRESULT lResult = 0;

 // special case for commands
 if (message == WM_COMMAND)
 {
  if (OnCommand(wParam, lParam))
  {
   lResult = 1;
   goto LReturnTrue;
  }
  return FALSE;
 }

 // special case for notifies
 if (message == WM_NOTIFY)
 {
  NMHDR* pNMHDR = (NMHDR*)lParam;
  if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
   goto LReturnTrue;
  return FALSE;
 }

 // special case for activation
 if (message == WM_ACTIVATE)
  _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));

 // special case for set cursor HTERROR
 if (message == WM_SETCURSOR &&
  _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
 {
  lResult = 1;
  goto LReturnTrue;
 }

 const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
 UINT iHash; iHash = (LOWORD((DWORD)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 != 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(CRIT_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(CRIT_WINMSGCACHE);
      goto LDispatchRegistered;
     }
     lpEntry++;      // keep looking past this one
    }
   }
  }

  pMsgCache->lpEntry = NULL;
  AfxUnlockGlobals(CRIT_WINMSGCACHE);
  return FALSE;
 }
 ASSERT(FALSE);      // not reached

LDispatch:
이하는 wincore.cpp 파일 참조~~~~


귤러윈도우메시지가 들어왔다.(예를 들어 mouse_move)
그러면 pMessageMap 을 통해서 메시지맵을 가져오고(여기에는 자신의 메시지맵과 상위클레스의 메시지맵 포인터를 가지고 있쥐)
Cash를 통해 최근의 메시지는 모아놓는다. 왜냐하면 자주 발생하는 메시지를 바로 처리하기 위해서…
그래서 여기를 뒤져보고…그리고 여기에 저장되어 있는 메시지이면 처리를 하고,

Else
아니면 cash를 업데이트하고 for문을 돌려서 AfxFindMessageEntry를 통해 Message가 있는지 확인한다.
여기서 pMessagemap 은 가져온 메시지 맵이다.