rovershen 阅读(873) 评论(2)
#if !defined(AFX_EXPLORERTREE_H__F22991C2_DB9C_11D6_B7DB_0080C82BE86B__INCLUDED_)
#define AFX_EXPLORERTREE_H__F22991C2_DB9C_11D6_B7DB_0080C82BE86B__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ExplorerTree.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CExplorerTree window
class CExplorerTree : public CTreeCtrl
{
public:
	HTREEITEM GetItemFromPath(CString&path);
	class FILEITEM{
	public:
		LPITEMIDLIST pidl;
		BOOL bListed;
		FILEITEM(){
			pidl=NULL;
			bListed=FALSE;
		}
	};
	typedef FILEITEM* LPFILEITEM;
	
	CExplorerTree(DWORD flag=SHCONTF_FOLDERS);//SHCONTF_NONFOLDER,SHCONTF_INCLUDEHIDDEN
	virtual ~CExplorerTree();
	void BuildTree();
	void RefreshTree(HTREEITEM item=NULL);
	void DeleteTree(HTREEITEM item=NULL);
	void ListFolder(HTREEITEM item);
	BOOL GetItemPath(HTREEITEM item,CString&path);
	void ExpandTree(HTREEITEM item);
	BOOL GetItemFolder(HTREEITEM&item,LPSHELLFOLDER&lpFolder);
	protected:
	LPMALLOC lpMalloc;
	LPSHELLFOLDER lpDesktop;
	DWORD dwListFlag;
//methods
	static int CALLBACK CompareItem(LPARAM lParam1,LPARAM lParam2,LPARAM lParam);
	LPITEMIDLIST Append(LPCITEMIDLIST pidlBase,LPCITEMIDLIST pidlAdd);
	LPITEMIDLIST MakeCopy(LPCITEMIDLIST pidl);
	UINT GetSize(LPCITEMIDLIST pidl);
	LPITEMIDLIST GetNextItemID(LPCITEMIDLIST pidl);
	int GetIcon(LPITEMIDLIST pidl,UINT flag=SHGFI_OPENICON);
	BOOL GetItemName(LPITEMIDLIST  pidl,CString&name);
	BOOL ItemIsFileSystem(LPITEMIDLIST pidl);
	// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CExplorerTree)
	public:
	//}}AFX_VIRTUAL

	// Generated message map functions
protected:
	BOOL EqualPIDL(LPITEMIDLIST&pidl1,LPITEMIDLIST&pidl2);
	HTREEITEM FindPath(HTREEITEM item,LPITEMIDLIST&pidl);
	//{{AFX_MSG(CExplorerTree)
	afx_msg void OnItemExpanded(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnDestroy();
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_EXPLORERTREE_H__F22991C2_DB9C_11D6_B7DB_0080C82BE86B__INCLUDED_)
// ExplorerTree.cpp : implementation file
//

#include "stdafx.h"
#include "ExplorerTree.h"
#include <atlconv.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CExplorerTree

CExplorerTree::CExplorerTree(DWORD flag)
{
	dwListFlag=flag;
	lpMalloc=NULL;
	lpDesktop=NULL;
}

CExplorerTree::~CExplorerTree()
{
}


BEGIN_MESSAGE_MAP(CExplorerTree, CTreeCtrl)
	//{{AFX_MSG_MAP(CExplorerTree)
	ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemExpanded)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExplorerTree message handlers
int CExplorerTree::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;
	BuildTree();
	return 0;
}

void CExplorerTree::RefreshTree(HTREEITEM item)
{
	if(ItemHasChildren(item)){
		DeleteTree(item);
	}
	ListFolder(item);
}

int CExplorerTree::GetIcon(LPITEMIDLIST pidl, UINT flag)
{
	SHFILEINFO sfi;
	flag|=(SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL);
	SHGetFileInfo((LPCTSTR)pidl,0,&sfi,sizeof(SHFILEINFO),flag);
	return sfi.iIcon;
}

BOOL CExplorerTree::GetItemName(LPITEMIDLIST pidl, CString &name)
{
	SHFILEINFO sfi;
	SHGetFileInfo((LPCTSTR)pidl,0,&sfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME|SHGFI_PIDL);
	name=sfi.szDisplayName;

	return TRUE;
}

