一 基础操作
1 插入节点
1)插入根节点
-
-
HTREEITEM hRoot;
-
CString str=L"ROOT"
-
hRoot=nTreeCtrl.InsertItem(str);
-
-
-
hRoot=nTreeCtrl.InsertItem(str,TVI_ROOT,TVI_LAST);
2)插入孩子节点
-
-
HTREEITEM hChild=nTreeCtrl.InsertItem(str,hRoot);
-
-
-
HTREEITEM hChild=nTreeCtrl.InsertItem(str,hRoot,TVI_LAST);
2 获得节点句柄
-
-
HTREEITEM hRootItem;
-
hRootItem=nTreeCtrl.GetRootItem();
-
-
-
-
HTREEITEM hCurrentItem;
-
hCurrentItem=nTreeCtrl.GetSelectedItem();
-
-
-
-
-
HTREEITEM hPreItem;
-
hPreItem=nTreeCtrl.GetNextItem(hItem,TVGN_PREVIOUS);
-
-
-
-
HTREEITEM hNextItem;
-
hNextItem=nTreeCtrl.GetNextItem(hItem,TVGN_NEXT);
3 推断某节点是否有孩子节点
-
-
if (nTreeCtrl.ItemHasChildren(hRoot))
4 展开或收缩子节点
-
-
if(nTreeCtrl.ItemHasChildren(hRoot))
-
nTreeCtrl.Expand(hParentItem,TVE_EXPAND);
5 获得第一个孩子节点的句柄
-
-
if (nTreeCtrl.ItemHasChildren(hRoot))
-
{
-
-
HTREEITEM hChild=nTreeCtrl.GetChildItem(hRoot);
-
-
}
6 遍历hRoot下一层的全部孩子节点
-
-
if (nTreeCtrl.ItemHasChildren(hRoot))
-
{
-
-
HTREEITEM hChild=nTreeCtrl.GetChildItem(hRoot);
-
-
-
while(hChild)
-
{
-
hChild=nTreeCtrl.GetNextItem(hChild,TVGN_NEXT);
-
-
}
-
-
}
7 获得某节点上的文字
-
-
CString str;
-
nTreeCtrl.GetItemText(hRoot);
8 选择某节点。并让其获得焦点
首先,TREE控件的样式必须设置为TVS_SHOWSELALWAYS
其次: 选择该节点
-
treeCtrl.SelectItem(hItem);
最后,设置焦点
Tree控件设置焦点后,会自己主动将焦点定位到选择的节点上
9 清空树控件
-
<strong> nTreeCtrl.DeleteAllItems();</strong>
10 将指定文件夹下的文件插入节点
-
void InsertPath(CString path, HTREEITEM hRoot, CTreeCtrl& ctrl)
-
{
-
CFileFind nFindFile;
-
CString str=L"";
-
CString nPicFileName=L"";
-
BOOL IsExist=FALSE;
-
HTREEITEM hSubItem;
-
-
nPicFileName.Format(L"%s\\*.*",path);
-
IsExist = nFindFile.FindFile(nPicFileName);
-
while (IsExist)
-
{
-
IsExist = nFindFile.FindNextFile();
-
if(nFindFile.IsDots())
-
continue;
-
nPicFileName = nFindFile.GetFileName();
-
-
-
if(nFindFile.IsDirectory())
-
{
-
hSubItem = ctrl.InsertItem(nPicFileName,hRoot);
-
InsertPath(nFindFile.GetFilePath(),hSubItem,ctrl);
-
}
-
else
-
{
-
-
str = nPicFileName.Right(4);
-
if(!str.CompareNoCase(_T(".jpg")) || !str.CompareNoCase(_T(".tif")))
-
{
-
ctrl.InsertItem(nPicFileName,hRoot);
-
}
-
}
-
}
-
nFindFile.Close();
-
}
-
void LoadPath(CString path)
-
{
-
CTreeCtrl& ctrl = GetTreeCtrl();
-
ASSERT(ctrl);
-
ctrl.DeleteAllItems();
-
HTREEITEM hRoot = ctrl.InsertItem(path);
-
InsertPath(path,hRoot,ctrl);
-
ctrl.Expand(hRoot,TVE_EXPAND);
-
-
}
11 将文件列表中的文件插入树控件中
-
void InsetAllFile( list<CString>& filePathList){
-
-
-
CTreeCtrl & nTreeCtrl=((CMyTreeView*)(((CMainFrame*)AfxGetMainWnd())->m_SplitterWnd.GetPane(0,0)))->GetTreeCtrl();
-
nTreeCtrl.DeleteAllItems();
-
-
list<CString>::iterator it=filePathList.begin();
-
HTREEITEM hRoot=NULL;
-
CString filePath;
-
CString treeRootName=L"根文件夹";
-
-
while(it!=filePathList.end())
-
{
-
filePath=*it;
-
-
-
-
if(hRoot==NULL)
-
hRoot=nTreeCtrl.InsertItem(treeRootName);
-
-
-
-
if(filePath.Find(treeRootName)==0)
-
filePath=filePath.Right(filePath.GetLength()-treeRootName.GetLength()-1);
-
-
-
LoadPicFiles(nTreeCtrl,filePath, hRoot);
-
-
it++;
-
}
-
-
}
-
void LoadPicFiles(CTreeCtrl& nTreeCtrl, CString nFilePath, HTREEITEM nRoot)
-
{
-
-
-
-
-
-
-
-
-
-
-
-
-
-
CString nSubFolder;
-
CString nSubFilePath;
-
BOOL IsExist=FALSE;
-
-
-
-
int nIndex=-1;
-
nIndex=nFilePath.Find(L‘\\‘);
-
-
if(nIndex>=0)
-
{
-
nSubFolder=nFilePath.Left(nIndex);
-
nSubFilePath=nFilePath.Right(nFilePath.GetLength()-nIndex-1);
-
-
HTREEITEM nSubRoot=NULL;
-
if(nTreeCtrl.ItemHasChildren(nRoot))
-
nSubRoot=nTreeCtrl.GetChildItem(nRoot);
-
CString str;
-
BOOL bExist=FALSE;
-
while(nSubRoot)
-
{
-
str=nTreeCtrl.GetItemText(nSubRoot);
-
-
if (str.CompareNoCase(nSubFolder)==0)
-
{
-
-
bExist=TRUE;
-
break;
-
}
-
-
nSubRoot=nTreeCtrl.GetNextSiblingItem(nSubRoot);
-
}
-
-
if(!bExist)
-
{
-
-
nSubRoot=nTreeCtrl.InsertItem(nSubFolder,nRoot);
-
-
LoadPicFiles(nTreeCtrl,nSubFilePath,nSubRoot);
-
}else{
-
LoadPicFiles(nTreeCtrl,nSubFilePath,nSubRoot);
-
}
-
}
-
else if(nFilePath.Find(L".jpg")!=-1 || nFilePath.Find(L".tif")!=-1)
-
{
-
nTreeCtrl.InsertItem(nFilePath,nRoot);
-
}
-
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二 扩展操作
1 响应TVN_ITEMEXPANDING 消息时 怎样获得将要展开或收缩的那一个节点的句柄
MSDN:
<strong>TVN_ITEMEXPANDING</strong> <em><a target=_blank target="_blank" class="synParam" href="http://blog.csdn.net/shuilan0066/article/details/6638504" style="color: rgb(255, 153, 0); text-decoration: none;">pnmtv</a></em> <strong>= (NM_TREEVIEW FAR *)</strong> <em>lParam</em>
pnmtv
- Pointer to an NM_TREEVIEW structure.
The itemNew member is aTVITEM structure that contains valid information about the parent
item in thehItem,state, andlParam members. Theaction member indicates whether the list is to expand or collapse. For a list of possible values, see the description of theTVM_EXPAND message.
。。。
。
。。
。。。
-
typedef struct _NM_TREEVIEW {
-
NMHDR hdr;
-
UINT action;
-
TV_ITEM itemOld;
-
TV_ITEM itemNew;
-
POINT ptDrag;
-
} NM_TREEVIEW;
-
typedef NM_TREEVIEW FAR* LPNM_TREEVIEW;
-
-
typedef struct _TV_ITEM { tvi
-
UINT mask;
-
HTREEITEM hItem;
-
UINT state;
-
UINT stateMask;
-
LPSTR pszText;
-
int cchTextMax;
-
int iImage;
-
int iSelectedImage;
-
int cChildren;
-
LPARAM lParam; }
-
TV_ITEM, FAR* LPTV_ITEM;
-
在 TV_ITEM 的 hItem中 存放着要展开项的句柄
解决:查了这么多,事实上非常easy 代码例如以下:
-
void CLeftView::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
-
{
-
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
-
-
HTREEITEM htree=pNMTreeView->itemNew.hItem;
-
-
。。。
-
}
2 怎么知道CTreeCtrl的一个节点是展开的还是收缩着的
解决:
方法1
-
<strong> (GetItemState(hItem, TVIS_EXPANDED )&TVIS_EXPANDED)!=TVIS_EXPANDED
方法2
响应TVN_ITEMEXPANDING事件时:
-
void CExampleDlg::OnItemexpandingTree1(NMHDR* pNMHDR, LRESULT* pResult)
-
-
{
-
-
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
-
-
if (pNMTreeView->action == TVE_COLLAPSE)
-
-
。。。
-
-
。。。
-
-
}
3 推断节点是否被扩展过
-
if ((GetTreeCtrl().GetItemState(hItem,TVIS_EXPANDEDONCE )&TVIS_EXPANDEDONCE )!=0 )
4 使用 CImageList m_ImageList; 载入位图或图标。并将其与树控件联系在一起。由此便能够设置每一个节点的图标
-
CImageList m_ImageList;
-
m_ImageList.Create(12,12,ILC_COLORDDB | ILC_MASK, 3, 1);
-
HICON hAdd=::LoadIcon(::AfxGetInstanceHandle(), (LPCTSTR)IDI_ADD);
-
HICON hRemove=::LoadIcon(::AfxGetInstanceHandle(), (LPCTSTR)IDI_REMOVE);
-
HICON hLeaf=::LoadIcon(::AfxGetInstanceHandle(), (LPCTSTR)IDI_LEAF);
-
m_ImageList.Add(hAdd);
-
m_ImageList.Add(hRemove);
-
m_ImageList.Add(hLeaf);
-
GetTreeCtrl().SetImageList(&m_ImageList,TVSIL_NORMAL);
-
m_treeCtrl.SetItemImage(htree,0,0)
5 什么时候响应OnItemexpanding 消息
当节点第一次被展开时,才响应此消息。也就是说:当以开后该节点再展开或收缩时,便不再响应此消息了。
6 设置树控件形式为 TVS_HASBUTTONS|TVS_LINESATROOT 时, 树控件节点前才会出现+ - 号
下面为综合样例: 点击button上一个 显示该节点的上一个兄弟节点。并更改控件焦点
设置控件样式:
-
BOOL CTreePathView::PreCreateWindow(CREATESTRUCT& cs)
-
{
-
// TODO: 在此处通过改动
-
// CREATESTRUCT cs 来改动窗体类或样式
-
-
cs.style|=TVS_HASLINES|TVS_SHOWSELALWAYS; //若是想用CImageList的图标 ,则不要设置为TVS_HASBUTTONS形式
-
-
-
return CTreeView::PreCreateWindow(cs);
-
}
点击button5(焦点移动到上一个兄弟节点)
-
void NewImageView::OnBnClickedButton5() // 上一个图
-
{
-
// TODO: 在此加入控件通知处理程序代码
-
-
CTreePathView * pTree=(CTreePathView* )(((CMainFrame *)AfxGetMainWnd())->m_wndSplitter.GetPane(0,0));
-
-
CTreeCtrl & treeCtrl=pTree->GetTreeCtrl();
-
-
HTREEITEM hItem=treeCtrl.GetSelectedItem();
-
if (hItem!=NULL)
-
{
-
hItem=treeCtrl.GetNextItem(hItem,TVGN_PREVIOUS);
-
-
if (hItem!=NULL)
-
{
-
CString str;
-
str=pTree->GetFullPath(hItem);
-
SetImage(str);
-
treeCtrl.SelectItem(hItem);
-
treeCtrl.SetFocus();
-
InvalidateRect(m_ClientRect);
-
}
-
}
-
}
点击button6(焦点移动到下一个兄弟节点)
-
void NewImageView::OnBnClickedButton6() //下一个
-
{
-
// TODO: 在此加入控件通知处理程序代码
-
-
CTreePathView * pTree=(CTreePathView* )(((CMainFrame *)AfxGetMainWnd())->m_wndSplitter.GetPane(0,0));
-
CTreeCtrl & treeCtrl=pTree->GetTreeCtrl();
-
HTREEITEM hItem=treeCtrl.GetSelectedItem();
-
-
if (hItem!=NULL)
-
{
-
hItem=treeCtrl.GetNextItem(hItem,TVGN_NEXT);
-
-
if (hItem!=NULL)
-
{
-
CString str;
-
str=pTree->GetFullPath(hItem);
-
SetImage(str);
-
-
treeCtrl.SelectItem(hItem);
-
treeCtrl.SetFocus();
-
InvalidateRect(m_ClientRect);
-
}
-
}
-
}
7 遍历树控件的全部节点
1) 获得根节点句柄
-
CTreeCtrl& nTreeCtrl=((CImportTreeView*)m_SplitterWnd.GetPane(0,0))->GetTreeCtrl();
-
-
HTREEITEM hItem;
-
-
hItem = nTreeCtrl.GetRootItem();
-
-
TreeVisit(&nTreeCtrl,hItem);
2)遍历全部节点
-
void TreeVisit(CTreeCtrl* pCtrl,HTREEITEM hItem)
-
{
-
if(pCtrl->ItemHasChildren(hItem))
-
{
-
HTREEITEM hChildItem = pCtrl->GetChildItem(hItem);
-
while(hChildItem!=NULL)
-
{
-
TreeVisit(pCtrl,hChildItem);
-
hChildItem = pCtrl->GetNextItem(hChildItem, TVGN_NEXT);
-
}
-
}
-
else
-
Leaf(pCtrl,hItem);
-
}
8 获得某Item节点的全路径
-
CString m_ParentFolder[10];
-
CString m_OldParentFolder[10];
-
-
BOOL AddParentFolder(CString nParentFolder[10], CString nParent)
-
{
-
for(int i=9;i>0;i--)
-
nParentFolder[i]=nParentFolder[i-1];
-
nParentFolder[0]=nParent;
-
return TRUE;
-
}
-
-
-
CString AllCString(CString nParentFolder[10])
-
{
-
CString nAllCString=L"";
-
for(int i=0;i<10;i++)
-
{
-
if(nParentFolder[i]==L"") break;
-
nAllCString+=L"\\"+nParentFolder[i];
-
}
-
return nAllCString;
-
}
获得Item节点路径的函数
-
CString GetItemPath(CTreeCtrl* pCtrl,HTREEITEM hItem)
-
{
-
CString nSelItemName=pCtrl->GetItemText(hItem);
-
-
HTREEITEM parentItem=pCtrl->GetParentItem(hItem);
-
-
if (parentItem==NULL)
-
return nSelItemName;
-
-
-
for(int i=0;i<10;i++) m_OldParentFolder[i]=L"";
-
-
-
for(int i=0;i<10;i++)
-
m_OldParentFolder[i]=m_ParentFolder[i];
-
-
-
for(int i=0;i<10;i++)
-
m_ParentFolder[i]=L"";
-
-
CString itemPath;
-
CString parentFolder=nSelItemName;
-
-
-
AddParentFolder(m_ParentFolder,parentFolder);
-
-
-
-
-
while(parentItem!=NULL&&pCtrl->GetItemText(parentItem).Compare(m_PicFolder))
-
{
-
parentFolder=pCtrl->GetItemText(parentItem);
-
AddParentFolder(m_ParentFolder,parentFolder);
-
parentItem=pCtrl->GetParentItem(parentItem);
-
-
}
-
-
itemPath.Format(L"%s%s",m_PicFolder,AllCString(m_ParentFolder));
-
-
-
for(int i=0;i<10;i++) m_OldParentFolder[i]=L"";
-
-
for(int i=0;i<10;i++)
-
m_ParentFolder[i]=L"";
-
-
return itemPath;
-
-
}
获得叶子节点的函数
-
void Leaf(CTreeCtrl* pCtrl,HTREEITEM hItem)
-
{
-
-
CString itemName=pCtrl->GetItemText(hItem);
-
-
-
if(nSelItemName.Find(L".jpg")!=-1 || nSelItemName.Find(L".tif")!=-1)
-
{
-
-
-
for(int i=0;i<10;i++)
-
m_OldParentFolder[i]=m_ParentFolder[i];
-
-
-
for(int i=0;i<10;i++)
-
m_ParentFolder[i]=L"";
-
-
CString imgPath=L"";
-
CString parentFolder=itemName;
-
-
-
AddParentFolder(m_ParentFolder,parentFolder);
-
-
HTREEITEM parentItem=pCtrl->GetParentItem(hItem);
-
-
-
while(pCtrl->GetItemText(parentItem).Compare(m_imgPath))
-
{
-
parentFolder=pCtrl->GetItemText(parentItem);
-
AddParentFolder(m_ParentFolder,parentFolder);
-
parentItem=pCtrl->GetParentItem(parentItem)
-
-
}
-
-
-
imgPath.Format(L"%s%s",m_imgPath,AllCString(m_ParentFolder));
-
-
}
-
-
-
-
ShowPic(imgPath);
-
-
-
}
上述方法过于繁杂,再来了简洁些的
使用栈。依次将本节点-->根节点入栈 出栈时顺序便为根节点-->本节点
1)叶子节点
-
-
void CMainFrame::PostPath(CTreeCtrl& nTreeCtrl, HTREEITEM hItem,CString &path)
-
{
-
stack<HTREEITEM> itemStack;
-
while (hItem!=nTreeCtrl.GetRootItem ())
-
{
-
itemStack.push(hItem);
-
hItem=nTreeCtrl.GetParentItem (hItem);
-
}
-
itemStack.push(nTreeCtrl.GetRootItem ());
-
CString itemName;
-
while (!itemStack.empty())
-
{
-
hItem=(HTREEITEM)itemStack.top();
-
itemStack.pop();
-
itemName=nTreeCtrl.GetItemText (hItem);
-
path+=itemName;
-
path+=L"\\";
-
}
-
path.TrimRight(L"\\");
-
path+=L".xml";
-
}
2)文件夹节点
-
void CMainFrame::DirPath(CTreeCtrl& nTreeCtrl, HTREEITEM nRoot,CString &path)
-
{
-
stack<HTREEITEM> itemStack;
-
while (hItem!=nTreeCtrl.GetRootItem ())
-
{
-
itemStack.push(hItem);
-
hItem=nTreeCtrl.GetParentItem (hItem);
-
}
-
itemStack.push(nTreeCtrl.GetRootItem ());
-
CString itemName;
-
while (!itemStack.empty())
-
{
-
hItem=(HTREEITEM)itemStack.top();
-
itemStack.pop();
-
itemName=nTreeCtrl.GetItemText (hItem);
-
path+=itemName;
-
path+=L"\\";
-
}
-
}
9 获得树中全部叶子节点的父文件夹
即:树中可能有很多枝干,获取这些枝干的路径
-
std::vector<CString> m_BookDirectory;
-
void GetBookDirectory(CTreeCtrl* pCtrl,HTREEITEM hItem)
-
{
-
-
if(pCtrl->ItemHasChildren(hItem))
-
{
-
HTREEITEM hChildItem = pCtrl->GetChildItem(hItem);
-
while(hChildItem!=NULL)
-
{
-
GetBookDirectory(pCtrl,hChildItem);
-
-
if(pCtrl->ItemHasChildren(hChildItem))
-
hChildItem = pCtrl->GetNextItem(hChildItem, TVGN_NEXT);
-
else
-
break;
-
}
-
}
-
else
-
{
-
HTREEITEM parentItem=pCtrl->GetParentItem(hItem);
-
CString bookPath=GetItemPath(pCtrl,parentItem);
-
-
m_BookDirectory.push_back(bookPath);
-
-
}
-
}
-
CTreeCtrl& nTreeCtrl=((CImportTreeView*)m_SplitterWnd.GetPane(0,0))->GetTreeCtrl();
-
HTREEITEM hItem;
-
hItem = nTreeCtrl.GetRootItem();
-
-
m_BookDirectory.clear();
-
GetBookDirectory(&nTreeCtrl,hItem);
10 利用InsertItem、SetItemData 存放与该节点有关的数字信息
-
HTREEITEM InsertItem(
-
LPCTSTR lpszItem,
-
int nImage,
-
int nSelectedImage,
-
HTREEITEM hParent = TVI_ROOT,
-
HTREEITEM hInsertAfter = TVI_LAST
-
);
-
存放65535以上的大数据时 用SetItemData
A 32-bit application-specific value
-
BOOL SetItemData(
-
HTREEITEM hItem,
-
DWORD_PTR dwData
-
);
-