目录树 转 ctreectrl

前面发了一个用MFC类Ctreectrl实现的目录树,引来了很多搜索,不过后来发现代码效率比较低,在展开文件很多的文件夹时非常慢,这里整合了目录树类..优化了展开部分的代码..其实差不多完全不同了(也是在别人的代码上改的)。
先发效果图:
还不知道怎么同时显示checkbox和系统图标...太水了...
不带checkbox的:

带checkbox的:


下面是调用部分代码:
    //pStatic 是一个空框,也就是要显示目录树的地方。
    CStatic *pStatic = (CStatic *)GetDlgItem(IDC_STATIC_DIRTREE);
    CRect ret;
    CString msg;
    pStatic->GetWindowRect(&ret);
    ScreenToClient(&ret);
    ret.left += 6;
    ret.right -=10;
    ret.top += 15;
    ret.bottom -=6;
   //IDC_DIRTREE为自定义的值,在View->ResourceSymbols添加
    if(pStatic!=NULL)m_DirTreeCtrl.Create(WS_VISIBLE,
        ret, this, IDC_DIRTREE);
   //文件过滤为bmp格式文件
    m_DirTreeCtrl.DisplayTree(NULL,TRUE,".bmp");

同时为目录树添加事件响应函数:
(更好的是集成在目录树代码里面,自己没有去弄了,简单的处理一下)
view的h文件
    afx_msg void OnItemexpandedDirtreeTWO(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnClickDirTree(NMHDR* pNMHDR, LRESULT* pResult);
view的cpp文件
    ON_NOTIFY(TVN_ITEMEXPANDED, IDC_DIRTREE, OnItemexpandedDirtreeTWO)
    ON_NOTIFY(NM_CLICK, IDC_DIRTREE, OnClickDirTree)
void CPlatFormView::OnItemexpandedDirtreeTWO(NMHDR *pNMHDR, LRESULT *pResult)
{
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
    // TODO: Add your control notification handler code here
    TVITEM tvItem = pNMTreeView->itemNew;
    m_DirTreeCtrl.ExpandItem(tvItem.hItem);   
    *pResult = 0;
}
void CPlatFormView::OnClickDirTree(NMHDR* pNMHDR, LRESULT* pResult)
{
    m_DirTreeCtrl.OnClick();
    *pResult = 0;
}

CDirTreeCtrl类代码:
class CDirTreeCtrl : public CTreeCtrl
{
//data
private:
    void UpdateViewParent(HTREEITEM hItem);
    void GetAllFloderFile(CString Path);
    void GetSelectFileHelp(HTREEITEM hItem);
    void UpdateView(HTREEITEM hItem,BOOL Val);
    BOOL IsFiterFile(CString FileName);
    CString GetFullPath(HTREEITEM hItem);
    LPCTSTR GetSubPath(LPCTSTR strPath);
    BOOL FindSubDir( LPCTSTR strPath);
    HTREEITEM AddItem( HTREEITEM hParent, LPCTSTR strPath );
    void DisplayPath(HTREEITEM hParent, LPCTSTR strPath);
    BOOL DisplayDrives();
    BOOL GetSysImgList();
    //是否显示文件
    BOOL        m_bShowFiles;
    //文件后缀
    CString        m_sFileFilter;
    //错误提示
    CString        m_strError;   
    CStringArray m_strSelectFile;
    CImageList    m_imgList;
    CString        m_strRoot;
    HTREEITEM m_hDirTreeRoot;
    BOOL m_bUpdatedCheck;
    DWORD m_treeStyle;
// Construction
public:
    CDirTreeCtrl();
    void ExpandItem(HTREEITEM hItem);
    void GetSelectFile(CStringArray &);
    void OnClick();
    void SetDirTreeStyle();
    BOOL DisplayTree(LPCTSTR strRoot,BOOL bFiles = TRUE,LPCTSTR sFilter = _T(".bmp"));
    virtual ~CDirTreeCtrl();

    // Generated message map functions
protected:
    //{{AFX_MSG(CDirTreeCtrl)
        // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

cpp代码:
/
// CDirTreeCtrl
//构造函数
CDirTreeCtrl::CDirTreeCtrl()
{
    m_strRoot = _T("");
    m_strSelectFile.RemoveAll();
    m_bUpdatedCheck = FALSE;
}

CDirTreeCtrl::~CDirTreeCtrl()
{
    m_imgList.Detach();
}


BEGIN_MESSAGE_MAP(CDirTreeCtrl, CTreeCtrl)
    //{{AFX_MSG_MAP(CDirTreeCtrl)
        // NOTE - the ClassWizard will add and remove mapping macros here.
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CDirTreeCtrl message handlers
//程序调用的接口,显示一棵目录树,
//strRoot为根目录路径
//bFiles是否显示文件
//sFilter文件过滤
BOOL CDirTreeCtrl::DisplayTree(LPCTSTR strRoot, BOOL bFiles, LPCTSTR sFilter)
{
    //初始化,设置高度,颜色,清空
    SetItemHeight(20);
    SetTextColor(RGB(0X0,0X0,0XFF));
    DeleteAllItems();
    //初始化参数,系统图标列表,是否显示文件,文件后缀过滤,显示路径
    SetDirTreeStyle();
    if (!(m_treeStyle & TVS_CHECKBOXES) && !GetSysImgList() ) return FALSE;
    m_bShowFiles = bFiles; 
    m_sFileFilter = sFilter;

    if ( strRoot == NULL || strRoot[0] == '#CONTENT#' )
    {
        //显示所有驱动文件
        if ( !DisplayDrives() )    return FALSE;
        m_strRoot = _T("");
    }
    else
    {
        //显示当前输入的为root
        m_strRoot = strRoot;
        if ( m_strRoot.Right(1) != '/' ) m_strRoot +=_T("/");
        HTREEITEM hParent = AddItem( TVI_ROOT, m_strRoot );
       
        DisplayPath( hParent, strRoot );
    }
    return TRUE;
}
//设置目录树属性,是否需要checkbox在此处处理
void CDirTreeCtrl::SetDirTreeStyle()
{
    DWORD dwStyle = GetWindowLong(m_hWnd, GWL_STYLE );
    dwStyle |= TVS_HASBUTTONS |
        TVS_HASLINES | TVS_LINESATROOT |
        TVS_CHECKBOXES |
        WS_BORDER | WS_TABSTOP ;
    m_treeStyle = dwStyle;
    SetWindowLong(m_hWnd, GWL_STYLE, dwStyle );
}
//获取系统图标
BOOL CDirTreeCtrl::GetSysImgList()
{
    SHFILEINFO shFinfo;
    HIMAGELIST hImgList = NULL;
   
    if ( GetImageList( TVSIL_NORMAL ) ) m_imgList.Detach();
   
    hImgList = (HIMAGELIST)SHGetFileInfo( "C:/",
        0,
        &shFinfo,
        sizeof( shFinfo ),
        SHGFI_SYSICONINDEX |
        SHGFI_SMALLICON );
    if ( !hImgList )
    {
        m_strError = _T("无法得到系统图标文件!");
        return FALSE;
    }
    m_imgList.m_hImageList = hImgList;   
   
    SetImageList( &m_imgList, TVSIL_NORMAL );
    return TRUE; 
}
//显示系统盘符
BOOL CDirTreeCtrl::DisplayDrives()
{
    DeleteAllItems();
   
    char  szDrives[260];
    char* pDrive=NULL;
    if ( !GetLogicalDriveStrings( sizeof(szDrives), szDrives ) )
    {
        m_strError =_T("驱动信息获取失败!");
        return FALSE;
    }
   
    pDrive = szDrives;
    //取得的信息 "c:/<null>d:/<null><null>"
    m_hDirTreeRoot = InsertItem(_T("我的电脑"));
    while( *pDrive!=0 )
    {
        //HTREEITEM hParent = AddItem( TVI_ROOT, pDrive );
        HTREEITEM hParent = AddItem( m_hDirTreeRoot, pDrive );
        if ( FindSubDir( pDrive ) )   
            InsertItem( _T(""), 0, 0, hParent );
        pDrive += strlen( pDrive ) + 1;
    }
//    Expand( m_hDirTreeRoot, TVE_EXPAND );
    return TRUE;
}
//显示指定路径下信息
void CDirTreeCtrl::DisplayPath(HTREEITEM hParent, LPCTSTR strPath)
{
    CFileFind find;
    CString   strPathFiles = strPath;
    BOOL      bFind;
    CStringArray strDirArray;
    CStringArray strFileArray;
   
    if ( strPathFiles.Right(1) != _T("/") ) strPathFiles += "/";
    strPathFiles += _T("*.*");
   
    bFind = find.FindFile( strPathFiles );
    while ( bFind )
    {
        bFind = find.FindNextFile();
        if ( find.IsDirectory() && !find.IsDots() )
        {       
            strDirArray.Add( find.GetFilePath() );
        }
        if ( !find.IsDirectory() && m_bShowFiles && IsFiterFile(find.GetFileName()))
            strFileArray.Add( find.GetFilePath() );
    }
   
    SetRedraw( FALSE );
    CWaitCursor wait;
   
    for ( int i = 0; i < strDirArray.GetSize(); i++ )
    {
        HTREEITEM hItem = AddItem( hParent, strDirArray.GetAt(i) );
        if ( FindSubDir( strDirArray.GetAt(i) ) )
            InsertItem( _T(""), 0, 0, hItem );
    }
   
    if ( m_bShowFiles )
    {
        for ( i = 0; i < strFileArray.GetSize(); i++ )
        {
            CString    sFile=strFileArray.GetAt(i);
            bFind=sFile.Find( m_sFileFilter );
           
            if( !FAILED(bFind) )    HTREEITEM hItem = AddItem( hParent,sFile );           
        }
    }
   
    SetRedraw( TRUE );   
}
//添加项
HTREEITEM CDirTreeCtrl::AddItem(HTREEITEM hParent, LPCTSTR strPath)
{
    //如果有Checkbox选项则不加在系统图标
    CString    strTemp = strPath;
    if ( strTemp.Right(1) != '/' )     strTemp += _T("/");

    if(m_treeStyle & TVS_CHECKBOXES)
    {
        strTemp = GetSubPath(strTemp);
        return InsertItem(strTemp,hParent);
        //return InsertItem(GetSubPath( strTemp ),hParent);
    }
    SHFILEINFO shFinfo;
    int iIcon, iIconSel;
    
   
    if ( !SHGetFileInfo( strTemp,
        0,
        &shFinfo,
        sizeof( shFinfo ),
        SHGFI_ICON |
        SHGFI_SMALLICON ) )
    {
        m_strError = _T("系统图表获取失败 !");
        return NULL;
    }
   
    iIcon = shFinfo.iIcon;
   
    // we only need the index from the system image list
   
    DestroyIcon( shFinfo.hIcon );
   
    if ( !SHGetFileInfo( strTemp,
        0,
        &shFinfo,
        sizeof( shFinfo ),
        SHGFI_ICON | SHGFI_OPENICON |
        SHGFI_SMALLICON ) )
    {
        m_strError =  _T("系统图表获取失败 !");
        return NULL;
    }
   
    iIconSel = shFinfo.iIcon;
   
    // we only need the index of the system image list
   
    DestroyIcon( shFinfo.hIcon );
   
    if ( strTemp.Right(1) == _T("/") )
        strTemp.SetAt( strTemp.GetLength() - 1, '#CONTENT#' );
   
    if ( hParent == TVI_ROOT )
        return InsertItem( strTemp, iIcon, iIconSel, hParent );
   
    return InsertItem( GetSubPath( strTemp ), iIcon, iIconSel, hParent );
}

//是否有子目录可展开
BOOL CDirTreeCtrl::FindSubDir(LPCTSTR strPath)
{
    CFileFind find;
    CString   strTemp = strPath;
    BOOL      bFind;
   
    if ( strTemp[strTemp.GetLength()-1] == '/' )
        strTemp += "*.*";
    else
        strTemp += "/*.*";   
   
    bFind = find.FindFile( strTemp );   
    while ( bFind )
    {
        bFind = find.FindNextFile();
        if ( find.IsDirectory() && !find.IsDots() )
        {
            return TRUE;
        }
        if ( !find.IsDirectory() && m_bShowFiles )
            return TRUE;       
    }
    return FALSE;
}
//获取路径
LPCTSTR CDirTreeCtrl::GetSubPath(LPCTSTR strPath)
{
    static CString strTemp;
    int     iPos;
   
    strTemp = strPath;
    if ( strTemp.Right(1) == '/' )
        strTemp.SetAt( strTemp.GetLength() - 1, '#CONTENT#' );
    iPos = strTemp.ReverseFind( '/' );
    if ( iPos != -1 )
        strTemp = strTemp.Mid( iPos + 1);
   
    return (LPCTSTR)strTemp;
}
//展开事件响应函数
void CDirTreeCtrl::ExpandItem(HTREEITEM hItem)
{
    CString strPath;
    if(hItem == m_hDirTreeRoot) return;
    HTREEITEM hChild = GetChildItem( hItem );
    while ( hChild )
    {
        DeleteItem( hChild );
        hChild = GetChildItem( hItem );
    }
    strPath = GetFullPath( hItem );
    DisplayPath( hItem, strPath );
    UpdateView( hItem, GetCheck(hItem));
}
//获取全目录
CString CDirTreeCtrl::GetFullPath(HTREEITEM hItem)
{
    CString strReturn;
    CString strTemp;
    HTREEITEM hParent = hItem;
   
    strReturn = "";
   
    while ( hParent )
    {
       
        strTemp  = GetItemText( hParent );
        if(strTemp != "我的电脑") {
            strTemp += "/";
            strReturn = strTemp + strReturn;
        }
        hParent = GetParentItem( hParent );
    }
   
    strReturn.TrimRight( '/' );
   
    return strReturn;
}
//判断是否为过滤文件
BOOL CDirTreeCtrl::IsFiterFile(CString strFileName)
{
    CString strFileNameExt;
    int pos=strFileName.ReverseFind('.');
    strFileNameExt=strFileName.Mid(pos,strFileName.GetLength()-pos);
    strFileNameExt.MakeLower();
    //目前程序只支持BMP格式
    if( strFileNameExt==m_sFileFilter)
    {
        return TRUE;
    }
    else return FALSE;
}
//点选响应事件
void CDirTreeCtrl::OnClick()
{
    if(!(m_treeStyle & TVS_CHECKBOXES)) return;
    CPoint myPoint;
    UINT uFlag;
    GetCursorPos(&myPoint);
    ScreenToClient(&myPoint);
    HTREEITEM hItem = HitTest(myPoint, &uFlag);
    //用户点选了一个目录项
    if ((hItem != NULL) &&
        ((TVHT_ONITEM & uFlag)
        && !(TVHT_ONITEMBUTTON & uFlag) && !(TVHT_ONITEMLABEL & uFlag)
        ))
    {
        //跟新该目录项的子目录状态
        UpdateView(hItem,!GetCheck(hItem));
        if(GetCheck(hItem)) UpdateViewParent(hItem);
        m_bUpdatedCheck = FALSE;
     }
}
//向下更新选择项
void CDirTreeCtrl::UpdateView(HTREEITEM hItem, BOOL Val)
{
    if (!hItem) return ;
    HTREEITEM hChildItem = GetChildItem(hItem);
    while (hChildItem != NULL)
    {
        UpdateView(hChildItem,Val);
        SetCheck(hChildItem,Val);
        hChildItem = GetNextItem(hChildItem, TVGN_NEXT);
    }
}
//获取选择文件
void CDirTreeCtrl::GetSelectFileHelp(HTREEITEM hItem)
{
    if (!hItem) return ;
    HTREEITEM hChildItem = GetChildItem(hItem);
    while (hChildItem != NULL)
    {
        CString tname = GetFullPath(hChildItem);
        //该节点被选择了
        if(GetCheck(hChildItem)) {           
            CString filename = GetFullPath(hChildItem);
            //filename.Delete(filename.GetLength()-1,1);
            //如果是图片文件,则添加到选择列表中
            if(IsFiterFile(filename)) {
                    m_strSelectFile.Add(filename);
                //是文件夹,则获取文件夹下所有的图片文件,也不再递归搜索该目录下的文件了
            } else {
                GetAllFloderFile(GetFullPath(hChildItem));
            }
            //获取该文件夹下的子目录文件
        } else {
            GetSelectFileHelp(hChildItem);
        }
        hChildItem = GetNextItem(hChildItem, TVGN_NEXT);
    }
    m_bUpdatedCheck = TRUE;
}
//过去指定文件夹下所有的文件
void CDirTreeCtrl::GetAllFloderFile(CString Path)
{
    CString strPath = Path;
    if ( strPath.Right( 1 ) != "/" )
        strPath += "/";
    strPath += _T( "*.*" );
    CFileFind file;
    BOOL bContinue = file.FindFile( strPath );
    while ( bContinue )
    {
        bContinue = file.FindNextFile();
        CString tmp = file.GetFileName();
        //是文件夹就递归下去搜索
        if ( file.IsDirectory() && ! file.IsDots() )
        {
            if ( Path.Right( 1 ) != "/" ) GetAllFloderFile(Path + "/" + file.GetFileName());
            else GetAllFloderFile(Path + file.GetFileName());
        }
        //图像文件就加入选择列表
        else if(IsFiterFile(file.GetFileName())) {
            CString strFileNameExt;
            CString filename;
            if ( Path.Right( 1 ) != "/" ) filename = Path+"/"+file.GetFileName();
            else filename = Path + file.GetFileName();
            m_strSelectFile.Add(filename);
        }
    }
}
//获取选择的文件,传入CStringArray的参数
void CDirTreeCtrl::GetSelectFile(CStringArray &SelectFile)
{
    if(!m_bUpdatedCheck)
        GetSelectFileHelp(TVI_ROOT);
    SelectFile.Copy(m_strSelectFile);
}
//更新父目录的选择状态
//如果子目录不再被选中这父目录也不被选中
void CDirTreeCtrl::UpdateViewParent(HTREEITEM hItem)
{
    if (!hItem) return ;
    if (hItem == m_hDirTreeRoot) return ;
    HTREEITEM hParentItem = GetParentItem(hItem);
    if(GetCheck(hParentItem))
        SetCheck(hParentItem,FALSE);
    UpdateViewParent(hParentItem);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值