www.pudn.com > source.rar > ShellTree.cpp


// ShellTree.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "FlashNow.h" 
#include "BrowserFrame.h" 
#include "ShellTree.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CShellTree 
 
CShellTree::CShellTree() 
{ 
    p_List=NULL; 
} 
 
CShellTree::~CShellTree() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CShellTree, CTreeCtrl) 
//{{AFX_MSG_MAP(CShellTree) 
ON_WM_CREATE() 
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemExpanding) 
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChanged) 
ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteItem) 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CShellTree message handlers 
 
void CShellTree::AssociateList(CShellList *pList) 
{ 
    p_List=pList; 
} 
 
void CShellTree::SetImageList() 
{ 
    CTreeCtrl::SetImageList(CShell::GetImageList(TRUE),TVSIL_NORMAL); 
} 
 
int CShellTree::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
    if (CTreeCtrl::OnCreate(lpCreateStruct) == -1) 
        return -1; 
     
    SetImageList();	 
    BuildTree(); 
    return 0; 
} 
 
HTREEITEM CShellTree::SetSelection(CString Path,BOOL Check) 
{ 
    HTREEITEM Item=h_Desktop; 
     
    if(!Path.IsEmpty()&&Path.Right(1)!='\\') 
        Path+='\\'; 
     
    if(Check&&!IsValidPath(Path)) 
        return NULL; 
     
    Path.MakeUpper(); 
     
    int Which=0; 
    int BigMatch=0; 
     
    for(int i=0;i=0) 
        { 
            int Length=m_SpecialFolder[i].GetLength(); 
            if(Length>BigMatch) 
            { 
                BigMatch=Length; 
                Which=i; 
            } 
        } 
    } 
     
    if(!BigMatch) 
        return NULL; 
     
    Item=h_SpecialFolder[Which]; 
    Expand(Item,TVE_EXPAND); 
     
    int FullLength=Path.GetLength(); 
     
    for(i=BigMatch;iFree(pIDList);   
            lpMalloc->Release(); 
        } 
         
        if(!h_Desktop) 
            h_Desktop=TVI_ROOT; 
         
        FillTree(pDesktopShellFolder,NULL,h_Desktop); 
        pDesktopShellFolder->Release(); 
    } 
     
    FillSpecialFolders(); 
    hItem = GetRootItem(); 
    Expand(hItem,TVE_EXPAND); 
     
    SetRedraw(TRUE); 
    m_Building = FALSE; 
} 
 
/**************************************************************************** 
* 
*  FUNCTION: FillTree( LPSHELLFOLDER pParentShellFolder, 
*                      LPITEMIDLIST  pParentFullIDList, 
*                      HTREEITEM     hParent) 
* 
*  PURPOSE: Fills a branch of the TreeView control.  Given the 
*           shell folder, enumerate the subitems of this folder, 
*           and add the appropriate items to the tree. 
* 
*  PARAMETERS: 
*    pParentShellFolder         - Pointer to shell folder that we want to enumerate items  
*    pParentFullIDList        - Fully qualified item id list to the item that we are enumerating 
*                   items for.  In other words, this is the pIDList to the item 
*                   identified by the pParentShellFolder parameter. 
*    hParent      - Parent node 
* 
*  COMMENTS: 
*    This function enumerates the items in the folder identifed by pParentShellFolder. 
*    Note that since we are filling the left hand pane, we will only add 
*    items that are folders and/or have sub-folders.  We *could* put all 
*    items in here if we wanted, but that's not the intent. 
* 
****************************************************************************/ 
 
