⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 explorertreeview.cpp

📁 类似资源管理器的vc源代码,实现起来相当不容易啊,要细心琢磨
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ExplorerTreeView.cpp : implementation file
//

#include "stdafx.h"
#include "CMyExplorer.h"
#include "ExplorerTreeView.h"
#include "ExplorerListView.h"
#include "ShellContextMenu.h"
#include "ShellFileOp.h"

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

CExplorerTreeView * g_TreeView = NULL;
extern CExplorerListView * g_ListView;

/////////////////////////////////////////////////////////////////////////////
// CExplorerTreeView

IMPLEMENT_DYNCREATE(CExplorerTreeView, CTreeView)

CExplorerTreeView::CExplorerTreeView()
{
	g_TreeView       = this;
	m_pTreeCtrl      = &GetTreeCtrl();
	m_psfDesk        = NULL;
	m_pidlDesk       = NULL;
	m_pidlMyComputer = NULL;

	m_hDesktop       = NULL;
	m_hMyComputer    = NULL;
	m_hSelItem       = NULL;
	m_hMoveSrc       = NULL;

	m_pSelLiParam    = NULL;
}

CExplorerTreeView::~CExplorerTreeView()
{
//	m_pTreeCtrl->SetImageList(NULL,TVSIL_NORMAL);
}


BEGIN_MESSAGE_MAP(CExplorerTreeView, CTreeView)
	//{{AFX_MSG_MAP(CExplorerTreeView)
	ON_WM_CREATE()
	ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
	ON_NOTIFY_REFLECT(TVN_SELCHANGING, OnSelchanging)
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
	ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_REFRESHFILES,OnRefreshTree)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExplorerTreeView drawing

void CExplorerTreeView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CExplorerTreeView diagnostics

#ifdef _DEBUG
void CExplorerTreeView::AssertValid() const
{
	CTreeView::AssertValid();
}

void CExplorerTreeView::Dump(CDumpContext& dc) const
{
	CTreeView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CExplorerTreeView message handlers

int CExplorerTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CTreeView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	m_pTreeCtrl->ModifyStyle(0,TVS_HASBUTTONS|TVS_SHOWSELALWAYS);

	InitExplorerTree();
	InitImageList();
	
	int i = m_TreeTarget.Register(this);

	return 0;
}

void CExplorerTreeView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	CPoint pt;
	GetCursorPos(&pt);
	m_pTreeCtrl->ScreenToClient(&pt);
	HTREEITEM hItem = m_pTreeCtrl->HitTest(pt,NULL);
	if ( hItem==NULL )
		return;
	LPTREEPARAM ptrParam  = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hItem);

	CShellContextMenu scm;        
	scm.SetObjects(ptrParam->lpidl);    
	m_pTreeCtrl->ClientToScreen(&pt);
	UINT idCommand = scm.ShowContextMenu(this, pt);

	switch( idCommand )
	{
	case 18: //chose delete
		{
			HTREEITEM hParentItem = m_pTreeCtrl->GetParentItem(hItem);
			SendMessage(WM_REFRESHFILES,(WPARAM)hParentItem,0);
			g_ListView->SendMessage(WM_REFRESHFILES,0,0);
			break;
		}
	case 27:  //chose paste
		{
			SendMessage(WM_REFRESHFILES,(WPARAM)hItem,0);
			g_ListView->SendMessage(WM_REFRESHFILES,0,0);
			break;
		}
	}

	*pResult = 0;
}

void CExplorerTreeView::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	TV_ITEM tvItem = pNMTreeView->itemNew;
	if ( pNMTreeView->action==2 )      //展开
	{
		SendMessage(WM_REFRESHFILES,(WPARAM)tvItem.hItem,0);
		SetSubItemFolder(tvItem);
	}

	*pResult = 0;
}

void CExplorerTreeView::OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult) 
{
	
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	TV_ITEM tvItem = pNMTreeView->itemNew;
	m_hSelItem     = tvItem.hItem;

	LPTREEPARAM pliParam  = (LPTREEPARAM)tvItem.lParam;
	if ( g_ListView )
	{
		g_ListView->SetListContext(pliParam->lpsf,pliParam->lpidl);
	}
	*pResult = 0;
}

void CExplorerTreeView::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	TV_ITEM tvItem = pNMTreeView->itemNew;

	HTREEITEM hItem = tvItem.hItem;
	m_hMoveSrc = m_pTreeCtrl->GetParentItem(hItem);

	HTREEITEM hSel = m_pTreeCtrl->GetSelectedItem();
	
	LPTREEPARAM ptrItem = (LPTREEPARAM)tvItem.lParam;
	
	char * szSrc = new char[MAX_PATH];
	ZeroMemory(szSrc,MAX_PATH);
	SHGetPathFromIDList(ptrItem->lpidl,szSrc);

	//创建拖拽数据源
	int hgblSize = sizeof(DROPFILES) + ( strlen(szSrc)+2 )* sizeof(_TCHAR);
	HGLOBAL hgblData = ::GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,hgblSize);
	if (hgblData == NULL)
		return;
	
	LPDROPFILES pDropFiles = (LPDROPFILES)GlobalLock(hgblData);

	pDropFiles->pFiles = sizeof(DROPFILES);
	pDropFiles->fWide = FALSE;
	LPSTR pGlobalString = (LPSTR)(pDropFiles) + sizeof(DROPFILES);


	strcpy((char*)(pGlobalString), szSrc);
	pGlobalString += ( strlen(szSrc)+1 ) * sizeof(_TCHAR);
	pGlobalString[0] = _T('\0');
	
	GlobalUnlock(hgblData);
	delete szSrc;

	COleDataSource *poleSourceObj = new COleDataSource;
	poleSourceObj->CacheGlobalData(CF_HDROP,hgblData);
	DROPEFFECT dropeffect = poleSourceObj->DoDragDrop();

	*pResult = 0;
}

