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 은 가져온 메시지 맵이다.
'MFC' 카테고리의 다른 글
DECLARE_DYNCREATE()와 IMPLEMENT_DYNCREATE() 다른이 글 고찰 발췌 - 실행중 타입정보 (1) | 2008.08.31 |
---|---|
MFC 내부구조 #2 MFC Internals - 대충 읽어볼 글 (1) | 2008.08.31 |
MFC 내부구조 #1 MFC Internals - 대충 읽어볼 글 (0) | 2008.08.31 |
[MFC Hole]CWnd::SubclassWindow(), CWnd::UnsubclassWindow() (0) | 2008.08.31 |
mfc internal - 메시지 맵 및 라우팅 자세한 설명 (0) | 2008.08.30 |
novtable 사용의미 (1) | 2008.08.30 |
MFC 메시지 맵과 메시지 핸들링 원리 (0) | 2008.08.30 |