dirtreectrl.cpp

来自「一个FTP下载的源代码。代码质量非常高」· C++ 代码 · 共 1,193 行 · 第 1/2 页

CPP
1,193
字号
// DirTreeCtrl.cpp: 
// 
// wrapped CTreeCtrl to select and or display folders and files (optional )
// 

#include "stdafx.h"

#include "DirTreeCtrl.h"
#include "localview.h"
#include "resource.h"
#include "mainfrm.h"
#include "transferasdlg.h"
#include "CommandQueue.h"
#include "FtpListCtrl.h"
#include "LocalView2.h"
#include "LocalFileListCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDirTreeCtrl

CDirTreeCtrl::CDirTreeCtrl()
{
	m_dont_notify = false;
	m_hDragSource = NULL;
	m_hDragHilited = NULL;
}

CDirTreeCtrl::~CDirTreeCtrl()
{
}


BEGIN_MESSAGE_MAP(CDirTreeCtrl, CTreeCtrl)
	//{{AFX_MSG_MAP(CDirTreeCtrl)
	ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemexpanded)
	ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
	ON_WM_VSCROLL()
	ON_WM_CREATE()
	ON_WM_KEYDOWN()
	ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnBeginlabeledit)
	ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndlabeledit)
	ON_WM_CONTEXTMENU()
	ON_COMMAND(ID_LOCALTREECONTEXT_ADDTOQUEUE, OnLocaltreecontextAddtoqueue)
	ON_COMMAND(ID_LOCALTREECONTEXT_DELETE, OnLocaltreecontextDelete)
	ON_COMMAND(ID_LOCALTREECONTEXT_RENAME, OnLocaltreecontextRename)
	ON_COMMAND(ID_LOCALTREECONTEXT_UPLOAD, OnLocaltreecontextUpload)
	ON_COMMAND(ID_LOCALTREECONTEXT_UPLOADAS, OnLocaltreecontextUploadas)
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// Behandlungsroutinen f黵 Nachrichten CDirTreeCtrl 

BOOL CDirTreeCtrl::DisplayTree(LPCTSTR strRoot, BOOL bFiles)
{
	m_dont_notify=TRUE;
	DWORD dwStyle = GetStyle();   // read the windowstyle
	
	// Display the DirTree with the Rootname e.g. C:\
	// if Rootname == NULL then Display all Drives on this PC
    // First, we need the system-ImageList
	
	DeleteAllItems();

	LPITEMIDLIST list;
	SHGetSpecialFolderLocation(m_pOwner->m_hWnd,CSIDL_DRIVES,&list);
	SHFILEINFO shFinfo;

	SHGetFileInfo((LPCTSTR)list,0,&shFinfo,sizeof(shFinfo),SHGFI_PIDL|SHGFI_ICON|SHGFI_SMALLICON);	
	DestroyIcon(shFinfo.hIcon);
	int iIcon=shFinfo.iIcon;
	SHGetFileInfo((LPCTSTR)list,0,&shFinfo,sizeof(shFinfo),SHGFI_PIDL|SHGFI_ICON|SHGFI_SMALLICON|SHGFI_OPENICON|SHGFI_DISPLAYNAME);
	
	CoTaskMemFree(list);

	DestroyIcon(shFinfo.hIcon);
	
	HTREEITEM hParent=InsertItem(shFinfo.szDisplayName,iIcon,shFinfo.iIcon,TVI_ROOT);
	
	if ( !DisplayDrives() )
	{
		m_dont_notify=FALSE;
		return FALSE;
	}
	Expand(GetRootItem(), TVE_EXPAND);
	return TRUE;	
}
/////////////////////////////////////////////////
BOOL CDirTreeCtrl::GetSysImgList()
/////////////////////////////////////////////////
{
	CImageList sysImgList;
	SHFILEINFO shFinfo;
	
	sysImgList.Attach((HIMAGELIST)SHGetFileInfo( _T("C:\\"),
							  0,
							  &shFinfo,
							  sizeof( shFinfo ),
							  SHGFI_SYSICONINDEX |
							  SHGFI_SMALLICON ));
	
	SetImageList( &sysImgList, TVSIL_NORMAL );
	sysImgList.Detach();
	return TRUE;
}

