标签:
一 基础操作
1 插入节点
1)插入根节点
1 //插入根节点 2 HTREEITEM hRoot; 3 CString str=L"ROOT" 4 hRoot=nTreeCtrl.InsertItem(str); 5 6 //相当于 7 hRoot=nTreeCtrl.InsertItem(str,TVI_ROOT,TVI_LAST);
2)插入孩子节点
1 //添加hRoot节点的孩子节点,并且被添加的节点位于hRoot所有孩子节点的末尾 2 HTREEITEM hChild=nTreeCtrl.InsertItem(str,hRoot); 3 4 //相当于 5 HTREEITEM hChild=nTreeCtrl.InsertItem(str,hRoot,TVI_LAST);
2 获得节点句柄
1 //获得根节点 2 HTREEITEM hRootItem; 3 hRootItem=nTreeCtrl.GetRootItem(); 4 5 6 //获得当前节点 7 HTREEITEM hCurrentItem; 8 hCurrentItem=nTreeCtrl.GetSelectedItem(); 9 10 11 //获得hItem的前一个节点 12 13 HTREEITEM hPreItem; 14 hPreItem=nTreeCtrl.GetNextItem(hItem,TVGN_PREVIOUS); 15 16 17 //获得hItem的下一个节点 18 HTREEITEM hNextItem; 19 hNextItem=nTreeCtrl.GetNextItem(hItem,TVGN_NEXT);
3 判断某节点是否有孩子节点
1 //判断某节点是否有孩子节点 2 if (nTreeCtrl.ItemHasChildren(hRoot))
4 展开或收缩子节点
1 //展开 2 if(nTreeCtrl.ItemHasChildren(hRoot)) 3 nTreeCtrl.Expand(hParentItem,TVE_EXPAND);
5 获得第一个孩子节点的句柄
1 //判断某节点是否有孩子节点 2 if (nTreeCtrl.ItemHasChildren(hRoot)) 3 { 4 //获得孩子节点 5 HTREEITEM hChild=nTreeCtrl.GetChildItem(hRoot); 6 7 }
6 遍历hRoot下一层的所有孩子节点
1 //判断某节点是否有孩子节点 2 if (nTreeCtrl.ItemHasChildren(hRoot)) 3 { 4 //获得孩子节点 5 HTREEITEM hChild=nTreeCtrl.GetChildItem(hRoot); 6 7 //遍历hRoot下一层的所有孩子节点 8 while(hChild) 9 { 10 hChild=nTreeCtrl.GetNextItem(hChild,TVGN_NEXT); 11 12 } 13 14 }
7 获得某节点上的文字
1 //获得某节点上的文字
2 CString str;
3 nTreeCtrl.GetItemText(hRoot);
8 选择某节点,并让其获得焦点
首先,TREE控件的样式必须设置为TVS_SHOWSELALWAYS
其次: 选择该节点
1 treeCtrl.SelectItem(hItem);
最后,设置焦点
1 treeCtrl.SetFocus();
Tree控件设置焦点后,会自动将焦点定位到选择的节点上
9 清空树控件
1 nTreeCtrl.DeleteAllItems();
10 将指定目录下的文件插入节点
1 void InsertPath(CString path, HTREEITEM hRoot, CTreeCtrl& ctrl) 2 { 3 CFileFind nFindFile; 4 CString str=L""; 5 CString nPicFileName=L""; 6 BOOL IsExist=FALSE; 7 HTREEITEM hSubItem; 8 9 nPicFileName.Format(L"%s\\*.*",path); 10 IsExist = nFindFile.FindFile(nPicFileName); 11 while (IsExist) 12 { 13 IsExist = nFindFile.FindNextFile(); 14 if(nFindFile.IsDots()) 15 continue; 16 nPicFileName = nFindFile.GetFileName(); 17 18 //路径 19 if(nFindFile.IsDirectory()) 20 { 21 hSubItem = ctrl.InsertItem(nPicFileName,hRoot); 22 InsertPath(nFindFile.GetFilePath(),hSubItem,ctrl); 23 } 24 else 25 { 26 //文件 27 str = nPicFileName.Right(4); 28 if(!str.CompareNoCase(_T(".jpg")) || !str.CompareNoCase(_T(".tif"))) 29 { 30 ctrl.InsertItem(nPicFileName,hRoot); 31 } 32 } 33 } 34 nFindFile.Close(); 35 }
1 void LoadPath(CString path) //path为指定目录 此函数的作用为将path目录下的文件插入树控件中 2 { 3 CTreeCtrl& ctrl = GetTreeCtrl(); 4 ASSERT(ctrl); 5 ctrl.DeleteAllItems(); 6 HTREEITEM hRoot = ctrl.InsertItem(path); 7 InsertPath(path,hRoot,ctrl); 8 ctrl.Expand(hRoot,TVE_EXPAND); 9 10 }
11 将文件列表中的文件插入树控件中
1 void InsetAllFile( list<CString>& filePathList){ 2 3 4 CTreeCtrl & nTreeCtrl=((CMyTreeView*)(((CMainFrame*)AfxGetMainWnd())->m_SplitterWnd.GetPane(0,0)))->GetTreeCtrl(); 5 nTreeCtrl.DeleteAllItems(); 6 7 list<CString>::iterator it=filePathList.begin(); 8 HTREEITEM hRoot=NULL; 9 CString filePath; 10 CString treeRootName=L"根目录"; //所有的文件都在根目录下 即:默认所有的文件都在同一个目录下 11 12 while(it!=filePathList.end()) 13 { 14 filePath=*it; 15 16 17 18 if(hRoot==NULL) 19 hRoot=nTreeCtrl.InsertItem(treeRootName); //建立根目录 20 21 22 23 if(filePath.Find(treeRootName)==0) // 文件第一层目录与根目录相同,则截去文件第一层目录,文件从第二层目录开始 24 filePath=filePath.Right(filePath.GetLength()-treeRootName.GetLength()-1); 25 26 27 LoadPicFiles(nTreeCtrl,filePath, hRoot); 28 29 it++; 30 } 31 32 }
1 void LoadPicFiles(CTreeCtrl& nTreeCtrl, CString nFilePath, HTREEITEM nRoot) 2 { 3 4 // 判断nPicFolder是目录还是文件 5 // 如果是文件 6 // 直接将文件插入到树控件中 nTreeCtrl.InsertItem(nPicFolder,nRoot); 7 // 如果是目录 8 // 获取nPicFolder的第一层目录 9 // 判断nRoot目录下是否已经有此层目录 10 // 如果有此层目录 11 // 递归插入其他 12 // 如果无此层目录 13 // 插入此层目录,然后递归插入其他 14 15 16 CString nSubFolder; //首层目录 17 CString nSubFilePath; //去掉首层目录后的文件名 18 BOOL IsExist=FALSE; 19 20 21 22 int nIndex=-1; 23 nIndex=nFilePath.Find(L‘\\‘); 24 25 if(nIndex>=0) //目录 26 { 27 nSubFolder=nFilePath.Left(nIndex); 28 nSubFilePath=nFilePath.Right(nFilePath.GetLength()-nIndex-1); 29 30 HTREEITEM nSubRoot=NULL; 31 if(nTreeCtrl.ItemHasChildren(nRoot)) 32 nSubRoot=nTreeCtrl.GetChildItem(nRoot); 33 CString str; 34 BOOL bExist=FALSE; 35 while(nSubRoot) 36 { 37 str=nTreeCtrl.GetItemText(nSubRoot); 38 39 if (str.CompareNoCase(nSubFolder)==0) 40 { 41 42 bExist=TRUE; 43 break; 44 } 45 46 nSubRoot=nTreeCtrl.GetNextSiblingItem(nSubRoot); 47 } 48 49 if(!bExist) 50 { 51 52 nSubRoot=nTreeCtrl.InsertItem(nSubFolder,nRoot); 53 54 LoadPicFiles(nTreeCtrl,nSubFilePath,nSubRoot); 55 }else{ 56 LoadPicFiles(nTreeCtrl,nSubFilePath,nSubRoot); 57 } 58 } 59 else if(nFilePath.Find(L".jpg")!=-1 || nFilePath.Find(L".tif")!=-1) 60 { 61 nTreeCtrl.InsertItem(nFilePath,nRoot); 62 } 63 }
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二 扩展操作
1 响应TVN_ITEMEXPANDING 消息时 如何获得将要展开或收缩的那一个节点的句柄
MSDN:
TVN_ITEMEXPANDING pnmtv = (NM_TREEVIEW FAR *) lParam
。。。。。。。。。
1 typedef struct _NM_TREEVIEW { 2 NMHDR hdr; 3 UINT action; 4 TV_ITEM itemOld; 5 TV_ITEM itemNew; 6 POINT ptDrag; 7 } NM_TREEVIEW; 8 typedef NM_TREEVIEW FAR* LPNM_TREEVIEW; 9
1 typedef struct _TV_ITEM { tvi 2 UINT mask; 3 HTREEITEM hItem; 4 UINT state; 5 UINT stateMask; 6 LPSTR pszText; 7 int cchTextMax; 8 int iImage; 9 int iSelectedImage; 10 int cChildren; 11 LPARAM lParam; } 12 TV_ITEM, FAR* LPTV_ITEM; 13
在 TV_ITEM 的 hItem中 存放着要展开项的句柄
解决:查了这么多,其实很简单 代码如下:
1 void CLeftView::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) 2 { 3 LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); 4 // TODO: 在此添加控件通知处理程序代 5 HTREEITEM htree=pNMTreeView->itemNew.hItem; // 这个就是 将要被扩展或收缩节点的句柄 6 7 。。。 8 }
2 怎么知道CTreeCtrl的一个节点是展开的还是收缩着的
解决:
方法1
1 (GetItemState(hItem, TVIS_EXPANDED )&TVIS_EXPANDED)!=TVIS_EXPANDED //如果相等,则说明改节点是扩展的,如果不相等,则说明该节点是收缩的
方法2
响应TVN_ITEMEXPANDING事件时:
1 void CExampleDlg::OnItemexpandingTree1(NMHDR* pNMHDR, LRESULT* pResult) 2 3 { 4 5 NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; 6 7 if (pNMTreeView->action == TVE_COLLAPSE) //判断action的值 8 9 。。。 10 11 。。。 12 13 }
3 判断节点是否被扩展过
1 1 if ((GetTreeCtrl().GetItemState(hItem,TVIS_EXPANDEDONCE )&TVIS_EXPANDEDONCE )!=0 ) //判断是否扩展过一次,若!=0则说明被扩展过
4 使用 CImageList m_ImageList; 加载位图或图标,并将其与树控件联系在一起,由此便可以设置每个节点的图标
1 CImageList m_ImageList; 2 m_ImageList.Create(12,12,ILC_COLORDDB | ILC_MASK, 3, 1); 3 HICON hAdd=::LoadIcon(::AfxGetInstanceHandle(), (LPCTSTR)IDI_ADD); 4 HICON hRemove=::LoadIcon(::AfxGetInstanceHandle(), (LPCTSTR)IDI_REMOVE); 5 HICON hLeaf=::LoadIcon(::AfxGetInstanceHandle(), (LPCTSTR)IDI_LEAF); 6 m_ImageList.Add(hAdd); 7 m_ImageList.Add(hRemove); 8 m_ImageList.Add(hLeaf); 9 GetTreeCtrl().SetImageList(&m_ImageList,TVSIL_NORMAL); // 树控件和图像列表相连
1 m_treeCtrl.SetItemImage(htree,0,0) // 通过SetItemImage(htree,0,0) 设置节点的图标
5 什么时候响应OnItemexpanding 消息
当节点第一次被展开时,才响应此消息。也就是说:当以开后该节点再展开或收缩时,便不再响应此消息了。
6 设置树控件形式为 TVS_HASBUTTONS|TVS_LINESATROOT 时, 树控件节点前才会出现+ - 号
以下为综合例子: 点击按钮上一个 显示该节点的上一个兄弟节点,并更改控件焦点
设置控件样式:
1 BOOL CTreePathView::PreCreateWindow(CREATESTRUCT& cs) 2 { 3 // TODO: 在此处通过修改 4 // CREATESTRUCT cs 来修改窗口类或样式 5 6 cs.style|=TVS_HASLINES|TVS_SHOWSELALWAYS; //若是想用CImageList的图标 ,则不要设置为TVS_HASBUTTONS形式 7 8 9 return CTreeView::PreCreateWindow(cs); 10 }
点击按钮5(焦点移动到上一个兄弟节点)
1 void NewImageView::OnBnClickedButton5() // 上一个图 2 { 3 // TODO: 在此添加控件通知处理程序代码 4 5 CTreePathView * pTree=(CTreePathView* )(((CMainFrame *)AfxGetMainWnd())->m_wndSplitter.GetPane(0,0)); 6 7 CTreeCtrl & treeCtrl=pTree->GetTreeCtrl(); 8 9 HTREEITEM hItem=treeCtrl.GetSelectedItem(); 10 if (hItem!=NULL) 11 { 12 hItem=treeCtrl.GetNextItem(hItem,TVGN_PREVIOUS); 13 14 if (hItem!=NULL) 15 { 16 CString str; 17 str=pTree->GetFullPath(hItem); 18 SetImage(str); 19 treeCtrl.SelectItem(hItem); 20 treeCtrl.SetFocus(); 21 InvalidateRect(m_ClientRect); 22 } 23 } 24 }
点击按钮6(焦点移动到下一个兄弟节点)
1 void NewImageView::OnBnClickedButton6() //下一个 2 { 3 // TODO: 在此添加控件通知处理程序代码 4 5 CTreePathView * pTree=(CTreePathView* )(((CMainFrame *)AfxGetMainWnd())->m_wndSplitter.GetPane(0,0)); 6 CTreeCtrl & treeCtrl=pTree->GetTreeCtrl(); 7 HTREEITEM hItem=treeCtrl.GetSelectedItem(); 8 9 if (hItem!=NULL) 10 { 11 hItem=treeCtrl.GetNextItem(hItem,TVGN_NEXT); 12 13 if (hItem!=NULL) 14 { 15 CString str; 16 str=pTree->GetFullPath(hItem); 17 SetImage(str); 18 19 treeCtrl.SelectItem(hItem); 20 treeCtrl.SetFocus(); 21 InvalidateRect(m_ClientRect); 22 } 23 } 24 }
7 遍历树控件的所有节点
1) 获得根节点句柄
1 CTreeCtrl& nTreeCtrl=((CImportTreeView*)m_SplitterWnd.GetPane(0,0))->GetTreeCtrl(); 2 3 HTREEITEM hItem; 4 //获得根目录节点 5 hItem = nTreeCtrl.GetRootItem(); 6 //遍历树控件节点 7 TreeVisit(&nTreeCtrl,hItem);
2)遍历所有节点
1 void TreeVisit(CTreeCtrl* pCtrl,HTREEITEM hItem) 2 { 3 if(pCtrl->ItemHasChildren(hItem)) 4 { 5 HTREEITEM hChildItem = pCtrl->GetChildItem(hItem); 6 while(hChildItem!=NULL) 7 { 8 TreeVisit(pCtrl,hChildItem); //递归遍历孩子节点 9 hChildItem = pCtrl->GetNextItem(hChildItem, TVGN_NEXT); 10 } 11 } 12 else // 对叶子节点进行操作 13 Leaf(pCtrl,hItem); 14 }
8 获得某Item节点的全路径
1 CString m_ParentFolder[10]; 2 CString m_OldParentFolder[10];
1 //--------------------将nParent添加到nParentFolder[10]第一位---------------------- 2 BOOL AddParentFolder(CString nParentFolder[10], CString nParent) 3 { 4 for(int i=9;i>0;i--) 5 nParentFolder[i]=nParentFolder[i-1]; 6 nParentFolder[0]=nParent; 7 return TRUE; 8 } 9 10 //---------------------nParentFolder[10]中的有效数据整合(加\)--------------------- 11 CString AllCString(CString nParentFolder[10]) 12 { 13 CString nAllCString=L""; 14 for(int i=0;i<10;i++) 15 { 16 if(nParentFolder[i]==L"") break; 17 nAllCString+=L"\\"+nParentFolder[i]; 18 } 19 return nAllCString; 20 }
获得Item节点路径的函数
1 CString GetItemPath(CTreeCtrl* pCtrl,HTREEITEM hItem) 2 { 3 CString nSelItemName=pCtrl->GetItemText(hItem); 4 5 HTREEITEM parentItem=pCtrl->GetParentItem(hItem); 6 7 if (parentItem==NULL) //hItem即为根目录 8 return nSelItemName; 9 10 //清空OLD 11 for(int i=0;i<10;i++) m_OldParentFolder[i]=L""; 12 13 //m_OldParentFolder 记录上一个节点的父节点 14 for(int i=0;i<10;i++) 15 m_OldParentFolder[i]=m_ParentFolder[i]; 16 17 //m_ParentFolder 记录当前节点的父亲节点 18 for(int i=0;i<10;i++) 19 m_ParentFolder[i]=L""; 20 21 CString itemPath; 22 CString parentFolder=nSelItemName; 23 24 //将parentFolder添加到m_ParentFolder[0],其他值依次后移 25 AddParentFolder(m_ParentFolder,parentFolder); 26 27 28 29 // m_PicFolder 为根节点对应的名字 30 while(parentItem!=NULL&&pCtrl->GetItemText(parentItem).Compare(m_PicFolder)) 31 { 32 parentFolder=pCtrl->GetItemText(parentItem); 33 AddParentFolder(m_ParentFolder,parentFolder); 34 parentItem=pCtrl->GetParentItem(parentItem); 35 36 } 37 38 itemPath.Format(L"%s%s",m_PicFolder,AllCString(m_ParentFolder)); 39 40 //清空OLD 41 for(int i=0;i<10;i++) m_OldParentFolder[i]=L""; 42 //清空 43 for(int i=0;i<10;i++) 44 m_ParentFolder[i]=L""; 45 46 return itemPath; 47 48 }
获得叶子节点的函数
1 void Leaf(CTreeCtrl* pCtrl,HTREEITEM hItem) 2 { 3 4 CString itemName=pCtrl->GetItemText(hItem); 5 6 // 叶子节点是jpg文件或tif文件 7 if(nSelItemName.Find(L".jpg")!=-1 || nSelItemName.Find(L".tif")!=-1) 8 { 9 10 //m_OldParentFolder 记录上一个节点的父节点 11 for(int i=0;i<10;i++) 12 m_OldParentFolder[i]=m_ParentFolder[i]; 13 14 //m_ParentFolder 记录当前节点的父亲节点 15 for(int i=0;i<10;i++) 16 m_ParentFolder[i]=L""; 17 18 CString imgPath=L""; 19 CString parentFolder=itemName; 20 21 //将parentFolder添加到m_ParentFolder[0],其他值依次后移 22 AddParentFolder(m_ParentFolder,parentFolder); 23 24 HTREEITEM parentItem=pCtrl->GetParentItem(hItem); 25 26 // m_imgPath 为根节点对应的名字 27 while(pCtrl->GetItemText(parentItem).Compare(m_imgPath)) 28 { 29 parentFolder=pCtrl->GetItemText(parentItem); 30 AddParentFolder(m_ParentFolder,parentFolder); 31 parentItem=pCtrl->GetParentItem(parentItem) 32 33 } 34 35 // 获得叶子节点的全路径 36 imgPath.Format(L"%s%s",m_imgPath,AllCString(m_ParentFolder)); 37 38 } 39 40 41 // 对imgPath 所指的文件进行操作 42 ShowPic(imgPath); 43 44 45 }
上述方法过于繁杂,再来了简洁些的
使用栈,依次将本节点-->根节点入栈 出栈时顺序便为根节点-->本节点
1)叶子节点
1 //本地是否存在此文章 2 void CMainFrame::PostPath(CTreeCtrl& nTreeCtrl, HTREEITEM hItem,CString &path) 3 { 4 stack<HTREEITEM> itemStack; 5 while (hItem!=nTreeCtrl.GetRootItem ()) 6 { 7 itemStack.push(hItem); 8 hItem=nTreeCtrl.GetParentItem (hItem); 9 } 10 itemStack.push(nTreeCtrl.GetRootItem ()); 11 CString itemName; 12 while (!itemStack.empty()) 13 { 14 hItem=(HTREEITEM)itemStack.top(); 15 itemStack.pop(); 16 itemName=nTreeCtrl.GetItemText (hItem); 17 path+=itemName; 18 path+=L"\\"; 19 } 20 path.TrimRight(L"\\"); 21 path+=L".xml"; 22 }
2)目录节点
1 void CMainFrame::DirPath(CTreeCtrl& nTreeCtrl, HTREEITEM nRoot,CString &path) 2 { 3 stack<HTREEITEM> itemStack; 4 while (hItem!=nTreeCtrl.GetRootItem ()) 5 { 6 itemStack.push(hItem); 7 hItem=nTreeCtrl.GetParentItem (hItem); 8 } 9 itemStack.push(nTreeCtrl.GetRootItem ()); 10 CString itemName; 11 while (!itemStack.empty()) 12 { 13 hItem=(HTREEITEM)itemStack.top(); 14 itemStack.pop(); 15 itemName=nTreeCtrl.GetItemText (hItem); 16 path+=itemName; 17 path+=L"\\"; 18 } 19 }
9 获得树中所有叶子节点的父目录
即:树中可能有许多枝干,获取这些枝干的路径
1 std::vector<CString> m_BookDirectory; //存放所有叶子节点的父目录
1 void GetBookDirectory(CTreeCtrl* pCtrl,HTREEITEM hItem) 2 { 3 4 if(pCtrl->ItemHasChildren(hItem)) 5 { 6 HTREEITEM hChildItem = pCtrl->GetChildItem(hItem); 7 while(hChildItem!=NULL) 8 { 9 GetBookDirectory(pCtrl,hChildItem); //递归遍历孩子节点 10 11 if(pCtrl->ItemHasChildren(hChildItem)) 12 hChildItem = pCtrl->GetNextItem(hChildItem, TVGN_NEXT); 13 else 14 break; 15 } 16 } 17 else 18 { 19 HTREEITEM parentItem=pCtrl->GetParentItem(hItem); 20 CString bookPath=GetItemPath(pCtrl,parentItem); 21 22 m_BookDirectory.push_back(bookPath); 23 24 } 25 }
1 CTreeCtrl& nTreeCtrl=((CImportTreeView*)m_SplitterWnd.GetPane(0,0))->GetTreeCtrl(); 2 HTREEITEM hItem; 3 hItem = nTreeCtrl.GetRootItem(); 4 5 m_BookDirectory.clear(); 6 GetBookDirectory(&nTreeCtrl,hItem); //获得几本书 及书的路径
10 利用InsertItem、SetItemData 存放与该节点有关的数字信息
1 HTREEITEM InsertItem( 2 LPCTSTR lpszItem, 3 int nImage, //实测范围0-65535 4 int nSelectedImage, 5 HTREEITEM hParent = TVI_ROOT, 6 HTREEITEM hInsertAfter = TVI_LAST 7 ); 8
存放65535以上的大数据时 用SetItemData
A 32-bit application-specific value
1 BOOL SetItemData(HTREEITEM hItem,DWORD_PTR dwData );
来自:http://blog.csdn.net/shuilan0066/article/details/6638504
标签:
原文地址:http://www.cnblogs.com/lpxblog/p/4607346.html