前面发了一个用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);
}
目录树 转 ctreectrl
最新推荐文章于 2024-07-11 11:48:17 发布