BOOL CDirTreeCtrl::DisplayDrives()
{
	//
	// Displaying the Available Drives on this PC
	// This are the First Items in the TreeCtrl
	//
	//DeleteAllItems();
	TCHAR  szDrives[128];
	TCHAR* pDrive;

	if ( !GetLogicalDriveStrings( sizeof(szDrives)/sizeof(TCHAR), szDrives ) )
	{
		m_strError = "Error Getting Logical DriveStrings!";
		return FALSE;
	}

	pDrive = szDrives;
	while( *pDrive )
	{
		HTREEITEM hParent = AddItem( GetRootItem(), pDrive );
	//	if ( FindSubDir( pDrive ) )
			InsertItem( _T(""), 0, 0, hParent );
		pDrive += _tcslen( pDrive ) + 1;
	}


	return TRUE;

}

void ArrayQuickSort(std::vector<CString> &array, int l, int r);
void ArrayInsertionSort(std::vector<CString> &array);
void SortArray(std::vector<CString> &array)
{
	// Sorts the Array for n < 11 using insertion sort, else using Quicksort
	
	if (array.size() > 1) 
		if (array.size() < 11) ArrayInsertionSort(array);
		else ArrayQuickSort(array, 1, array.size()-1);
}

void ArrayQuickSort(std::vector<CString> &array, int l, int r)
{
	int i,j;
	int max = array.size();
	CString v;

	if (r > l) {
		v = array[r];
		i = l-1;
		j = r;
		for (;;) {
			while ((array[i].CollateNoCase( v ) < 0) && (i < max)) i++;
			while ((array[j].CollateNoCase( v ) > 0) && (j > 0)) j--;
			if (i >= j) break;
			v = array[i];
			array[i]=array[j];
			array[j]=v;
		}
		v = array[i];
		array[i]=array[r];
		array[r]=v;

		ArrayQuickSort(array, l, i-1);
		ArrayQuickSort(array, i+1, r);
	}
}

void ArrayInsertionSort(std::vector<CString> &array)
{
	int i,j;
	CString v;
	int n=array.size();

	for (i = 1; i < n-1; i++) {
		v = array[i];
		j = i;
		while ((j > 0) && (array[j-1].CollateNoCase( v ) > 0)) {
			array[j]=array[j-1];
			j--;
		}
		array[j]=v;
	}
}

void CDirTreeCtrl::DisplayPath(HTREEITEM hParent, LPCTSTR strPath)
{
	//
	// Displaying the Path in the TreeCtrl
	//
	CFileFind find;
	CString   strPathFiles = strPath;
	BOOL      bFind;
	std::vector<CString> strDirArray;
	
	if ( strPathFiles.Right(1) != "\\" )
		strPathFiles += "\\";
	strPathFiles += "*.*";

	bFind = find.FindFile( strPathFiles );

	while ( bFind )
	{
		bFind = find.FindNextFile();
		if ( find.IsDirectory() && !find.IsDots() )
		{		
			strDirArray.push_back( find.GetFilePath() );
		}
		
	}
    
	SortArray(strDirArray);
	SetRedraw( FALSE );
	CWaitCursor wait;
    
	for ( UINT i = 0; i < strDirArray.size(); i++ )
	{
		HTREEITEM hItem = AddItem( hParent, strDirArray[i] );
		if ( FindSubDir( strDirArray[i] ) )
			InsertItem( _T(""), 0, 0, hItem );
	}

    
	SetRedraw(TRUE);	
}

