列举shell namespace的树控件
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_)
#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; }