void CExplorerTree::OnItemExpanded(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	*pResult = 0;
	HTREEITEM item=pNMTreeView->itemNew.hItem;
	if (ItemHasChildren(item)&&pNMTreeView->action==TVE_EXPAND){
		ExpandTree(pNMTreeView->itemNew.hItem);
	}
}

void CExplorerTree::DeleteTree(HTREEITEM item)
{
	LPSHELLFOLDER lpFolder=NULL;
	HTREEITEM root=item;
	if(root==NULL)
		root=GetRootItem();
	if(root==NULL)
		return;
	if (ItemHasChildren(root)){
		HTREEITEM hChildItem = GetChildItem(root);
		while (hChildItem != NULL)
		{
			DeleteTree(hChildItem);
			LPFILEITEM pItem=(LPFILEITEM)GetItemData(hChildItem);
			LPITEMIDLIST pidl=pItem->pidl;
			lpMalloc->Free(pidl);
			delete pItem;
			DeleteItem(hChildItem);
			hChildItem = GetChildItem(root);
		}
	}
}

void CExplorerTree::ListFolder(HTREEITEM item)
{
	HTREEITEM hRoot=item;
	if(item==NULL)
		hRoot=GetRootItem();
	LPFILEITEM pItem=(LPFILEITEM)GetItemData(hRoot);
	if(ItemHasChildren(hRoot))
		return;
	LPITEMIDLIST pidl,temp;
	int open;
	int nm;
	LPSHELLFOLDER lpFolder=NULL;
	if(!GetItemFolder(hRoot,lpFolder)||lpFolder==NULL)
		return;
	BeginWaitCursor();
	CString name;
	LPENUMIDLIST lpEnum=NULL;
	ULONG cnt;
	LPITEMIDLIST root=pItem->pidl;
	pItem->bListed=TRUE;
	if(SUCCEEDED(lpFolder->EnumObjects(0,dwListFlag,&lpEnum))){
		while(S_OK==lpEnum->Next(1,&temp,&cnt)){
			pidl=Append(root,temp);
			if(ItemIsFileSystem(pidl)){
				open=GetIcon(pidl);
				nm=GetIcon(pidl,0);
				GetItemName(pidl,name);

				pItem=new FILEITEM;
				pItem->pidl=pidl;
				HTREEITEM child=InsertItem(name,nm,open,hRoot);
				SetItemData(child,(DWORD)pItem);
			}
			else
				lpMalloc->Free(pidl);
			lpMalloc->Free(temp);
		}
		lpEnum->Release();
	}
	lpFolder->Release();
	TVSORTCB tvs;
	tvs.hParent = hRoot;
	tvs.lpfnCompare = CompareItem;
	tvs.lParam =(long)this;
	SortChildrenCB(&tvs);
	EndWaitCursor();
}

LPITEMIDLIST CExplorerTree::GetNextItemID(LPCITEMIDLIST pidl) 
{ 
	// Check for valid pidl.
	if(pidl == NULL)
		return NULL;
	
	// Get the size of the specified item identifier. 
	int cb = pidl->mkid.cb; 
	
	// If the size is zero, it is the end of the list. 
	if (cb == 0) 
		return NULL; 
	
	// Add cb to pidl (casting to increment by bytes). 
	pidl = (LPITEMIDLIST) (((LPBYTE) pidl) + cb); 
	
	// Return NULL if it is null-terminating, or a pidl otherwise. 
	return (pidl->mkid.cb == 0) ? NULL : (LPITEMIDLIST) pidl; 
} 

UINT CExplorerTree::GetSize(LPCITEMIDLIST pidl)
{
    UINT cbTotal = 0;
    if (pidl)
    {
        cbTotal += sizeof(pidl->mkid.cb);    // Null terminator
        while (pidl)
        {
            cbTotal += pidl->mkid.cb;
            pidl = GetNextItemID(pidl);
        }
    }
    return cbTotal;
}

LPITEMIDLIST CExplorerTree::MakeCopy(LPCITEMIDLIST pidl)
{
    UINT cb = 0;
	LPITEMIDLIST pidlTemp = (LPITEMIDLIST) pidl;
	
	// Calculate size of list.
    cb = GetSize(pidl);
	
    LPITEMIDLIST pidlRet = (LPITEMIDLIST)lpMalloc->Alloc(cb);
    if (pidlRet)
        CopyMemory(pidlRet, pidl, cb);
    return pidlRet;
}