void CShellTree::FillTree(LPSHELLFOLDER pParentShellFolder, LPITEMIDLIST pParentFullIDList, HTREEITEM hParent) 
{ 
    if(!pParentShellFolder) 
        return; 
    HTREEITEM       hPrev = NULL; 
    LPENUMIDLIST    lpe=NULL; 
    LPITEMIDLIST    pIDList=NULL, pFullIDList=NULL; 
    CShellTreeItemData *    pStid=NULL; 
    LPMALLOC        lpMalloc=NULL; 
    ULONG           ulFetched; 
    HRESULT         hr; 
     
    hr = SHGetMalloc(&lpMalloc); 
    if (FAILED(hr)) 
        return; 
     
    DWORD dwFlags = SHCONTF_FOLDERS; 
    if( m_ShowHidden ) 
        dwFlags |= SHCONTF_INCLUDEHIDDEN; 
     
    hr = pParentShellFolder->EnumObjects(GetSafeHwnd(), dwFlags, &lpe); 
     
    if (SUCCEEDED(hr)) 
    { 
        while (S_OK == lpe->Next(1, &pIDList, &ulFetched)) 
        { 
            hPrev = InsertItem(pParentShellFolder,pParentFullIDList,pIDList,hParent,hPrev); 
        } 
         
        lpMalloc->Free(pIDList); 
        pIDList=NULL; 
    } 
     
    if (lpe)   
        lpe->Release(); 
     
    if (lpMalloc)  
        lpMalloc->Release(); 
} 
 
void CShellTree::OnItemExpanding(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
    CShellTreeItemData *   pStid; 
    HRESULT        hr; 
    LPSHELLFOLDER  pShellFolder=NULL; 
    static char    szBuff[_MAX_PATH]; 
    TV_SORTCB      tvscb; 
     
    NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR; 
     
    if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE)) 
        return; 
     
    pStid=(CShellTreeItemData *)pnmtv->itemNew.lParam; 
    if (pStid) 
    { 
        hr=pStid->m_pParentShellFolder->BindToObject(pStid->m_pIDList, 
            0, IID_IShellFolder,(LPVOID *)&pShellFolder); 
         
        if (SUCCEEDED(hr)) 
        { 
            FillTree(pShellFolder,pStid->m_pFullIDList,pnmtv->itemNew.hItem); 
        } 
         
        tvscb.hParent     = pnmtv->itemNew.hItem; 
        tvscb.lParam      = 0; 
        tvscb.lpfnCompare = SortProc; 
    } 
     
    *pResult=0; 
} 
 
HTREEITEM CShellTree::InsertItem(LPSHELLFOLDER pParentShellFolder, LPITEMIDLIST pParentFullIDList,LPITEMIDLIST pIDList,HTREEITEM hParent,HTREEITEM hItem) 
{ 
    TV_ITEM         tvi; 
    TV_INSERTSTRUCT tvins; 
    LPITEMIDLIST    pFullIDList=NULL; 
    CShellTreeItemData *    pStid=NULL; 
    LPMALLOC        lpMalloc=NULL; 
    HRESULT         hr; 
    char            szBuff[_MAX_PATH]; 
     
    hr = SHGetMalloc(&lpMalloc); 
    if (FAILED(hr)) 
        return NULL; 
     
    ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER; 
    pParentShellFolder->GetAttributesOf(1, (const struct _ITEMIDLIST **)&pIDList, &ulAttrs); 
    if (ulAttrs & SFGAO_FOLDER) 
    { 
        tvi.mask= TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; 
        if (ulAttrs & SFGAO_HASSUBFOLDER) 
        { 
            tvi.cChildren=1; 
            tvi.mask |= TVIF_CHILDREN; 
        } 
         
        pStid = (CShellTreeItemData *)lpMalloc->Alloc(sizeof(CShellTreeItemData)); 
        if (!pStid) 
        { 
            lpMalloc->Release(); 
            return NULL; 
        } 
         
        if (!GetItemName(pParentShellFolder, pIDList, SHGDN_NORMAL, szBuff)) 
        { 
            lpMalloc->Release(); 
            return NULL; 
        } 
         
        tvi.pszText    = szBuff; 
        tvi.cchTextMax = _MAX_PATH; 
        pFullIDList = ConcatPidl(pParentFullIDList, pIDList); 
         
        pStid->m_pIDList = CopyPidl(lpMalloc, pIDList); 
         
        tvi.iImage = GetItemIcon(pFullIDList, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON); 
        tvi.iSelectedImage = GetItemIcon(pFullIDList, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON |	SHGFI_OPENICON); 
         
        pStid->m_pParentShellFolder = pParentShellFolder; 
        pParentShellFolder->AddRef(); 
         
        pStid->m_pFullIDList = ConcatPidl(pParentFullIDList, pIDList); 
         
        tvi.lParam = (LPARAM)pStid; 
         
        tvins.item         = tvi; 
        tvins.hInsertAfter = hItem; 
        tvins.hParent      = hParent; 
        hItem = CTreeCtrl::InsertItem(&tvins); 
         
        lpMalloc->Free(pFullIDList);   
        pFullIDList=NULL; 
         
    } 
     
    if (lpMalloc)  
        lpMalloc->Release(); 
     
    TV_SORTCB tvscb; 
    tvscb.hParent=hParent; 
    tvscb.lParam=0; 
    tvscb.lpfnCompare=SortProc; 
     
    SortChildrenCB(&tvscb); 
    return hItem; 
} 
 
