实现高级树形控件类CDirTreeCtrl,其父类为CTreeCtrl
添加成员函数Initialize,向树控件的根部插入"我的电脑"和"桌面"两个节点的操作。
//初始化树控件
void CDirTreeCtrl::Initialize()
{
LPITEMIDLIST itemlist;
char buf[256];
int iDesktopIcon;
int iComputerIcon;
DeleteAllItems(); //清空所有控件节点
SetImageList(NULL,0); //将控件的图像链表设为空
//得到"桌面"的磁盘全路径
SHGetSpecialFolderLocation(this->m_hWnd,CSIDL_DESKTOP,&itemlist);
SHGetPathFromIDList(itemlist,buf);
m_DesktopPath=buf;
//创建图标链表
m_ImageList.Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),
ILC_COLOR24.50,50);
//设置背景色
m_ImageList.SetBkColor(GetSysColor(COLOR_WINDOW));
iDesktopIcon=m_ImageList.Add( //将"桌面"图标加入链表
ExtractIcon(AfxGetApp()->m_hInstance,"shell32.dll",34));//得到"桌面"图标
iComputerIcon=m_ImageList.Add( //将"我的电脑"图标加入链表
ExtractIcon(AfxGetApp()->m_hInstance,"shell32.dll",15));
m_DriveRoot=InsertItems("我的电脑",TVI_ROOT,true,iComputerIcon,iComputerIcon);
m_DesktopRoot=AddItem(m_DesktopPath,TVI_ROOT,true,iDesktopPath,iDesktopPath);
}
//向树控件中插入节点
HTREEITEM CDirTreeCtrl::AddItem(const char* path,
HTREEITEM parent,
bool isDir,int iconEx,int iconEx2)
{
SHFILEINFO shinfo,shinfo_sel;
//得到默认的文本图标
SHGetFileInfo(path,&shinfo,SHGFI_DISPLAYNAME|SHGFI_ICON|SHGFI_SMALLICON);
//得到选择状态的文本图标
SHGetFileInfo(path,NULL,
&shinfo_sel,
sizeof(shinfo_sel),
SHGFI_DISPLAYNAME|
SHGFI_ICON|
SHGFI_OPENICON|
SHGFI_SMALLICON);
int icon =(iconEx!=-1)?iconEx:m_ImageList.Add(shinfo.hIcon);
int iconsel =(iconEX2!=-1)?iconEX2:m_ImageList.Add(shinfo.hIcon);
SetImageList(&m_ImageList,LVSIL_NORMAL); //设置图形链表
return InsertItems(shinfo.szDisplayName,parent,isDir,icon,iconsel); //插入节点
}
//初始化树控件
void CDirTreeCtrl::Initialize()
{
LPITEMIDLIST itemlist;
char buf[256];
int iDesktopIcon;
int iComputerIcon;
DeleteAllItems(); //清空所有控件节点
SetImageList(NULL,0); //将控件的图像链表设为空
//得到"桌面"的磁盘全路径
SHGetSpecialFolderLocation(this->m_hWnd,CSIDL_DESKTOP,&itemlist);
SHGetPathFromIDList(itemlist,buf);
m_DesktopPath=buf;
//创建图标链表
m_ImageList.Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),
ILC_COLOR24.50,50);
//设置背景色
m_ImageList.SetBkColor(GetSysColor(COLOR_WINDOW));
iDesktopIcon=m_ImageList.Add( //将"桌面"图标加入链表
ExtractIcon(AfxGetApp()->m_hInstance,"shell32.dll",34));//得到"桌面"图标
iComputerIcon=m_ImageList.Add( //将"我的电脑"图标加入链表
ExtractIcon(AfxGetApp()->m_hInstance,"shell32.dll",15));
m_DriveRoot=InsertItems("我的电脑",TVI_ROOT,true,iComputerIcon,iComputerIcon);
m_DesktopRoot=AddItem(m_DesktopPath,TVI_ROOT,true,iDesktopPath,iDesktopPath);
}
//向树控件中插入节点
HTREEITEM CDirTreeCtrl::AddItem(const char* path,
HTREEITEM parent,
bool isDir,int iconEx,int iconEx2)
{
SHFILEINFO shinfo,shinfo_sel;
//得到默认的文本图标
SHGetFileInfo(path,&shinfo,SHGFI_DISPLAYNAME|SHGFI_ICON|SHGFI_SMALLICON);
//得到选择状态的文本图标
SHGetFileInfo(path,NULL,
&shinfo_sel,
sizeof(shinfo_sel),
SHGFI_DISPLAYNAME|
SHGFI_ICON|
SHGFI_OPENICON|
SHGFI_SMALLICON);
int icon =(iconEx!=-1)?iconEx:m_ImageList.Add(shinfo.hIcon);
int iconsel =(iconEX2!=-1)?iconEX2:m_ImageList.Add(shinfo.hIcon);
SetImageList(&m_ImageList,LVSIL_NORMAL); //设置图形链表
return InsertItems(shinfo.szDisplayName,parent,isDir,icon,iconsel); //插入节点
}
//插入节点
HTREEITEM CDirTreeCtrl::InsertItems(const char* name,
HTREEITEM parent,
bool isDir,int icon,int iconOpen)
{
HTREEITEM hitm;
hitm=InsertItem(name,icon,iconOpen,parent); //插入节点
if(isDir)
{
InsertItem("",hitm); //如果节点为目录,就为其插入一个空的子节点
}
return hitm;
}
HTREEITEM CDirTreeCtrl::InsertItems(const char* name,
HTREEITEM parent,
bool isDir,int icon,int iconOpen)
{
HTREEITEM hitm;
hitm=InsertItem(name,icon,iconOpen,parent); //插入节点
if(isDir)
{
InsertItem("",hitm); //如果节点为目录,就为其插入一个空的子节点
}
return hitm;
}
当树形控件的某个节点被打开或关闭时,就会触发TVN_ITEMEXPANDED消息,自动调用OnItemexpanded函数。
在该函数中,对节点的状态进行判断,如果节点当前处于TVIS_EXPANDED状态,则调用ExpandBranch成员函
数,打开节点;否则,调用DeleteAllChild成员函数,关闭节点。
void CDirTreeCtrl::OnItemexpanded(NMHDR* pNMHDR,LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView=(NM_TREEVIEW*) pNMHDR;
TV_ITEM itm=pNMTreeView->itemNew; //得到当前节点
//判断节点状态
if(itm.state & TVIS_EXPANDED)
ExpandBranch(itm.hItem); //打开节点
else
DeleteAllChild(itm.hItem);
*pResult=0;
}
//打开指定节点
void CDirTreeCtrl::ExpandBranch(HTREEITEM parent)
{
bool bOne=false;
if(parent==m_DriveRoot) //判断当前节点是否为根节点
{
char *ptr;
DeleteAllChild(parent,false); //是根节点,删除所有子节点
//调用API函数,得到系统的盘符信息
GetLogicalDriveStrings(500,m_DrivesName);
ptr=m_DrivesName;
//处理盘符信息
while(*ptr)
{
bOne=true;
AddItem(ptr,m_DriveRoot,true); //添加节点
ptr+=strlen(ptr)+1;
}
}
else
{
m_strFullPath="";
CString pathWildcard;
//得到当前路径
m_strFullPath=GetPathFromHere(m_strFullPath,parent);
//删除所有子节点
DeleteAllChild(parent,false);
//准备过滤字符串
pathWildcard=m_strFullPath+"*.*";
CFileFind finder;
BOOL bWorking=finder.FindFile(pathWildcard);
while(bWorking)
{
bWorking=finder.FindNextFile(); //查找下一个表项
if(finder.IsDirectory() && !finder.IsDots) //如果是目录
{
bOne=true;
//添加到树控件中
HTREEITEM itm=AddItem(m_strFullPath+finder.GetFileName(),parent);
InsertItem("",itm);
}
}
}
if(!bOne) InsertItem("",parent); //插入空节点
}
//关闭指定节点
void CDirTreeCtrl::DeleteAllChild(HTREEITEM itm,bool isEmpty)
{
HTREEITEM child;
child=GetChildItem(itm); //得到指定节点的子节点
while(child) //如果其指定节点具有子节点
{
//如果子节点为空,则递归调用DeleteAllChild函数
if(GetChildItem(child))
DeleteAllChild(GetChildItem(child),isEmpty);
DeleteItem(child); //删除子节点
SetImageList(&m_ImageList,TVSIL_NORMAL);
child=GetChildItem(itm); //得到指定节点的子节点
}
if(isEmpty)
InsertItem("",itm);
}
//获取指定节点的路径
CString CDirTreeCtrl::GetPathFromHere(CString s,HTREEITEM itm)
{
HTREEITEM parent=GetParentItem(itm); //得到指定节点的父节点
HTREEITEM itmChild=GetParentItem(itm); //得到指定节点的子节点
//如果指定节点并非目录,则获取其父节点路径
if(!itmChild) return GetPathFromHere(s,parent);
//如果指定为根
if(itm==m_DrivesRoot) return "";
if(parent==m_DrivesRoot) //如果指定节点的父节点为根
{
HTREEITEM child;
char* ptr=m_DrivesName; //得到盘符信息
child=GetChildItem(parent); //得到子节点
while(child) //遍历盘符节点,查找指定节点
{
if(child==itm) //如果找到指定节点
{
s=CString(ptr)+s;
return s;
}
ptr+=strlen(ptr)+1; //得到下一个盘符信息
child=GetNextItem(child,TVGN_NEXT); //得到下一个盘符节点
}
}
else if(itm==m_DesktopRoot) //如果指定节点为桌面
{
s=m_DesktopPath+'\\'+s;
return s;
}
else //如果指定节点为普通目录
{
if(GetItemText(itm)!=CString(""))
s=GetItemText(itm)+''\\+s;
s=GetPathFromHere(s,parent); //递归调用
}
if(!itmChild && s.GEtLength()>0)
s=s.Left(s.GetLength()-1);
return s;
}
void CDirTreeCtrl::OnItemexpanded(NMHDR* pNMHDR,LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView=(NM_TREEVIEW*) pNMHDR;
TV_ITEM itm=pNMTreeView->itemNew; //得到当前节点
//判断节点状态
if(itm.state & TVIS_EXPANDED)
ExpandBranch(itm.hItem); //打开节点
else
DeleteAllChild(itm.hItem);
*pResult=0;
}
//打开指定节点
void CDirTreeCtrl::ExpandBranch(HTREEITEM parent)
{
bool bOne=false;
if(parent==m_DriveRoot) //判断当前节点是否为根节点
{
char *ptr;
DeleteAllChild(parent,false); //是根节点,删除所有子节点
//调用API函数,得到系统的盘符信息
GetLogicalDriveStrings(500,m_DrivesName);
ptr=m_DrivesName;
//处理盘符信息
while(*ptr)
{
bOne=true;
AddItem(ptr,m_DriveRoot,true); //添加节点
ptr+=strlen(ptr)+1;
}
}
else
{
m_strFullPath="";
CString pathWildcard;
//得到当前路径
m_strFullPath=GetPathFromHere(m_strFullPath,parent);
//删除所有子节点
DeleteAllChild(parent,false);
//准备过滤字符串
pathWildcard=m_strFullPath+"*.*";
CFileFind finder;
BOOL bWorking=finder.FindFile(pathWildcard);
while(bWorking)
{
bWorking=finder.FindNextFile(); //查找下一个表项
if(finder.IsDirectory() && !finder.IsDots) //如果是目录
{
bOne=true;
//添加到树控件中
HTREEITEM itm=AddItem(m_strFullPath+finder.GetFileName(),parent);
InsertItem("",itm);
}
}
}
if(!bOne) InsertItem("",parent); //插入空节点
}
//关闭指定节点
void CDirTreeCtrl::DeleteAllChild(HTREEITEM itm,bool isEmpty)
{
HTREEITEM child;
child=GetChildItem(itm); //得到指定节点的子节点
while(child) //如果其指定节点具有子节点
{
//如果子节点为空,则递归调用DeleteAllChild函数
if(GetChildItem(child))
DeleteAllChild(GetChildItem(child),isEmpty);
DeleteItem(child); //删除子节点
SetImageList(&m_ImageList,TVSIL_NORMAL);
child=GetChildItem(itm); //得到指定节点的子节点
}
if(isEmpty)
InsertItem("",itm);
}
//获取指定节点的路径
CString CDirTreeCtrl::GetPathFromHere(CString s,HTREEITEM itm)
{
HTREEITEM parent=GetParentItem(itm); //得到指定节点的父节点
HTREEITEM itmChild=GetParentItem(itm); //得到指定节点的子节点
//如果指定节点并非目录,则获取其父节点路径
if(!itmChild) return GetPathFromHere(s,parent);
//如果指定为根
if(itm==m_DrivesRoot) return "";
if(parent==m_DrivesRoot) //如果指定节点的父节点为根
{
HTREEITEM child;
char* ptr=m_DrivesName; //得到盘符信息
child=GetChildItem(parent); //得到子节点
while(child) //遍历盘符节点,查找指定节点
{
if(child==itm) //如果找到指定节点
{
s=CString(ptr)+s;
return s;
}
ptr+=strlen(ptr)+1; //得到下一个盘符信息
child=GetNextItem(child,TVGN_NEXT); //得到下一个盘符节点
}
}
else if(itm==m_DesktopRoot) //如果指定节点为桌面
{
s=m_DesktopPath+'\\'+s;
return s;
}
else //如果指定节点为普通目录
{
if(GetItemText(itm)!=CString(""))
s=GetItemText(itm)+''\\+s;
s=GetPathFromHere(s,parent); //递归调用
}
if(!itmChild && s.GEtLength()>0)
s=s.Left(s.GetLength()-1);
return s;
}
本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/164046,如需转载请自行联系原作者