美文网首页
MFC消息的路由

MFC消息的路由

作者: 酸豆角炒腰花儿 | 来源:发表于2022-07-26 14:50 被阅读0次

首先消息分三类,分别是窗口消息,命令消息,通告消息。其中窗口消息的“流动”是很规则的,只是纵向流动,只能从派生类流到基类,最终“流到”基类CCmdTarget...绝无“旁逸斜出”的可能。命令消息和通告消息则不同。下面以命令消息来讲述命令消息的“路由”。

当dispatch一个消息时,消息首先由AfxWndProc分发,在经由AfxCallWndProc保存消息,最终调用对应的WindowProc.在WindowProc中判断是否是命令消息或者通告消息,是的话,分别交由OnCommand和OnNotify处理。不是的话最后交给窗口过程处理。下面讨论命令消息的路由。

 不妨假设调用了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函数返回的就是与这个框架窗口关联的视类对象。流程转到(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并没有改写,所以最终调用CCmdTarge::OnCmdMsg(),这个函数最终会调用_AfxDispatchCmdMsg[文章的最好附注该函数的定义]对命令消息进行分发处理[其他的分析和这个类似。],如果没处理,再交由(3),由与这个视类关联的文档类处理。其中CDocument* m_pDocument;是CView的成员变量。如果(2),(3)都没处理,则流程返回(4),由框架类处理,如果框架类也没处理,则转到(5),由应用程序类处理。这就是命令消息的处理流程。

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;

相关文章

  • MFC消息的路由

    首先消息分三类,分别是窗口消息,命令消息,通告消息。其中窗口消息的“流动”是很规则的,只是纵向流动,只能从派生类流...

  • VC++(四)简单绘图

    MFC消息映射机制 MFC消息映射机制的具体实现方法是:在每个能接收和处理消息的类中,定义一个消息和消息函数静态对...

  • Chain of Responsibility模式(行为型)

    问题 熟悉VC/MFC的都知道,VC是”基于消息,事件驱动“,消息在VC开发中起着举足经重的作用。在MFC中,消息...

  • MFC的消息机制

    1. 消息映射机制 1.1 消息映射机制的含义 MFC使用消息映射机制来处理消息,拥有一个消息与消息处理函数一一对...

  • MFC的自定义控件之消息机制

    MFC消息机制 MFC是使用一种消息映射机制来处理消息,在应用程序框架中的表现就是一个消息与消息处理函数一一对应的...

  • MFC动态按钮的创建及其消息响应 和 自定义消息]

    MFC动态按钮的创建及其消息响应 和 自定义消息

  • peerconnection_client的MainWnd分析(

    MainWnd中使用的就是MFC的消息机制,在此复习一下MFC吧 在MainWnd::Create()中,调用Re...

  • MFC 快速入门

    概述 MFC微软基础类库的作用在Windows平台做GUI开发使用 MFC框架设计思想 Windows消息机制 S...

  • windows消息机制(MFC)

    windows消息机制(MFC) 消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,...

  • SIP路由机制解析

    SIP中存在两种路由场景: 1,请求消息的路由 2,响应消息的路由 其中,响应消息的路由非常简单,就是完全依靠Vi...

网友评论

      本文标题:MFC消息的路由

      本文链接:https://www.haomeiwen.com/subject/eiuoirtx.html