void CShellTree::OnSelChanged(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
    if(m_Building) 
        return; 
     
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; 
     
    if(!p_List||!p_List->GetSafeHwnd()) 
        return; 
     
    CString FullPath=GetItemFullPath(pNMTreeView->itemNew.hItem); 
     
    ::theApp.SetWindowTitle(FullPath,TRUE);	 
    ::theApp.m_UserData.m_LastPath=FullPath; 
     
    PopulateList(pNMTreeView->itemNew.hItem); 
} 
 
void CShellTree::OnDeleteItem(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; 
    *pResult = 0; 
     
    HRESULT        hr; 
    LPMALLOC       lpMalloc; 
    CShellTreeItemData *  pStid; 
     
    pStid=(CShellTreeItemData *)pNMTreeView->itemOld.lParam; 
    if(!pStid) 
        return; 
     
    hr=SHGetMalloc(&lpMalloc); 
    if (FAILED(hr)) 
        return; 
     
    pStid->m_pParentShellFolder->Release(); 
    lpMalloc->Free(pStid->m_pIDList);   
    lpMalloc->Free(pStid->m_pFullIDList);   
    lpMalloc->Free(pStid);   
    lpMalloc->Release(); 
     
    *pResult = 0; 
} 
 
//函数FindChild,在子项中查找指定目录项 
//参数hParent,父目录 
//参数pSlid,指定目录项的项数据 
//返回查找结果,NULL为查找失败 
HTREEITEM CShellTree::FindChild(HTREEITEM hParent, CShellListItemData *pSlid) 
{ 
    //是否包含子项 
    if (ItemHasChildren(hParent)) 
    { 
        HTREEITEM hChildItem = GetChildItem(hParent); 
        //查看所有子项 
        while (hChildItem) 
        { 
            //比较子项内容 
            if(!CompareStid(GetItemData(hChildItem),(LPARAM)pSlid)) 
                return hChildItem; 
            hChildItem = GetNextItem(hChildItem, TVGN_NEXT); 
        } 
    } 
    //查找失败,返回NULL 
    return NULL; 
} 
 
CString CShellTree::GetItemFullPath(HTREEITEM Item) 
{ 
    CString FullPath; 
     
    CShellTreeItemData * pStid=(CShellTreeItemData *)GetItemData(Item); 
    if(!pStid) 
        return FullPath; 
    TCHAR szBuff[_MAX_PATH]; 
     
    SHGetPathFromIDList(pStid->m_pFullIDList,szBuff); 
    FullPath=szBuff; 
     
    if(!FullPath.IsEmpty()&&FullPath.Right(1)!='\\') 
        FullPath+='\\'; 
     
    return FullPath; 
} 
 
CString CShellTree::GetSelectedItemFullPath() 
{ 
    return GetItemFullPath(GetSelectedItem()); 
} 
 
