1 .树视图风格:TVS_HASBUTTONS; // 在父项旁边显示(+)和(-) TVS_HASLINES; // 使用线条显示各项之间的层次 TVS_LINESATROOT; // 使用线条链接树视图控件根部各项 2 .处理单击事件:TVN_SELCHANGED void CTreeCtrlDlg::OnTvnSelchangedTree1(NMHDR * pNMHDR, LRESULT * pResult) ... { LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 HTREEITEM ht=m_treeCtrl.GetSelectedItem(); CString strSelect=m_treeCtrl.GetItemText(ht); m_strTreeVal=strSelect; UpdateData(FALSE); *pResult = 0;} 3 .同时让自己派生的CMyTreeCtrl类和对话框处理TVN_SELCHANGED消息:只须在CMyTreeCtrl中处理以下消息,并返回FALSE就OK了ON_NOTIFY_REFLECT_EX(TVN_SELCHANGED, OnTvnSelchanged) OnTvnSelchanged的签名如下BOOL CMyTreeCtrl::OnTvnSelchanged(NMHDR * pNMHDR,LRESULT * pResult) 4 .编辑标签:要允许编辑树视图控件中的文本,可以设置以下三个步骤 1 .设置树视图的TVS_EDITLABELS风格TVS_EDITLABE可以通过资源编辑框内部修改(Edit labels),也可以用代码的方式修改,如下 long lStyle = ::GetWindowLong(m_treeCtrl.GetSafeHwnd(),GWL_STYLE); lStyle |= TVS_EDITLABELS; ::SetWindowLong(m_treeCtrl.GetSafeHwnd(),GWL_STYLE,lStyle) 2 .处理TVN_BEGINLABELEDIT通知消息 // 设置相关限制,如限制编辑框字符串长度 CEdit * pEdit = GetEditControl(); // 获取当前选中结点编辑框 ASSERT(pEdit); if (pEdit) ... { pEdit->LimitText(15);//设置编辑框文本长度为15个字符串 *pResult = 0; } 3 .处理TVN_ENDLABLEEDIT通知消息 HTREEITEM hParent = GetParentItem(pTVDispInfo -> item.hItem); // 获取父结点 HTREEITEM hChild = GetChildItem(hParent ? hParent:TVI_ROOT); // 获取第一个根结点 hChild = GetNextSiblingItem(hChild); // 获取下一个兄弟节点 if (pTVDispInfo -> item.hItem != hChild) // 判断是否与当前节点相同 pTVDispInfo -> item.pszText // 获取当前节点的字符串 CString strText = GetItemText(hChild); // 获取节点的字符串 3 .让树视图处理Esc和Enter键重载PreTranslateMessage函数BOOL bHandleMsg = FALSE; switch (pMsg -> message) ... { case VK_ESCAPE: case VK_RETURN: if (::GetKeyState(VK_CONTROL)&0x8000) ...{ break; } if (GetEditControl()) ...{ ::TranslateMessage(pMsg); ::DispatchMessage(pMsg); bHandleMsg=TRUE; } break; } 4 .实现上下文菜单在WM_RBUTTONDOWN消息处理函数上实现上下文菜单 5 .展开和收起树视图结点:HTREEITEM hItem = GetRootItem(); // 获取根结点,可能会有多个根结点 ItemHasChildren(hParent) // 判断结点是否有孩子结点 hItem = GetChildItem(hParent); // 获取第一个子结点 hItem = GetNextSiblingItem(hItem)); // 获取下一个兄弟结点结点 Expand(hItem,bExpand ? TVE_EXPAND:TVE_COLLAPSE); // 展开/叠起结点 Select(hItem,TVGN_FIRSTVISIBLE); // 设置选中结点 CString str = GetItemText(hChild); // 获取结点字符串信息 HTREEITEM hCurrSel = GetSelectedItem(); // 获取当前选中结点 SelectItem(hNewSel);HTREEITEM hNewSel = HitTest(pt, & nFlags); // 判断坐标是否在当前结点范围内 HTREEITEM hItem = InsertItem(dlg.m_strItemText,hItemParent); // 插入结点 #pragma once // 定义文件MyTreeCtrl.h // CMyTreeCtrl class CMyTreeCtrl : public CTreeCtrl ... { DECLARE_DYNAMIC(CMyTreeCtrl)public: CMyTreeCtrl(); virtual ~CMyTreeCtrl();protected: DECLARE_MESSAGE_MAP() void ExpandBranch(HTREEITEM hItem,BOOL bExpand =TRUE);public: void ExpandAllBranches(BOOL bExpand =TRUE); BOOL DoesItemExist(HTREEITEM hItemParent, CString const& strItem); afx_msg void OnRButtonDown(UINT nFlags, CPoint point); afx_msg void OnAddItem(); virtual BOOL PreTranslateMessage(MSG* pMsg); afx_msg void OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult); afx_msg void OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult); afx_msg BOOL OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult);} ; // MyTreeCtrl.cpp : 实现文件 #include " stdafx.h " #include " TreeCtrl.h " #include " MyTreeCtrl.h " #include " .mytreectrl.h " #include " AddItemDlg.h " // CMyTreeCtrl IMPLEMENT_DYNAMIC(CMyTreeCtrl, CTreeCtrl)CMyTreeCtrl::CMyTreeCtrl() ... {} CMyTreeCtrl:: ~ CMyTreeCtrl() ... {} BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl) ON_WM_RBUTTONDOWN() ON_COMMAND(IDR_ADD_ITEM, OnAddItem) ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnTvnEndlabeledit) ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnTvnBeginlabeledit) ON_NOTIFY_REFLECT_EX(TVN_SELCHANGED, OnTvnSelchanged)END_MESSAGE_MAP() // CMyTreeCtrl 消息处理程序 void CMyTreeCtrl::ExpandBranch(HTREEITEM hItem,BOOL bExpand /**/ /* =TRUE */ ) // 展开 ... { if (ItemHasChildren(hItem)) //判断是否有孩子结点 ...{ Expand(hItem,bExpand?TVE_EXPAND:TVE_COLLAPSE); //展开/叠起结点 hItem=GetChildItem(hItem);//获取第一个子结点 do ...{ ExpandBranch(hItem); } while(hItem=GetNextSiblingItem(hItem));//获取兄弟结点 }} void CMyTreeCtrl::ExpandAllBranches(BOOL bExpand /**/ /* =TRUE */ ) ... { HTREEITEM hItem=GetRootItem();//获取根结点,可能会有多个根结点 do ...{ ExpandBranch(hItem,bExpand); } while(hItem=GetNextSiblingItem(hItem)); Select(hItem,TVGN_FIRSTVISIBLE);//设置选中结点} BOOL CMyTreeCtrl::DoesItemExist(HTREEITEM hItemParent, CString const & strItem) ... { BOOL bDoesItemExist=FALSE; ASSERT(strItem.GetLength()); HTREEITEM hChild=GetChildItem(hItemParent?hItemParent:TVI_ROOT); while (NULL!=hChild&&!bDoesItemExist) ...{ CString str=GetItemText(hChild);//获取结点字符串信息 if (0==str.CompareNoCase(strItem)) ...{ bDoesItemExist=TRUE; } else ...{ hChild=GetNextSiblingItem(hChild); } } return bDoesItemExist;} void CMyTreeCtrl::OnRButtonDown(UINT nFlags, CPoint point) ... { // TODO: 在此添加消息处理程序代码和/或调用默认值 // set focus to the tree control SetFocus(); // map the point that is passed to the // function from client coordinates // to screen coordinates ClientToScreen(&point); // Get the currently selected item HTREEITEM hCurrSel = GetSelectedItem();//获取当前选中结点 // Figure out which item was right clicked CPoint pt(0, 0); ::GetCursorPos(&pt); ScreenToClient (&pt); HTREEITEM hNewSel = HitTest(pt, &nFlags); // Set the selection to the item that the // mouse was over when the user right // clicked if (NULL == hNewSel) ...{ SelectItem(NULL); } else if (hCurrSel != hNewSel) ...{ SelectItem(hNewSel); SetFocus(); } // Load the context menu CMenu Menu; if (Menu.LoadMenu(IDM_CONTEXT_MENU)) ...{ CMenu* pSubMenu = Menu.GetSubMenu(0); if (pSubMenu!=NULL) ...{ // Display the context menu pSubMenu->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); } } } void CMyTreeCtrl::OnAddItem() // 添加上下文菜单 ... { // TODO: 在此添加命令处理程序代码 HTREEITEM hItemParent=GetSelectedItem(); //获取当前选中结点 CAddItemDlg dlg; if (dlg.DoModal()==IDOK) ...{ if (!DoesItemExist(hItemParent,dlg.m_strItemText)) ...{ HTREEITEM hItem=InsertItem(dlg.m_strItemText,hItemParent); //插入结点 SelectItem(hItem); } else ...{ AfxMessageBox("已存在相同结点"); } } } BOOL CMyTreeCtrl::PreTranslateMessage(MSG * pMsg) ... { // TODO: 在此添加专用代码和/或调用基类 BOOL bHandledMsg = FALSE; switch (pMsg->message) ...{ case WM_KEYDOWN: ...{ switch (pMsg->wParam) ...{ case VK_ESCAPE: case VK_RETURN: if (::GetKeyState(VK_CONTROL) & 0x8000) ...{ break; } if (GetEditControl()) ...{ ::TranslateMessage(pMsg); ::DispatchMessage(pMsg); bHandledMsg = TRUE; } break; default: break; } // switch (pMsg->wParam) } // WM_KEYDOWN break; default: break; } // switch (pMsg->message) // continue normal translation and dispatching return (bHandledMsg ?TRUE : CTreeCtrl::PreTranslateMessage(pMsg));} void CMyTreeCtrl::OnTvnBeginlabeledit(NMHDR * pNMHDR, LRESULT * pResult) ... { LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 *pResult=1; CEdit*pEdit=GetEditControl(); ASSERT(pEdit); if (pEdit) ...{ pEdit->LimitText(15); *pResult=0; } } void CMyTreeCtrl::OnTvnEndlabeledit(NMHDR * pNMHDR, LRESULT * pResult) ... { LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 BOOL bValidItem=FALSE; CString strItem=pTVDispInfo->item.pszText; if (0<strItem.GetLength()) ...{ HTREEITEM hParent=GetParentItem(pTVDispInfo->item.hItem); bValidItem=!DoesItemExist(hParent,strItem); } *pResult = bValidItem;} BOOL CMyTreeCtrl::OnTvnSelchanged(NMHDR * pNMHDR, LRESULT * pResult) ... { LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 TRACE(GetItemText(pNMTreeView->itemNew.hItem)); TRACE(" "); *pResult = 0; return FALSE; //返回FALSE可以让父窗口进行进一步的处理} 转自 http://hi.baidu.com/leafiness/blog/item/12fc87031c7c71753812bb05.html