HTREEITEM CExplorerTreeView::FindSubItemByPath(HTREEITEM hParent, LPSTR szPathName)
{
	HTREEITEM hNextItem,hChildItem = m_pTreeCtrl->GetChildItem(hParent);
	
	char * szPath = new char[MAX_PATH];
	while( hChildItem )
	{
		ZeroMemory(szPath,MAX_PATH);
		LPTREEPARAM ptrParam = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hChildItem);
		SHGetPathFromIDList(ptrParam->lpidl,szPath);
		if ( strcmp(szPathName,szPath)==0 )
		{
			delete szPath;
			return hChildItem;
		}
		hNextItem = m_pTreeCtrl->GetNextItem(hChildItem, TVGN_NEXT);
		hChildItem = hNextItem;	
	}
	delete szPath;
	return NULL;
}

long CExplorerTreeView::OnRefreshTree(WPARAM wParam, LPARAM lParam)
{
	HTREEITEM hRefresh;
	if  ( wParam==0 )
		hRefresh = m_hSelItem;
	else
		hRefresh = (HTREEITEM)wParam;
	if ( hRefresh==m_hDesktop )
		return 0;

	

	//删除多余项
	char * szPathName = new char[MAX_PATH];
	
	HTREEITEM hNextItem,hChildItem = m_pTreeCtrl->GetChildItem(hRefresh);
	while( hChildItem )
	{
		ZeroMemory(szPathName,MAX_PATH);
		LPTREEPARAM ptrParam = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hChildItem);
		SHGetPathFromIDList(ptrParam->lpidl,szPathName);
		//路径不为空、且不存在时才能删除
		//系统的文件夹路径为空,不能删
		if ( strlen(szPathName)!=0 && GetFileAttributes(szPathName)==INVALID_FILE_ATTRIBUTES )
		{
			hNextItem = m_pTreeCtrl->GetNextItem(hChildItem, TVGN_NEXT);
			if ( hChildItem==m_hSelItem )
				m_pTreeCtrl->SelectItem(hRefresh);
			LPTREEPARAM ptrParam = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hChildItem);
			m_pMalloc->Free(ptrParam);
			m_pTreeCtrl->DeleteItem(hChildItem);
		}
		else
		{
			hNextItem = m_pTreeCtrl->GetNextItem(hChildItem, TVGN_NEXT);
		}
		hChildItem = hNextItem;
	}
	delete szPathName;


	//添加新项
	IEnumIDList  * peidl;
	LPITEMIDLIST pidl, pidlAbs;
	IShellFolder * psf = NULL;

	LPTREEPARAM    ptrParent  = (LPTREEPARAM)m_pTreeCtrl->GetItemData(hRefresh);
	IShellFolder * psfParent  = ptrParent->lpsf;
	LPITEMIDLIST   pidlParent = ptrParent->lpidl;
	HRESULT hr = psfParent->EnumObjects(NULL,SHCONTF_FOLDERS,&peidl);
	if ( NOERROR!=hr )
		return 0;

	while (NOERROR == hr)
	{
		hr = peidl->Next(1, &pidl, NULL);
		if (hr == S_FALSE || pidl == NULL)
			break;
		
		
		pidlAbs = ConcatPidl(pidlParent,pidl);
		
		
		hr = psfParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&psf);
		if (hr == S_FALSE || psf == NULL)
			break;
		
		
		char * szPathName = new char[MAX_PATH];
		ZeroMemory(szPathName,MAX_PATH);
		SHGetPathFromIDList(pidlAbs,szPathName);

		if ( FindSubItemByPath(hRefresh,szPathName)==NULL )
		{
			SHFILEINFO sfi;
			SHGetFileInfo((LPCTSTR)pidlAbs, 
				0,
				&sfi, 
				sizeof(SHFILEINFO), 
				SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_DISPLAYNAME);
		
			TV_INSERTSTRUCT TCItem;
			TCItem.hParent             = hRefresh;
			if ( hRefresh==m_hMyComputer )
				TCItem.hInsertAfter = TVI_LAST;
			else
				TCItem.hInsertAfter = TVI_SORT;
			TCItem.item.mask           = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
			TCItem.item.pszText        = sfi.szDisplayName;
			TCItem.item.iImage         = sfi.iIcon;
			TCItem.item.iSelectedImage = sfi.iIcon;

			LPTREEPARAM ptrItem = (LPTREEPARAM)m_pMalloc->Alloc(sizeof(TREEPARAM));
			ptrItem->lpsf    = psf;
			ptrItem->lpidl   = pidlAbs;
			ptrItem->uParam  = 1;
			TCItem.item.lParam   = (LPARAM)ptrItem;
			
			HTREEITEM hCur = m_pTreeCtrl->InsertItem(&TCItem);
			AddChildren(psf,pidlAbs, hCur, false);
		}
		delete szPathName;
	}

	peidl->Release();

	return 0;
}

BOOL CExplorerTreeView::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	if ( pMsg->message==WM_KEYDOWN )
	{
		switch ( pMsg->wParam )
		{
		case 0x2e:       //DEL
			{
				CShellFileOp op;

⌨️ 快捷键说明

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