LPITEMIDLIST CExplorerTree::Append(LPCITEMIDLIST pidlBase, LPCITEMIDLIST pidlAdd)
{
    if(pidlBase == NULL)
        return NULL;
    if(pidlAdd == NULL)
        return MakeCopy(pidlBase);
    
    LPITEMIDLIST pidlNew;
	
    UINT cb1 = GetSize(pidlBase) - sizeof(pidlBase->mkid.cb);
    UINT cb2 = GetSize(pidlAdd);
	
    pidlNew = (LPITEMIDLIST)lpMalloc->Alloc(cb1 + cb2);
    if (pidlNew)
    {
        CopyMemory(pidlNew, pidlBase, cb1);
        CopyMemory(((LPSTR)pidlNew) + cb1, pidlAdd, cb2);
    }
    return pidlNew;
}

BOOL CExplorerTree::GetItemFolder(HTREEITEM &item, LPSHELLFOLDER &lpFolder)
{
	HTREEITEM parent=item;
	LPITEMIDLIST pidl=NULL;
	if(item==GetRootItem())
		return SUCCEEDED(lpDesktop->QueryInterface(IID_IShellFolder,(void**)&lpFolder));
	LPFILEITEM pItem=(LPFILEITEM)GetItemData(item);
	pidl=pItem->pidl;
	HRESULT hres=lpDesktop->BindToObject(pidl,0,IID_IShellFolder,(void**)&lpFolder);
	return SUCCEEDED(hres);
}

void CExplorerTree::OnDestroy() 
{
	DeleteTree();
	HTREEITEM root=GetRootItem();
	if(root==NULL)
		return;
	LPFILEITEM pItem=(LPFILEITEM)GetItemData(root);
	LPITEMIDLIST pidl=pItem->pidl;
	lpMalloc->Free(pidl);
	delete pItem;
	DeleteAllItems();
	if(lpMalloc)
		lpMalloc->Release();
	if(lpDesktop)
		lpDesktop->Release();
	CTreeCtrl::OnDestroy();
}

