今天突然发现在工程CE中在TOOLBAR【ConfigurationEditorToolBar】上面的button在MainFrame中的消息响应函数不一样。
MainFrame中创建了ToolBar,在这个ToolBar上面有4个按钮,一个是Reload, 其他一组是copy, delete, new三个按钮。在MainFrame中有两个消息响应函数,
BEGIN_MESSAGE_MAP(CMainFrame, TransActiveFrame)
//{{AFX_MSG_MAP(CMainFrame)
ON_COMMAND(ID_APP_RELOAD, onReload) //响应Reload 按钮
//}}AFX_MSG_MAP
ON_COMMAND_RANGE(ConfigurationEditorToolBar::WM_TOOLBAR_BEGIN,ConfigurationEditorToolBar::WM_TOOLBAR_END,onToolBarItemSelected)
//响应copy,delete,
END_MESSAGE_MAP()
原来ON_COMMAND和ON_COMMAND_RANGE宏展开后是不一样的,
ON_COMMAND:
#define ON_COMMAND(id, memberFxn) /
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSig_vv , (AFX_PMSG)&memberFxn },
ON_COMMAND_RANGE:
#define ON_COMMAND_RANGE(id, idLast, memberFxn) /
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)idLast, AfxSig_vw , /
(AFX_PMSG)(void (AFX_MSG_CALL CCmdTarget::*)(UINT))&memberFxn },
由于这个不同,从而造成在
文件路径:/Microsoft Visual Studio/VC98/MFC/SRC/CMDTARG.CPP
AFX_STATIC BOOL AFXAPI _AfxDispatchCmdMsg(CCmdTarget* pTarget, UINT nID, int nCode,
AFX_PMSG pfn, void* pExtra, UINT nSig, AFX_CMDHANDLERINFO* pHandlerInfo)
{
.....
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)(); //调用Reload响应函数void CMainFrame::onReload()
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); //调用copy, delete, new的响应函数void CMainFrame::onToolBarItemSelected(UINT nID)
break;
} //switch end
...
}
关于MFC的消息响应在vckbase上面发表的这篇文章描述的很详细,http://www.vckbase.com/document/viewdoc/?id=1048
但是他没有我上面提到的分派command消息的区别。这里面解释了很重要的一个函数CCmdTarget::OnCmdMsg,函数原型如下:
virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo);
该函数是一个虚函数,CWnd没有该函数的实现,其他像CView, CFrame,CDocument等都提供了该函数的实现.这也是解释为什么CDocument没有窗口也能实现消息传递的答案所在。