void CShellTree::FillSpecialFolders() 
{ 
    HTREEITEM Item; 
    LPITEMIDLIST pComputerIDList; 
    h_SpecialFolder[m_SpecialFolderCount]=h_Desktop; 
    m_SpecialFolder[m_SpecialFolderCount++]=GetItemFullPath(h_Desktop); 
     
    if(FAILED(SHGetSpecialFolderLocation(NULL,CSIDL_DRIVES,&pComputerIDList))) 
        return; 
     
    Item=GetChildItem(h_Desktop); 
    while(Item) 
    { 
        LPARAM lparam=GetItemData(Item); 
         
        if(!CompareStid(lparam,pComputerIDList)) 
            h_Computer=Item; 
        else 
        { 
            m_SpecialFolder[m_SpecialFolderCount]=GetItemFullPath(Item); 
            if(!m_SpecialFolder[m_SpecialFolderCount].IsEmpty()) 
                h_SpecialFolder[m_SpecialFolderCount++]=Item; 
        } 
         
        Item=this->GetNextSiblingItem(Item); 
    } 
    Expand(h_Computer,TVE_EXPAND); 
    Item=GetChildItem(h_Computer); 
    while(Item) 
    { 
        m_SpecialFolder[m_SpecialFolderCount]=GetItemFullPath(Item); 
        if(!m_SpecialFolder[m_SpecialFolderCount].IsEmpty()) 
            h_SpecialFolder[m_SpecialFolderCount++]=Item; 
         
        Item=this->GetNextSiblingItem(Item); 
    } 
     
    ASSERT(m_SpecialFolderCount<=26); 
     
    LPMALLOC lpMalloc=NULL; 
    if (FAILED(SHGetMalloc(&lpMalloc))) 
        return; 
    lpMalloc->Free(pComputerIDList);   
    lpMalloc->Release(); 
} 
 
HTREEITEM CShellTree::FindChild(HTREEITEM hItem, CString Path) 
{ 
    HTREEITEM hFound=GetChildItem(hItem); 
    while (hFound) 
    { 
        CString Item=GetItemText(hFound); 
        Item.MakeUpper(); 
        if(!Path.Compare(Item)) 
            return hFound; 
        hFound=GetNextItem(hFound,TVGN_NEXT); 
    } 
    return NULL; 
} 
 
void CShellTree::Refresh() 
{ 
    CString FullPath=GetSelectedItemFullPath(); 
    BuildTree(); 
    if(!SetSelection(FullPath)) 
        SelectRootItem(); 
} 
 
void CShellTree::SelectRootItem() 
{ 
    SelectItem(h_Computer); 
} 
 
void CShellTree::ItemUp() 
{ 
    HTREEITEM hItem=GetSelectedItem(); 
    if(hItem) 
    { 
        hItem=GetParentItem(hItem); 
        if(hItem) 
            SelectItem(hItem); 
    } 
} 
 
BOOL CShellTree::RootReached() 
{ 
    HTREEITEM hItem=GetSelectedItem(); 
    return (!hItem||hItem==h_Desktop); 
} 
 
//函数PopulateList,展开指定目录项 
//参数Item,指定目录项 
void CShellTree::PopulateList(HTREEITEM Item) 
{ 
    CShellTreeItemData *pStid; 
    LPSHELLFOLDER pShellFolder = NULL; 
    HRESULT hr; 
     
    pStid = (CShellTreeItemData *)GetItemData(Item); 
    if(pStid) 
    { 
        //顶级目录 
        if(Item == h_Desktop) 
        { 
            p_List->PopulateList(pStid->m_pParentShellFolder,pStid,Item); 
            return; 
        } 
         
        hr = pStid->m_pParentShellFolder->BindToObject(pStid->m_pIDList, 
            0,IID_IShellFolder,(LPVOID *)&pShellFolder); 
         
        //显示文件列表 
        if(SUCCEEDED(hr)) 
            p_List->PopulateList(pShellFolder,pStid,Item); 
    } 
}