简体   繁体   中英

Adding item to CTreectrl C++

I have a requirement of converting a project from VB to C++.

There is Tree control in VB. For adding items to Tree control "Add" Method(Nodes Collection) has been used, which contains a parameter called "key" and the same key can be retrieved on click of that particular item.

Is there any such provision in CTreeCtrl InsertItem function using TVITEM or TVITEMEX structure where we can add a key to each item of the tree control and get it back when clicked on it?

To create your root item:

TV_INSERTSTRUCT tvInsertStruct;
tvInsertStruct.hParent=NULL;
tvInsertStruct.hInsertAfter=TVI_LAST;
tvInsertStruct.item.pszText=_T("ROOT");
tvInsertStruct.item.mask=TVIF_TEXT;

const HTREEITEM hRootItem= m_tree.InsertItem(&tvInsertStruct);

To insert sub-items hanging on the root:

for(int i=0; i<SomeCollection.GetCount(); i++)
{
    const CElement* pElement= SomeCollection.GetAt(i);
    ASSERT(pElement);

    CString Name = pElement->GetName();

    tvInsertStruct.hParent = hRootItem;
    tvInsertStruct.hInsertAfter = TVI_LAST;
    const LPTSTR cutJobNameTemp = Name.GetBuffer(0);
    tvInsertStruct.item.pszText = cutJobNameTemp;
    tvInsertStruct.item.mask = TVIF_TEXT;

    HTREEITEM hItem = m_tree.InsertItem(&tvInsertStruct);       
    ASSERT(hItem);      
    tree.SetItemData(hItem, (DWORD_PTR)pElement);
}

The code line that answers your question is SetItemData : with it you can directly associate a tree node handle with a memory address.111

To see all nodes open just add:

ExpandTreeCtrl(m_tree);

NOTE: I know the following is not the cleanest approach to handle the selection of an item on the tree, so I replaced it with a more proper way that also handles keyboard

To get an entry point for your app to respond to Clicks on the tree, you can add in its parent dialog (or control)'s message map

 ON_NOTIFY(NM_CLICK, IDC_TREE, OnNMClickTree) 

and implement its handling function

 void CMyDialog::OnNMClickTree(NMHDR *pNMHDR, LRESULT *pResult) { UINT flags; CPoint point; GetCursorPos(&point); *pResult= 0; CTreeCtrl* pTree= dynamic_cast <CTreeCtrl*> (this->GetDlgItem(pNMHDR->idFrom)); if(pTree) { pTree->ScreenToClient(&point); HTREEITEM hItem = pTree->HitTest(point, &flags); if( (flags & TVHT_ONITEMINDENT) || (flags & TVHT_ONITEMBUTTON) ) //do nothing when clicking on the [+]expand / [-]collapse of the tree return; if(!hItem) return; // If you want to get item text: CString sText= pTree->GetItemText(hItem); //To get your element: CElement* pElement = (CElement*)pTree->GetItemData(hItem); } } 

To get an entry point for your app to respond to the change of the currently selected item on the tree, you can add in its parent dialog (or control)'s message map

void CMyDialog::OnTreeCtrlSelChanged(NMHDR* pNMHDR, LRESULT* pResult)
{
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*) pNMHDR;
    HTREEITEM hItem = pNMTreeView->itemNew.hItem;

    if(!hItem)
        return;

    // If you want to get item text:
    CString sText= m_tree.GetItemText(hItem);

    //To get your element:
    CElement* pElement = (CElement*)m_tree.GetItemData(hItem);
}

and implement its handling function

 void CMyDialog::OnTreeCtrlSelChanged(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*) pNMHDR; HTREEITEM hItem = pNMTreeView->itemNew.hItem; if(!hItem) return; // If you want to get item text: CString sText= m_tree.GetItemText(hItem); //To get your element: CElement* pElement = (CElement*)m_tree.GetItemData(hItem); } 

The line that is now dereferencing to access the CElement data associated with the tree node is GetItemData . Then do what you intend with the pointer you got.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM