MFC消息的路由

首先消息分三類,分別是窗口消息,命令消息,通告消息。其中窗口消息的“流動(dòng)”是很規(guī)則的,只是縱向流動(dòng),只能從派生類流到基類,最終“流到”基類CCmdTarget...絕無“旁逸斜出”的可能。命令消息和通告消息則不同。下面以命令消息來講述命令消息的“路由”。


當(dāng)dispatch一個(gè)消息時(shí),消息首先由AfxWndProc分發(fā),在經(jīng)由AfxCallWndProc保存消息,最終調(diào)用對(duì)應(yīng)的WindowProc.在WindowProc中判斷是否是命令消息或者通告消息,是的話,分別交由OnCommand和OnNotify處理。不是的話最后交給窗口過程處理。下面討論命令消息的路由。

?不妨假設(shè)調(diào)用了CFrameWnd::OnCmdMsg,

BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode)

{

... ...

?CView* pView = GetActiveView();

?if (pView->OnCmdMsg(nID, nCode))//(1)

return TRUE;

... ...

?if (CWnd::OnCmdMsg(nID, nCode))//(4)

return TRUE;

... ...

?CWinApp* pApp = AfxGetApp();

?if (pApp->OnCmdMsg(nID, nCode))//(5)

return TRUE;

?return FALSE;

}

由于在CFrameWnd中有CView* m_pViewActive; GetActiveView函數(shù)返回的就是與這個(gè)框架窗口關(guān)聯(lián)的視類對(duì)象。流程轉(zhuǎn)到(1),

(1):pView->OnCmdMsg,于是

BOOL CView::OnCmdMsg(UINT nID, int nCode)

{

... ...

?if (CWnd::OnCmdMsg(nID, nCode))?//(2)

return TRUE;

?BOOL bHandled = FALSE;

?bHandled = m_pDocument->OnCmdMsg(nID, nCode);//(3)

return bHandled;

}

消息最終由視類中的OnCmdMsg處理,而視類的OnCmdMsg并沒有改寫,所以最終調(diào)用CCmdTarge::OnCmdMsg(),這個(gè)函數(shù)最終會(huì)調(diào)用_AfxDispatchCmdMsg[文章的最好附注該函數(shù)的定義]對(duì)命令消息進(jìn)行分發(fā)處理[其他的分析和這個(gè)類似。],如果沒處理,再交由(3),由與這個(gè)視類關(guān)聯(lián)的文檔類處理。其中CDocument* m_pDocument;是CView的成員變量。如果(2),(3)都沒處理,則流程返回(4),由框架類處理,如果框架類也沒處理,則轉(zhuǎn)到(5),由應(yīng)用程序類處理。這就是命令消息的處理流程。


AFX_STATIC BOOL AFXAPI _AfxDispatchCmdMsg(CCmdTarget* pTarget, UINT nID, int nCode,

AFX_PMSG pfn, void* pExtra, UINT nSig, AFX_CMDHANDLERINFO* pHandlerInfo)

// return TRUE to stop routing

{

ASSERT_VALID(pTarget);

UNUSED(nCode);// unused in release builds

union MessageMapFunctions mmf;

mmf.pfn = pfn;

BOOL bResult = TRUE; // default is ok

if (pHandlerInfo != NULL)

{

// just fill in the information, don't do it

pHandlerInfo->pTarget = pTarget;

pHandlerInfo->pmf = mmf.pfn;

return TRUE;

}

switch (nSig)

{

case AfxSig_vv:

// normal command or control notification

ASSERT(CN_COMMAND == 0);// CN_COMMAND same as BN_CLICKED

ASSERT(pExtra == NULL);

(pTarget->*mmf.pfn_COMMAND)();

break;

case AfxSig_bv:

// normal command or control notification

ASSERT(CN_COMMAND == 0);// CN_COMMAND same as BN_CLICKED

ASSERT(pExtra == NULL);

bResult = (pTarget->*mmf.pfn_bCOMMAND)();

break;

case AfxSig_vw:

// normal command or control notification in a range

ASSERT(CN_COMMAND == 0);// CN_COMMAND same as BN_CLICKED

ASSERT(pExtra == NULL);

(pTarget->*mmf.pfn_COMMAND_RANGE)(nID);

break;

case AfxSig_bw:

// extended command (passed ID, returns bContinue)

ASSERT(pExtra == NULL);

bResult = (pTarget->*mmf.pfn_COMMAND_EX)(nID);

break;

case AfxSig_vNMHDRpl:

{

AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;

ASSERT(pNotify != NULL);

ASSERT(pNotify->pResult != NULL);

ASSERT(pNotify->pNMHDR != NULL);

(pTarget->*mmf.pfn_NOTIFY)(pNotify->pNMHDR, pNotify->pResult);

}

break;

case AfxSig_bNMHDRpl:

{

AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;

ASSERT(pNotify != NULL);

ASSERT(pNotify->pResult != NULL);

ASSERT(pNotify->pNMHDR != NULL);

bResult = (pTarget->*mmf.pfn_bNOTIFY)(pNotify->pNMHDR, pNotify->pResult);

}

break;

case AfxSig_vwNMHDRpl:

{

AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;

ASSERT(pNotify != NULL);

ASSERT(pNotify->pResult != NULL);

ASSERT(pNotify->pNMHDR != NULL);

(pTarget->*mmf.pfn_NOTIFY_RANGE)(nID, pNotify->pNMHDR,

pNotify->pResult);

}

break;

case AfxSig_bwNMHDRpl:

{

AFX_NOTIFY* pNotify = (AFX_NOTIFY*)pExtra;

ASSERT(pNotify != NULL);

ASSERT(pNotify->pResult != NULL);

ASSERT(pNotify->pNMHDR != NULL);

bResult = (pTarget->*mmf.pfn_NOTIFY_EX)(nID, pNotify->pNMHDR,

pNotify->pResult);

}

break;

case AfxSig_cmdui:

{

// ON_UPDATE_COMMAND_UI or ON_UPDATE_COMMAND_UI_REFLECT case

ASSERT(CN_UPDATE_COMMAND_UI == (UINT)-1);

ASSERT(nCode == CN_UPDATE_COMMAND_UI || nCode == 0xFFFF);

ASSERT(pExtra != NULL);

CCmdUI* pCmdUI = (CCmdUI*)pExtra;

ASSERT(!pCmdUI->m_bContinueRouting);// idle - not set

(pTarget->*mmf.pfn_UPDATE_COMMAND_UI)(pCmdUI);

bResult = !pCmdUI->m_bContinueRouting;

pCmdUI->m_bContinueRouting = FALSE;// go back to idle

}

break;

case AfxSig_cmduiw:

{

// ON_UPDATE_COMMAND_UI case

ASSERT(nCode == CN_UPDATE_COMMAND_UI);

ASSERT(pExtra != NULL);

CCmdUI* pCmdUI = (CCmdUI*)pExtra;

ASSERT(pCmdUI->m_nID == nID);// sanity assert

ASSERT(!pCmdUI->m_bContinueRouting);// idle - not set

(pTarget->*mmf.pfn_UPDATE_COMMAND_UI_RANGE)(pCmdUI, nID);

bResult = !pCmdUI->m_bContinueRouting;

pCmdUI->m_bContinueRouting = FALSE;// go back to idle

}

break;

// general extensibility hooks

case AfxSig_vpv:

(pTarget->*mmf.pfn_OTHER)(pExtra);

break;

case AfxSig_bpv:

bResult = (pTarget->*mmf.pfn_OTHER_EX)(pExtra);

break;

default:// illegal

ASSERT(FALSE);

return 0;

}

return bResult;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容