MFC 消息反射 的用法
MFC的消息反射,主要是用在 控件的封装和继承
因为控件为了方便使用,要自己处理通知,但是为灵活性,要开放给用户使用。
以MFC VisualStadio 风格的默认界面为例,树节点的双击事件怎么用。
1. 在CViewTree 中处理树节点双击事件的方法:
1.1 用类向导或手工加入通知处理,默认是通知反射。
BEGIN_MESSAGE_MAP(CViewTree, CTreeCtrl)
ON_NOTIFY_REFLECT(NM_DBLCLK, &CViewTree::OnNMDblclk)
END_MESSAGE_MAP()
1.2 写响应函数:
void CViewTree::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
{
HTREEITEM htItem = GetSelectedItem();
*pResult = 0;
}
2.在CFileView 中处理树节点双击事件的方法:
2.1 手工加入通知处理,这里不是反射,而是正常的通知。4是TreeCtrl的ID。
BEGIN_MESSAGE_MAP(CFileView, CDockablePane)
ON_NOTIFY(NM_DBLCLK, 4, &CFileView::OnDblClkTree)
END_MESSAGE_MAP()
2.2 写响应函数:
void CFileView::OnDblClkTree(NMHDR* pNMHDR, LRESULT* pResult)
{
HTREEITEM hTreeItem = m_wndFileView.GetSelectedItem();
*pResult = 0;
}
控件的优先级高于父窗口,也就是同时在CViewTree,CFileView 中定义响应函数,只有CViewTree会执行。若要CFileView执行必须在CViewTree中删除对应的消息响应。
但是所谓的子窗口返回FALSE,父窗口可以执行又是什么呢?
3. 在CViewTree 和 CFileView 中同时处理树节点双击事件的方法:
或者说在CViewTree中控制,是否CFileView可以执行通知响应。
这里用到了扩展通知反射:
3.1 手工加入扩展通知反射处理:
BEGIN_MESSAGE_MAP(CViewTree, CTreeCtrl)
ON_NOTIFY_REFLECT_EX(NM_DBLCLK, &CViewTree::OnNMDblclkEx)
END_MESSAGE_MAP()
3.2 写响应函数,注意响应函数是BOOL类型的:
BOOL CViewTree::OnNMDblclkEx(NMHDR *pNMHDR, LRESULT *pResult)
{
HTREEITEM htItem = GetSelectedItem();
*pResult = 0;
//return true; // CFileView中不执行OnDblClkTree
return false; //CFileView中执行OnDblClkTree
}
这样CViewTree就可以控制父子窗口如何执行了。
4 注:这个问题混淆了好久,主要问题处在:
4.1 VisualStadio 的类向导在创建树的通知处理时默认用的是ON_NOTIFY_REFLECT, 而CFileView中没有对应的向导创建。ON_NOTIFY和 ON_NOTIFY_REFLECT_EX 都也是要手工添加的。
4.2 网上对消息反射的解释总是包含返回值控制父窗口的执行,而实际上向导默认是没这个功能的,导致会把*pResult = 0; 这个误解为返回值。

浙公网安备 33010602011771号