HTREEITEM CDirTreeCtrl::AddItem(HTREEITEM hParent, LPCTSTR strPath)
{
	// Adding the Item to the TreeCtrl with the current Icons
    CString strTemp = strPath;
    
	strTemp.TrimRight('\\');
	
	int iIcon, iIconSel;
	SHFILEINFO shFinfo;
	if ( !SHGetFileInfo( strPath,
				0,
				&shFinfo,
				sizeof( shFinfo ),
				SHGFI_ICON | 
				SHGFI_SMALLICON ) )
	{
		m_strError = "Error Gettting SystemFileInfo!";
		return 0;
	}
	
	iIcon = shFinfo.iIcon;
	
	// we only need the index from the system image list
	
	DestroyIcon( shFinfo.hIcon );
	
	if ( !SHGetFileInfo( strPath,
				0,
				&shFinfo,
				sizeof( shFinfo ),
				SHGFI_ICON | SHGFI_OPENICON |
			    SHGFI_SMALLICON ) )
	{
		m_strError = "Error Gettting SystemFileInfo!";
		return 0;
	}

	iIconSel = shFinfo.iIcon;
	
	// we only need the index of the system image list

	DestroyIcon( shFinfo.hIcon );
	HTREEITEM ret=InsertItem( GetSubPath( strTemp ), iIcon,iIconSel, hParent );
	
	return ret;
	
}

LPCTSTR CDirTreeCtrl::GetSubPath(LPCTSTR strPath)
{
	//
	// getting the last SubPath from a PathString
	// e.g. C:\temp\readme.txt
	// the result = readme.txt
	static CString strTemp;
	int     iPos;

	strTemp = strPath;
	strTemp.TrimRight('\\');
	iPos = strTemp.ReverseFind( '\\' );
	if ( iPos != -1 )
	    strTemp = strTemp.Mid( iPos + 1);

	return (LPCTSTR)strTemp;
}

BOOL CDirTreeCtrl::FindSubDir( LPCTSTR strPath)
{
	//
	// Are there subDirs ?
	//
	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;
		}
		
	}

	return FALSE;

}

void CDirTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	 
	ExpandItem( pNMTreeView->itemNew.hItem, TVE_EXPAND );

	*pResult = 0;
}

CString CDirTreeCtrl::GetFullPath(HTREEITEM hItem) const
{
	if (!hItem)
		return "";

	// get the Full Path of the item
	CString strReturn;
	CString strTemp;
	HTREEITEM hParent = hItem;

	strReturn = "";

	while ( GetParentItem(hParent) )
	{
		
		strTemp  = GetItemText( hParent );
		strTemp += "\\";
		strReturn = strTemp + strReturn;
		hParent = GetParentItem( hParent );
	}
    
	return strReturn;

}

BOOL CDirTreeCtrl::SetSelPath(CString strPath)
{
	m_dont_notify = true;
	if (strPath=="\\" || strPath=="")
	{
		SelectItem(GetRootItem());
		ExpandItem(GetRootItem(), TVE_EXPAND);
		HTREEITEM hFound = GetChildItem(GetRootItem());
		CString strTemp;
		while (hFound)
		{
			Expand(hFound, TVE_COLLAPSE);
			hFound = GetNextItem(hFound, TVGN_NEXT);
		}
		m_dont_notify = false;
		return TRUE;
	}
	// Setting the Selection in the Tree
	HTREEITEM hParent  = GetChildItem(TVI_ROOT);
	int       iLen    = strPath.GetLength() + 2;
	LPTSTR    pszPath = new TCHAR[iLen];
	LPTSTR    pPath   = pszPath;
	BOOL      bRet    = FALSE;
    
	if ( !IsValidPath( strPath ) )
	{
		m_dont_notify = FALSE;
		delete [] pszPath; // this must be added 29.03.99
		return FALSE;
	}

	_tcscpy( pszPath, strPath );
	_tcsupr( pszPath );
	
	if ( pszPath[_tcslen(pszPath)-1] != '\\' )
		_tcscat( pszPath, _T("\\") );
    
	int iLen2 = _tcslen( pszPath );
	
	for (WORD i = 0; i < iLen2; i++ )
	{
		if ( pszPath[i] == '\\' )
		{
			pszPath[i] = '\0';
			hParent = SearchSiblingItem( hParent, pPath );
			if ( !hParent )  // Not found!
				break;
			else
			{				
				HTREEITEM hFound = GetChildItem(hParent);
				CString   strTemp;
				while (hFound)
				{
					Expand(hFound,TVE_COLLAPSE);
					hFound = GetNextItem( hFound, TVGN_NEXT );
				}

				Expand( hParent, TVE_EXPAND );
			}
			pPath += _tcslen(pPath) + 1;
		}
	}
	
	delete [] pszPath;
	
	if (hParent) // Ok the last subpath was found
	{		
		Select(hParent, TVGN_FIRSTVISIBLE); // select the last expanded item
		SelectItem(hParent);

		bRet = TRUE;
	}
	else
	{
		bRet = FALSE;
	}
	SetRedraw( TRUE );
	

	m_dont_notify = false;
    return bRet;
}

