(MFC) How does a parent class receive control messages if the control is a private member?

Say my main class has a private member, which is a class derived from the CTreeView control. How can I handle messages from this tree view control in the main class?

This is similar to the basic MDI application that Visual Studios creates for you, where you have two managed tree controls named CClassView and CFileView, and each of them has a private member derived from CTreeView.

Can I pass a message from a CViewTree child control to my CFileView class as follows?

void CViewTree::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult) { GetParent()->SendMessage(WM_NOTIFY, 0, (LPARAM)pNMHDR); } 

This code throws an exception, but if it really works, how would I handle the TVN_SELCHANGED message in the parent class?

Edit: So I tried the following sentences, but didn't have much luck with any of them.

 //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; } 

Second attempt:

 //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"); } 
+4
source share
3 answers

Not sure why you want to do this, you have less opportunity to reuse the code because you have a tight connection between the view and the parent. If you want to reuse selection logic, you can extract it into a separate class, for example, the DRAWCLI sample .

TVN_SELCHANGED has already been sent to the parent. However, reflection MFC sends a notification to the message card of the child window when ON_NOTIFY_REFLECT is present in the child element.

If you want the parent to also have a word in message processing, you can change ON_NOTIFY_REFLECT to ON_NOTIFY_REFLECT_EX and return FALSE to the reflected message handler.

You will receive WM_NOTIFY from the parent, so the way you process the notification is to add the ON_NOTIFY macro to the parent tree, as you usually do to manage the tree in the dialog box. The view identifier is most likely AFX_IDW_PANE_FIRST if you did not specify it.

+7
source
Shen was able to figure out my problem, which was looking back, was pretty trivial. Perhaps this will help others who may have the same question.

In the MDI w / visual studio program that I created from Visual Studio 2010, CFileView has a child instance of CViewTree. CViewTree was obtained from CTreeCtrl.

By default, MFC already sends messages to the child-parent chain. The answer is to determine the identifier of the control to receive notifications in the parent class.

So, firstly, we need to know the identifier of the tree. In the OnCreate CFileView method, you can see this code:

 if (!m_wndFileView.Create(dwViewStyle, rectDummy, this, 4)) 

For Create MSDN method for Create method:

 virtual BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ); 

In my example, id is 4. Now in the parent (CFileView in this case) just create the ON_NOTIFY macro as such:

 BEGIN_MESSAGE_MAP(CFileView, CDockablePane) //precreated for you ON_NOTIFY(TVN_SELCHANGED, 4, OnSelChanged) //you create this END_MESSAGE_MAP() //precreated for you 

I had to type the line above manually because the master of the class or message property for the parent did not have the message = TVN_SELCHANGED. Then, make sure that the OnSelChanged handler method is declared in the CFileView.h file as follows:

 afx_msg void OnSelChanged(NMHDR *pNMHDR, LRESULT *pResult); 

Now I can process a TVN_SELCHANGED message like this (back to CFileView.cpp):

 void CFileView::OnSelChanged(NMHDR *pNMHDR, LRESULT *pResult) { HTREEITEM item = m_wndFileView.GetSelectedItem(); AfxMessageBox(m_wndFileView.GetItemText(item)); } 
+2
source

In the described case, if you want to notify the CFileView parent from the CViewTree control with the message WM_NOTIFY TVN_SELCHANGED, you must do this in the OnNotify virtual function without using the message map. If OnNotify does not satisfy the correct handler, the message is sent to the parent CMainFrame, and there you can use the message map.

 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; } 
0
source

Source: https://habr.com/ru/post/1447545/


All Articles