void CExplorerTree::BuildTree()
{
	if(lpMalloc||lpDesktop||GetRootItem())
		return;
	SHFILEINFO sfi;
	ZeroMemory(&sfi,sizeof(SHFILEINFO));
	HIMAGELIST hil=(HIMAGELIST)SHGetFileInfo("*.txt",FILE_ATTRIBUTE_NORMAL,&sfi,sizeof(SHFILEINFO),
		SHGFI_USEFILEATTRIBUTES|SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
	if(hil){
		CImageList *pim=CImageList::FromHandle(hil);
		SetImageList(pim,LVSIL_NORMAL);
		pim->Detach();
	}
	SHGetMalloc(&lpMalloc);
	SHGetDesktopFolder(&lpDesktop);
	LPITEMIDLIST pidl=(LPITEMIDLIST)lpMalloc->Alloc(sizeof(USHORT));
	*((USHORT*)pidl)=0;
	int open=GetIcon(pidl);
	int nm=GetIcon(pidl,0);
	CString name;
	GetItemName(lpDesktop,pidl,name);
	HTREEITEM hRoot=InsertItem(name,nm,open);
	LPFILEITEM pItem=new FILEITEM;
	pItem->pidl=pidl;
	SetItemData(hRoot,(DWORD)pItem);
	RefreshTree(hRoot);
	Expand(hRoot,TVE_EXPAND);
}

BOOL CExplorerTree::GetItemPath(HTREEITEM item, CString &path)
{
	LPFILEITEM pItem=(LPFILEITEM)GetItemData(item);
	LPITEMIDLIST pidl=pItem->pidl;
	BOOL ret=SHGetPathFromIDList(pidl,path.GetBuffer(MAX_PATH));
	path.ReleaseBuffer();
	return ret;
}

int CExplorerTree::CompareItem(LPARAM lParam1, LPARAM lParam2, LPARAM lParam)
{
	LPITEMIDLIST p1=((LPFILEITEM)lParam1)->pidl;
	LPITEMIDLIST p2=((LPFILEITEM)lParam2)->pidl;
	CString name1,name2;
	CExplorerTree*pTree=(CExplorerTree*)lParam;
	SHGetPathFromIDList(p1,name1.GetBuffer(MAX_PATH));
	name1.ReleaseBuffer();
	SHGetPathFromIDList(p2,name2.GetBuffer(MAX_PATH));
	name2.ReleaseBuffer();
	if(name1.IsEmpty()&&name2.IsEmpty()){
		pTree->GetItemName(pTree->lpDesktop,p1,name1);
		pTree->GetItemName(pTree->lpDesktop,p2,name2);
	}
	if(name1.IsEmpty()&&!name2.IsEmpty())
		return 1;
	if(name2.IsEmpty()&&!name1.IsEmpty())
		return -1;
	return strcmpi(name1,name2);
}

void CExplorerTree::ExpandTree(HTREEITEM item)
{
	LPFILEITEM pItem=(LPFILEITEM)GetItemData(item);
	if(ItemHasChildren(item)){
		HTREEITEM hChildItem = GetChildItem(item);
		while (hChildItem != NULL)
		{
			LPFILEITEM pItem=(LPFILEITEM)GetItemData(hChildItem);
			if(!pItem->bListed)
				ListFolder(hChildItem);
			hChildItem = GetNextItem(hChildItem, TVGN_NEXT);
		}
	}
//	RedrawWindow();
}

BOOL CExplorerTree::ItemIsFileSystem(LPITEMIDLIST pidl)
{
	SHFILEINFO sfi;
	UINT flag=(SHGFI_ATTRIBUTES|SHGFI_PIDL);
	SHGetFileInfo((LPCTSTR)pidl,0,&sfi,sizeof(SHFILEINFO),flag);
	return TRUE;//(sfi.dwAttributes&(SFGAO_FILESYSTEM|SFGAO_FILESYSANCESTOR));
}

HTREEITEM CExplorerTree::GetItemFromPath(CString &path)
{
	USES_CONVERSION;
	LPITEMIDLIST pidl;
/*	if(pidl!=NULL){
		HTREEITEM item=FindPath(GetRootItem(),pidl);
		lpMalloc->Free(pidl);
		return item;
	}
	else
		return NULL;
*/
	CString xx;
	HTREEITEM item=GetRootItem();
	int index=0;
	do{
		index=path.Find("\\",index+1);
		if(index!=-1)
			xx=path.Left(index+1);
		else
			xx=path;
		if(NOERROR!=lpDesktop->ParseDisplayName(0,0,A2W(xx),0,&pidl,0))
			return NULL;
		item=FindPath(item,pidl);
		if(item)
			ExpandTree(GetParentItem(item));
		lpMalloc->Free(pidl);
	}while(xx!=path);
	return item;
}

HTREEITEM CExplorerTree::FindPath(HTREEITEM item, LPITEMIDLIST &pidl)
{
	LPFILEITEM pItem=(LPFILEITEM)GetItemData(item);
	CString text=GetItemText(item);
	if(EqualPIDL(pItem->pidl,pidl))
		return item;
	if(!ItemHasChildren(item))
		return NULL;
	HTREEITEM hFound=NULL;
	HTREEITEM hChildItem = GetChildItem(item);
	while (hChildItem != NULL)
	{
		text=GetItemText(hChildItem);
		hFound=FindPath(hChildItem,pidl);
		if(hFound!=NULL)
			break;
		hChildItem = GetNextItem(hChildItem, TVGN_NEXT);
	}
	return hFound;
}

BOOL CExplorerTree::EqualPIDL(LPITEMIDLIST &pidl1, LPITEMIDLIST &pidl2)
{
	UINT sz=GetSize(pidl1);
	if(sz!=GetSize(pidl2))
		return FALSE;
	BYTE* p1=(BYTE*)pidl1;
	BYTE* p2=(BYTE*)pidl2;
	for(UINT i=0;i<sz;i++){
		if(*p1++!=*p2++)
			return FALSE;
	}
	return TRUE;
}

评论列表
rovershen
re: 列举shell namespace的树控件
因为要列举整个“我的电脑”下的所有对象
david
re: 列举shell namespace的树控件
BOOL CExplorerTree::GetItemName(LPITEMIDLIST pidl, CString &name)
好象参数不对呢,有的地方需要三个参数啊 
daiweiwang2002@163.com

发表评论
切换编辑模式