VC中使用CTreeCtrl实现目录树
vc++ MFC 2010-08-18 19:49:35 阅读61 评论0 字号:大中小 订阅
程序代码主要来自网络上的VCHelper程序。
这里还是从头叙述操作全过程,也好给自己留下深刻映像。
首先新建MFC工程,在对话框中添加CTreeCtrl控件,并关联变量Ctreectrl
CTreeCtrl m_treectrl;
如果需要选择框,要将控件的复选框勾上。
并定义成员变量 HTREEITEM m_hTreeItemRoot,方便函数调用。
然后就是初始化目录树了。
这里主要分为三部:
设置树选项
添加硬盘目录
添加目录文件夹
SetTreeListStyle();
m_hTreeItemRoot = m_treectrl.InsertItem("我的电脑",NULL,NULL);///root就是节点的标题
GetLogicalDrives( m_hTreeItemRoot );
GetDriveDir( m_hTreeItemRoot );
m_treectrl.Expand( m_hTreeItemRoot, TVE_EXPAND );
各函数代码如下:
设置参数
void CVctestView::SetTreeListStyle()
{
DWORD dwStyle = GetWindowLong( m_treectrl.m_hWnd, GWL_STYLE );
dwStyle |= TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT;
SetWindowLong( m_treectrl.m_hWnd, GWL_STYLE, dwStyle );
}
获取盘符
void CVctestView::GetLogicalDrives(HTREEITEM hParent)
{
ASSERT( hParent );
DWORD dwAllDriveStrings = GetLogicalDriveStrings( 0, NULL );
ASSERT( dwAllDriveStrings >= 1 );
LPTSTR lpDriveStrings = NULL;
lpDriveStrings = new TCHAR[ dwAllDriveStrings + sizeof( _T( "" ) ) ];
ASSERT( lpDriveStrings != NULL );
// Save the original address for the drive strings...
LPTSTR lpTmp = lpDriveStrings;
GetLogicalDriveStrings( dwAllDriveStrings, lpDriveStrings );
size_t szDriveString = lstrlen( lpDriveStrings );
while ( szDriveString > 1 )
{
HTREEITEM tHTR = m_treectrl.InsertItem( lpDriveStrings, hParent );
//m_treectrl.SetCheck(tHTR, 1);
lpDriveStrings += szDriveString + 1;
szDriveString = lstrlen( lpDriveStrings );
}
lpDriveStrings = lpTmp;
if ( lpDriveStrings )
{
delete lpDriveStrings;
lpDriveStrings = NULL;
}
ASSERT( lpDriveStrings == NULL );
}
获取第一层目录
void CVctestView::GetDriveDir(HTREEITEM hItem)
{
ASSERT( hItem );
HTREEITEM hChild = m_treectrl.GetChildItem( hItem );
while ( hChild )
{
CString strDir = m_treectrl.GetItemText( hChild );
if ( strDir.Right( 1 ) != _T( "/" ) )
strDir += _T( "/" );
strDir += _T( "*.*" );
CFileFind file;
BOOL bContinue = file.FindFile( strDir );
while ( bContinue )
{
bContinue = file.FindNextFile();
if ( file.IsDirectory() && ! file.IsDots() )
{
HTREEITEM tHTR = m_treectrl.InsertItem( file.GetFileName(), hChild );
m_treectrl.SetCheck( tHTR, m_treectrl.GetCheck(hChild));
}
}
GetDriveDir( hChild );
hChild = m_treectrl.GetNextItem( hChild, TVGN_NEXT );
}
}
前面函数添加完后应该可以显示第一层目录了。
本来可以一次性用递归把所有目录生成,不过测试了一下发现这样
时间要太长,所以接下来的目录就用添加事件响应来完成了。
添加时间函数:
void CVctestView::OnItemexpandedTree1(NMHDR* pNMHDR, LRESULT* pResult)
代码如下:
void CVctestView::OnItemexpandedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
TVITEM tvItem = pNMTreeView->itemNew;
if ( tvItem.hItem == m_hTreeItemRoot )
return;
HTREEITEM hChild = m_treectrl.GetChildItem( tvItem.hItem );
CString TMP = GetFullPath(hChild);
while ( hChild )
{
AddSubDirectory( hChild );
hChild = m_treectrl.GetNextItem( hChild, TVGN_NEXT );
}
UpdateCheck(tvItem.hItem,FALSE);
*pResult = 0;
}
CString CVctestView::GetFullPath(HTREEITEM hItem)
{
ASSERT( hItem );
CString strTmp = _T( "" );
CString strPath = _T( "" );
while ( hItem != m_hTreeItemRoot )
{
strTmp = m_treectrl.GetItemText( hItem );
if ( strTmp.Right( 1 ) != _T( "/" ) )
strTmp += _T( "/" );
strPath = strTmp + strPath;
hItem = m_treectrl.GetParentItem( hItem );
}
return strPath;
}
这时候已经可以显示所有的目录系统了,不过还有一个缺点就是
选择框的不同步,也是这一天自己主要弄的。
最后的实现就是添加鼠标响应时间,只要用户点选了复选框则
更新响应的子目录项。
void CVctestView::OnClickTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
CPoint myPoint;
UINT uFlag;
GetCursorPos(&myPoint);
m_treectrl.ScreenToClient(&myPoint);
HTREEITEM hItem = m_treectrl.HitTest(myPoint, &uFlag);
if ((hItem != NULL) &&
((TVHT_ONITEM & uFlag)
&& !(TVHT_ONITEMBUTTON & uFlag) && !(TVHT_ONITEMLABEL & uFlag)
))
//此处用HitTest来判断点击区域,不是右边的标识符也不是左边的+图标,则就认为是点了复选框
{
UpdateCheck(hItem,TRUE);
}
*pResult = 0;
}
更新选择状态的递归程序,由于左键点击事件在选择框被标志之前所以
这里要选择相反的状态。
void CVctestView::UpdateCheck(HTREEITEM p, BOOL Check)
{
if (!p) return ;
HTREEITEM hChildItem = m_treectrl.GetChildItem(p);
while (hChildItem != NULL)
{
UpdateCheck(hChildItem,Check);
// if(m_treectrl.GetCheck(p) && !Check
// || m_treectrl.GetCheck(p) && Check) m_treectrl.SetCheck( hChildItem, 1);
m_treectrl.SetCheck(hChildItem,m_treectrl.GetCheck(p) ^ Check);
hChildItem = m_treectrl.GetNextItem(hChildItem, TVGN_NEXT);
}
}