HTREEITEM CDirTreeCtrl::SearchSiblingItem( HTREEITEM hItem, LPCTSTR strText)
{
	HTREEITEM hFound = GetChildItem( hItem );
	CString   strTemp;
	while ( hFound )
	{
		strTemp = GetItemText( hFound );
        strTemp.MakeUpper();
		if ( strTemp == strText )
			return hFound;
		hFound = GetNextItem( hFound, TVGN_NEXT );
	}

	return NULL;
}


void CDirTreeCtrl::ExpandItem(HTREEITEM hItem, UINT nCode)
{	
	if (!GetParentItem(hItem))
		return;
	if ( nCode == TVE_EXPAND )
	{
		TVITEM item;
		item.hItem=hItem;
		item.mask=TVIF_HANDLE|TVIF_STATE;
		GetItem(&item);

		if (item.state&TVIS_EXPANDEDONCE)
		{
			return;
		}
		HTREEITEM hChild = GetChildItem( hItem );
		while ( hChild )
		{
			DeleteItem( hChild );
			hChild = GetChildItem( hItem );
		}
        
		CString strPath = GetFullPath( hItem );
		DisplayPath( hItem, strPath );
	}
}

BOOL CDirTreeCtrl::IsValidPath(LPCTSTR strPath)
{
	// This function check the Pathname
	
	HTREEITEM hChild;
	CString   strItem;
	CString   strTempPath = strPath;
	BOOL      bFound = FALSE;
	CFileFind find;

	hChild = GetChildItem( GetRootItem() );
	strTempPath.MakeUpper();
	strTempPath.TrimRight('\\');

/*	while ( hChild )
	{
		strItem = GetItemText( hChild );
		strItem.MakeUpper();
		if ( strItem == strTempPath.Mid( 0, strItem.GetLength() ) )
		{
			bFound = TRUE;
			break;
		}
		hChild = GetNextItem( hChild, TVGN_NEXT );
	}
    
	if ( !bFound )
		return FALSE;*/

	strTempPath += "\\nul";
	if ( find.FindFile( strTempPath ) )
		return TRUE;
     
	return FALSE;
}

void CDirTreeCtrl::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	if (!m_dont_notify)
	{
		m_pOwner->SetLocalFolderOut(GetFullPath(pNMTreeView->itemNew.hItem));
	}
	*pResult = 0;
}

void CDirTreeCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}

int CDirTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	GetSysImgList()	;
		
	return 0;
}

void CDirTreeCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	if (nChar==VK_F2)
	{
		// To Use F2 as hot Key to get EditCtrl on the ListView it must have 
		// the Style TVS_EDITLABELS
		ASSERT( GetStyle() & TVS_EDITLABELS );
		// don't do an Edit Label when the multiple Items are selected
		//Don't allow to rename "My Computer"
		if (GetRootItem()==GetSelectedItem())
			return;
		//Don't allow to rename the drives
		if (GetRootItem()==GetParentItem(GetSelectedItem()))
			return;
		VERIFY( EditLabel( GetSelectedItem() ) != NULL );
	}

	CTreeCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}

#define VK_A		65
BOOL CDirTreeCtrl::PreTranslateMessage(MSG* pMsg) 
{
	// If edit control is visible in tree view control, sending a
	// WM_KEYDOWN message to the edit control will dismiss the edit
	// control.  When ENTER key was sent to the edit control, the parent
	// window of the tree view control is responsible for updating the
	// item's label in TVN_ENDLABELEDIT notification code.
	if ( pMsg->message == WM_KEYDOWN )
	{
		CEdit* edit = GetEditControl();
		if (edit)
		{
			if( GetKeyState( VK_CONTROL )&128 && pMsg->wParam == VK_A )
			{
				edit->SetSel(0, -1);
				return TRUE;
			}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?