比方说,我的主类有一个私人成员是从CTreeView控件派生的类。 我如何处理主类本身的树视图控件的消息?
这与Visual Studios为您构build的MDI基础应用程序类似,您可以在其中获得两个名为CClassView和CFileView的可停靠树视图控件,每个控件都有一个从CTreeView派生的私有成员。
我可以像这样将子成员控件CViewTree的消息传递给我的CFileView类吗?
void CViewTree::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult) { GetParent()->SendMessage(WM_NOTIFY, 0, (LPARAM)pNMHDR); }
这段代码会抛出一个exception,但如果这样做,我将如何处理父类中的TVN_SELCHANGED消息?
编辑:所以我已经尝试了以下build议,但没有任何一个运气。
//First try, in the parent .h file: afx_msg BOOL OnSelChange(NMHDR *pNMHDR, LRESULT *pResult); //In the .cpp file: ON_NOTIFY_REFLECT_EX(TVN_SELCHANGED, OnSelChange) //and BOOL ParentClass::OnSelChange(NMHDR *pNMHDR, LRESULT *pResult) { AfxMessageBox(L"in handler"); Return TRUE; }
第二次尝试:
//in the parent .h file: afx_msg void OnSelChange(NMHDR *pNMHDR, LRESULT *pResult); //In the .cpp file: ON_NOTIFY(TVN_SELCHANGED, AFX_IDW_PANE_FIRST, OnSelChange) //and void ParentClass::OnSelChange(NMHDR *pNMHDR, LRESULT *pResult) { AfxMessageBox(L"in handler"); }
不知道为什么要这么做,由于视图和父视图之间的紧密耦合,代码的可重用性会降低。 如果你想重新使用选择逻辑,你可以将其提取到一个独立的类,如DRAWCLI样本 。
TVN_SELCHANGED已经发送给父母。 但是,MFC的消息反射将通知路由到子窗口中的ON_NOTIFY_REFLECT时出现在子窗口的消息映射。
如果您希望父级在消息处理中拥有发言权,则可以将ON_NOTIFY_REFLECT更改为ON_NOTIFY_REFLECT_EX,并在反射的消息处理程序中返回FALSE。
你将得到一个WM_NOTIFY在父母,所以你处理通知的方式是添加一个ON_NOTIFY宏的树视图的父母,就像你通常做一个对话框上的树控件。 如果您没有指定,则视图的ID可能是AFX_IDW_PANE_FIRST。
盛能够弄清我的问题,现在回头看起来很琐碎。 也许这会帮助其他可能有同样问题的人。
在从Visual Studio 2010中生成的MDI w / visual studio样式程序中,CFileView具有CViewTree的子成员实例。 CViewTree是从CTreeCtrl派生的。
默认情况下,MFC已经将消息传递给子对母链。 答案是确定控制ID从父类中获取通知消息。
所以,首先,我们需要知道树控件的ID。 在CFileView的OnCreate方法中,您可以看到以下代码:
if (!m_wndFileView.Create(dwViewStyle, rectDummy, this, 4))
对于Create方法,MSDN具有以下内容:
virtual BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
在我的例子中,id是4.现在在父(CFileView在这种情况下),只需创建您的ON_NOTIFY宏:
BEGIN_MESSAGE_MAP(CFileView, CDockablePane) //precreated for you ON_NOTIFY(TVN_SELCHANGED, 4, OnSelChanged) //you create this END_MESSAGE_MAP() //precreated for you
我必须手动输入上面的这一行,因为父类的类向导或消息属性没有= TVN_SELCHANGED消息。 接下来,确保您的处理程序方法OnSelChanged在CFileView.h文件中声明为:
afx_msg void OnSelChanged(NMHDR *pNMHDR, LRESULT *pResult);
现在我可以像这样处理TVN_SELCHANGED消息(回到CFileView.cpp中):
void CFileView::OnSelChanged(NMHDR *pNMHDR, LRESULT *pResult) { HTREEITEM item = m_wndFileView.GetSelectedItem(); AfxMessageBox(m_wndFileView.GetItemText(item)); }
在所描述的情况下,如果要通过WM_NOTIFY TVN_SELCHANGED消息从控件CViewTree通知父CFileView,则应该在虚拟OnNotify函数中执行此操作,而不是使用消息映射。 如果OnNotify不符合正确的处理程序,则消息将转到父级CMainFrame,并且您可以使用消息映射。
BOOL CFileView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { if (nmHdr->idFrom != 4) return CDockablePane::OnNotify(wParam, lParam, pResult); if (nmHdr->code == TVN_SELCHANGED) { OnItemsSelChanged((NMHDR*)lParam, pResult); return TRUE; } return FALSE; }