实现高级树形控件类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);  //插入节点
   }
   //插入节点
   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;
   }