IEFolderTreeCtrl.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:15k
- //*******************************************************************************
- // COPYRIGHT NOTES
- // ---------------
- // You may use this source code, compile or redistribute it as part of your application
- // for free. You cannot redistribute it as a part of a software development
- // library without the agreement of the author. If the sources are
- // distributed along with the application, you should leave the original
- // copyright notes in the source code without any changes.
- // This code can be used WITHOUT ANY WARRANTIES at your own risk.
- //
- // For the latest updates to this code, check this site:
- // http://www.masmex.com
- // after Sept 2000
- //
- // Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
- //*******************************************************************************
- #include "stdafx.h"
- #include "IEFolderTreeCtrl.h"
- #include "UIMessages.h"
- #include <vector>
- #include <map>
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- typedef map<CShellPidlCompare,HTREEITEM> mapPidlToHTREEITEM;
- typedef vector<LPITEMIDLIST> vecPidl;
- int CALLBACK CIEFolderTreeCtrl::CompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
- {
- LPTVITEMDATA lptvid1 = (LPTVITEMDATA)((CUIListCtrlData*)lParam1)->GetExtData();
- LPTVITEMDATA lptvid2 = (LPTVITEMDATA)((CUIListCtrlData*)lParam2)->GetExtData();
- LPSHELLFOLDER psfParent = (LPSHELLFOLDER)lParamSort;
- HRESULT hr = psfParent->CompareIDs (0, lptvid1->lpi, lptvid2->lpi);
- if (FAILED (hr))
- return 0;
- return (short)hr;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CIEFolderTreeCtrl
- CIEFolderTreeCtrl::CIEFolderTreeCtrl()
- {
- SHGetMalloc(&m_pMalloc);
- m_hImageList = NULL;
- }
- CIEFolderTreeCtrl::~CIEFolderTreeCtrl()
- {
- // Free our memory allocator
- if (m_pMalloc)
- m_pMalloc->Release();
- }
- void CIEFolderTreeCtrl::Refresh()
- {
- HTREEITEM hItem = GetRootItem();
- if (hItem == NULL)
- return;
- CWaitCursor w;
- SetRedraw(FALSE);
- RefreshNode(hItem);
- SetRedraw(TRUE);
- }
- void CIEFolderTreeCtrl::OnDeleteItemData(DWORD dwData)
- {
- LPTVITEMDATA pItemData=(LPTVITEMDATA)dwData;
- if (pItemData == NULL)
- return;
- if (pItemData->lpsfParent)
- pItemData->lpsfParent->Release();
- if (pItemData->lpi)
- m_pMalloc->Free(pItemData->lpi);
- if (pItemData->lpifq)
- m_pMalloc->Free(pItemData->lpifq);
- m_pMalloc->Free(pItemData);
- }
- BOOL CIEFolderTreeCtrl::LoadURL(HTREEITEM hItem)
- {
- if (GetRootItem() == hItem)
- return FALSE;
- if (ItemHasChildren(hItem))
- return FALSE;
- CString strText(GetItemText(hItem));
- AfxMessageBox(strText);
- return TRUE;
- }
- bool CIEFolderTreeCtrl::LoadItems(LPCTSTR pszPath,DWORD dwFolderType)
- {
- ASSERT(m_pMalloc);
- if (m_hImageList == NULL)
- Init();
- bool bRet = false;
- CWaitCursor w;
- DeleteAllItems();
- //DeleteItemData();
- LPITEMIDLIST pidl=NULL;
- LPSHELLFOLDER psfDesktop=NULL;
- LPSHELLFOLDER pSubFolder=NULL;
- HRESULT hr = SHGetDesktopFolder(&psfDesktop);
- if (dwFolderType)
- {
- hr = SHGetSpecialFolderLocation(NULL, dwFolderType, &pidl);
- #ifdef _DEBUG
- CString sPath;
- GetShellPidl().SHPidlToPathEx(pidl,sPath);
- TRACE1("Populating special folder %sn",sPath);
- #endif
- hr = psfDesktop->BindToObject(pidl, 0, IID_IShellFolder,(LPVOID*)&pSubFolder);
- }
- else
- {
- if (pszPath && *pszPath != ' ')
- {
- hr = m_ShellPidl.SHPathToPidlEx(pszPath,&pidl,psfDesktop);
- if (SUCCEEDED(hr))
- {
- hr = psfDesktop->BindToObject(pidl, 0, IID_IShellFolder,(LPVOID*)&pSubFolder);
- if (SUCCEEDED(hr))
- m_sRootPath = pszPath;
- }
- }
- else
- {
- hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
- }
- }
- LPCTSTR pszTitle=NULL;
- SHFILEINFO fileInfo;
- ZeroMemory(&fileInfo,sizeof(fileInfo));
- int nImage=0, nSelImage=0;
- if (pidl)
- {
- SHGetFileInfo((LPCTSTR)pidl, NULL, &fileInfo, sizeof(fileInfo), SHGFI_PIDL|SHGFI_ATTRIBUTES|SHGFI_DISPLAYNAME);
- pszTitle = fileInfo.szDisplayName;
- m_ShellPidl.GetNormalAndSelectedIcons(pidl, nImage, nSelImage);
- if (nImage < 0)
- nImage = 0;
- if (nSelImage < 0)
- nSelImage = 0;
- }
- if (SUCCEEDED(hr))
- {
- LPTVITEMDATA lptvid = (LPTVITEMDATA)m_pMalloc->Alloc(sizeof(TVITEMDATA));
- if (lptvid == NULL)
- return bRet;
- ZeroMemory(lptvid,sizeof(TVITEMDATA));
- // Now make a copy of the ITEMIDLIST.
- lptvid->lpi = m_ShellPidl.CopyLastItemID(pidl);
- lptvid->lpifq = m_ShellPidl.CopyItemIDList(pidl);
- lptvid->lpsfParent = NULL;
- if (lptvid->lpsfParent)
- lptvid->lpsfParent->AddRef();
- HTREEITEM hRootItem = AddAnItem((HTREEITEM)NULL,pszTitle,(LPARAM)lptvid,(HTREEITEM)TVI_ROOT,nImage,nSelImage);
- AddItems(hRootItem,pSubFolder ? pSubFolder : psfDesktop);
- Expand(hRootItem,TVE_EXPAND);
- PostMessage(WM_APP_POPULATE_TREE);
- bRet = true;
- }
- if (pidl)
- m_pMalloc->Free(pidl);
- if (pSubFolder)
- pSubFolder->Release();
- if (psfDesktop)
- psfDesktop->Release();
- return bRet;
- }
- bool CIEFolderTreeCtrl::AddItems(HTREEITEM hItem,IShellFolder* pFolder)
- {
- IEnumIDList* pItems = NULL;
- LPITEMIDLIST pidlNext = NULL;
- DWORD dwFlags = SHCONTF_FOLDERS;
- if (GetShellSettings().ShowAllObjects() && !GetShellSettings().ShowSysFiles())
- dwFlags |= SHCONTF_INCLUDEHIDDEN;
- // Enumerate all object in the given folder
- HRESULT hr = pFolder->EnumObjects(NULL, dwFlags, &pItems);
- if (hr != NOERROR)
- return false;
- while (NOERROR == hr)
- {
- hr = pItems->Next(1, &pidlNext, NULL);
- if (hr == S_FALSE || pidlNext == NULL)
- break;
- if (AddFolder(hItem,pidlNext,pFolder) == NULL)
- m_pMalloc->Free(pidlNext);
- pidlNext = NULL;
- }
- if (pidlNext)
- m_pMalloc->Free(pidlNext);
- if (pItems)
- pItems->Release();
- Sort(hItem,pFolder);
- return true;
- }
- void CIEFolderTreeCtrl::Sort(HTREEITEM hParent,LPSHELLFOLDER pFolder)
- {
- // Sort the the node based on pidls
- TVSORTCB cbSort;
- cbSort.hParent = hParent;
- cbSort.lpfnCompare = CompareProc;
- cbSort.lParam = (LPARAM)pFolder;
- SortChildrenCB(&cbSort);
- }
- HTREEITEM CIEFolderTreeCtrl::AddFolder(HTREEITEM hItem,LPCTSTR pszPath)
- {
- LPITEMIDLIST pidlfq=NULL;
- HRESULT hr = GetShellPidl().SHPathToPidlEx(pszPath,&pidlfq,NULL);
- if (FAILED(hr))
- return NULL;
- LPTVITEMDATA lptvid = (LPTVITEMDATA)GetItemData(hItem);
- ASSERT(lptvid);
- LPITEMIDLIST pidl = GetShellPidl().CopyLastItemID(pidlfq);
- HTREEITEM hFolderItem = AddFolder(hItem,pidl,lptvid->lpsfParent);
- if (pidlfq)
- m_pMalloc->Free(pidlfq);
- return hFolderItem;
- }
- HTREEITEM CIEFolderTreeCtrl::AddFolder(HTREEITEM hItem,LPITEMIDLIST pidl,LPSHELLFOLDER pFolder)
- {
- ASSERT(m_pMalloc);
- LPTSTR pszFilePath = NULL;
- STRRET StrRetFilePath;
- SHFILEINFO FileInfo;
- ZeroMemory(&FileInfo,sizeof(FileInfo));
- FileInfo.dwAttributes=SFGAO_HASSUBFOLDER | SFGAO_FOLDER;
- HRESULT hr = pFolder->GetAttributesOf(1,(LPCITEMIDLIST*)&pidl,&FileInfo.dwAttributes);
- if (FAILED(hr))
- return NULL;
- // Create a submenu if this item is a folder
- if (!(FileInfo.dwAttributes & (SFGAO_HASSUBFOLDER | SFGAO_FOLDER)))
- return NULL;
- pFolder->GetDisplayNameOf(pidl,SHGDN_INFOLDER,&StrRetFilePath);
- GetShellPidl().StrRetToStr(StrRetFilePath, &pszFilePath, pidl);
- if (pszFilePath)
- {
- lstrcpy(FileInfo.szDisplayName,pszFilePath);
- m_pMalloc->Free(pszFilePath);
- pszFilePath = NULL;
- }
- // allocate new itemdata
- LPTVITEMDATA lptvid = (LPTVITEMDATA)m_pMalloc->Alloc(sizeof(TVITEMDATA));
- if (lptvid == NULL)
- return NULL;
- ZeroMemory(lptvid,sizeof(TVITEMDATA));
- // get itemdata for current node
- LPTVITEMDATA lpptvid = (LPTVITEMDATA)GetItemData(hItem);
- ASSERT(lpptvid);
- // create new fully qualified pidl
- lptvid->lpifq = m_ShellPidl.ConcatPidl(lpptvid->lpifq,pidl);
- // save relative pidl (will be freed in the clean up)
- lptvid->lpi = pidl;
- int nImage=0;
- int nSelImage=0;
- // get icons for new fq pidl
- m_ShellPidl.GetNormalAndSelectedIcons(lptvid->lpifq, nImage, nSelImage);
- // save folder for later use(when node is expanded)
- lptvid->lpsfParent = pFolder; // pointer to parent folder
- // keep hold of it(will be released in clean up)
- lptvid->lpsfParent->AddRef();
- // add the node to the tree unsorted (will be sorted later)
- int nChildren = 0;
- if (FileInfo.dwAttributes & SFGAO_HASSUBFOLDER)
- {
- nChildren=1;
- }
- HTREEITEM hNewItem = AddAnItem(hItem,FileInfo.szDisplayName,(DWORD)lptvid,(HTREEITEM)TVI_FIRST,nImage,nSelImage,nChildren);
- // set overlay images
- if (hNewItem)
- {
- SetAttributes(hNewItem,pFolder,pidl);
- }
- return hNewItem;
- }
- void CIEFolderTreeCtrl::SetAttributes(HTREEITEM hItem,LPSHELLFOLDER pFolder,LPITEMIDLIST pidl)
- {
- DWORD dwAttributes = SFGAO_DISPLAYATTRMASK | SFGAO_REMOVABLE;
- HRESULT hr = pFolder->GetAttributesOf(1,(LPCITEMIDLIST*)&pidl,&dwAttributes);
- if (FAILED(hr))
- return;
- if ((dwAttributes & SFGAO_COMPRESSED) && GetShellSettings().ShowCompColor())
- SetTextColor(hItem,RGB(0,0,255));
- else
- SetDefaultTextColor(hItem);
- if (dwAttributes & SFGAO_GHOSTED)
- SetItemState(hItem,TVIS_CUT,TVIS_CUT);
- else
- SetItemState(hItem,TVIS_CUT,0);
- if (dwAttributes & SFGAO_LINK)
- SetItemState(hItem,INDEXTOOVERLAYMASK(2),TVIS_OVERLAYMASK);
- else
- SetItemState(hItem,0,TVIS_OVERLAYMASK);
- if (dwAttributes & SFGAO_SHARE)
- SetItemState(hItem,INDEXTOOVERLAYMASK(1),TVIS_OVERLAYMASK);
- else
- SetItemState(hItem,0,TVIS_OVERLAYMASK);
- }
- BEGIN_MESSAGE_MAP(CIEFolderTreeCtrl, CUITreeCtrl)
- //{{AFX_MSG_MAP(CIEFolderTreeCtrl)
- ON_WM_CREATE()
- ON_WM_DESTROY()
- ON_MESSAGE(WM_SETTINGCHANGE,OnSettingChange)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CIEFolderTreeCtrl message handlers
- int CIEFolderTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CUITreeCtrl::OnCreate(lpCreateStruct) == -1)
- return -1;
-
- // TODO: Add your specialized creation code here
-
- return 0;
- }
- BOOL CIEFolderTreeCtrl::PreCreateWindow(CREATESTRUCT& cs)
- {
- // TODO: Add your specialized code here and/or call the base class
- // No label editing for Explorer items
- cs.style |= (TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS);
- return CTreeCtrl::PreCreateWindow(cs);
- }
- void CIEFolderTreeCtrl::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
- {
- // TODO: Add your specialized code here and/or call the base class
-
- CUITreeCtrl::CalcWindowRect(lpClientRect, nAdjustType);
- }
- LPCITEMIDLIST CIEFolderTreeCtrl::GetPathPidl(HTREEITEM hItem)
- {
- if (hItem == NULL)
- return NULL;
- LPLVITEMDATA plvit = (LPLVITEMDATA)GetItemData(hItem);
- ASSERT(plvit);
- if (plvit == NULL)
- return NULL;
- return plvit->lpifq;
- }
- LPSHELLFOLDER CIEFolderTreeCtrl::GetItemFolder(HTREEITEM hItem)
- {
- LPTVITEMDATA lpidCurr = (LPTVITEMDATA)GetItemData(hItem);
- ASSERT(lpidCurr);
- if (lpidCurr == NULL)
- return NULL;
- LPSHELLFOLDER psfCurr=NULL;
- if (lpidCurr->lpsfParent)
- lpidCurr->lpsfParent->BindToObject(lpidCurr->lpi,0,IID_IShellFolder,(LPVOID*)&psfCurr);
- if (psfCurr == NULL)
- {
- SHGetDesktopFolder(&psfCurr);
- }
- return psfCurr;
- }
- CString CIEFolderTreeCtrl::GetPathName(HTREEITEM hItem)
- {
- if (hItem == NULL)
- hItem = GetSelectedItem();
- CString sPath;
- if (hItem == NULL)
- return sPath;
- LPTVITEMDATA lptvid = (LPTVITEMDATA)GetItemData(hItem);
- if (lptvid != NULL)
- {
- SHGetPathFromIDList(lptvid->lpifq,sPath.GetBuffer(MAX_PATH));
- sPath.ReleaseBuffer();
- }
- return sPath;
- }
- void CIEFolderTreeCtrl::SetButtonState(HTREEITEM hItem)
- {
- LPSHELLFOLDER psfCurr=GetItemFolder(hItem);
- if (psfCurr == NULL)
- return;
- IEnumIDList* pItems=NULL;
- HRESULT hr = psfCurr->EnumObjects(NULL, SHCONTF_FOLDERS, &pItems);
- int nChildren=0;
- if (SUCCEEDED(hr))
- {
- pItems->Release();
- nChildren=1;
- }
- if (nChildren == 1 && !ItemHasChildren(hItem))
- {
- TVITEM tv;
- tv.mask = TVIF_CHILDREN;
- ZeroMemory(&tv,sizeof(tv));
- SetItem(&tv);
- }
- psfCurr->Release();
- }
- void CIEFolderTreeCtrl::RefreshNode(HTREEITEM hItem)
- {
- // If the item is not expanded, update its button state and return.
- if (!(GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED))
- {
- SetButtonState(hItem);
- return;
- }
- LPSHELLFOLDER psfCurr=GetItemFolder(hItem);
- if (psfCurr == NULL)
- return;
- mapPidlToHTREEITEM mPidlCurr;
- vecPidl vPidlNew;
- HTREEITEM hSelItem = GetSelectedItem();
- HTREEITEM hChild = GetChildItem(hItem);
- while (hChild != NULL)
- {
- HTREEITEM hNextItem = GetNextSiblingItem(hChild);
- LPTVITEMDATA lpid = (LPTVITEMDATA)GetItemData(hChild);
- mPidlCurr[CShellPidlCompare(psfCurr,lpid->lpi)] = hChild;
- hChild = hNextItem;
- }
- LPITEMIDLIST pidlNext=NULL;
- LPITEMIDLIST pidlCopy=NULL;
- IEnumIDList* pItems=NULL;
- DWORD dwFlags = SHCONTF_FOLDERS;
- if (GetShellSettings().ShowAllObjects() && !GetShellSettings().ShowSysFiles())
- dwFlags |= SHCONTF_INCLUDEHIDDEN;
- HRESULT hr = psfCurr->EnumObjects(NULL, dwFlags, &pItems);
- while (NOERROR == hr)
- {
- hr = pItems->Next(1, &pidlNext, NULL);
- if (hr == S_FALSE || pidlNext == NULL)// || pidlNext == pidlCopy)
- break;
- pidlCopy = pidlNext;
- mapPidlToHTREEITEM::iterator it = mPidlCurr.find(CShellPidlCompare(psfCurr,pidlNext));
- if (it != mPidlCurr.end())
- {
- mPidlCurr.erase(it);
- }
- else
- {
- SetAttributes((*it).second,psfCurr,pidlNext);
- vPidlNew.push_back(GetShellPidl().CopyItemIDList(pidlNext));
- }
- GetShellPidl().FreePidl(pidlNext);
- pidlNext=NULL;
- }
- if (pItems)
- pItems->Release();
- for(mapPidlToHTREEITEM::iterator it1=mPidlCurr.begin();it1 != mPidlCurr.end();it1++)
- {
- HTREEITEM hDelItem = (*it1).second;
- #ifdef _DEBUG
- CString sPath;
- GetShellPidl().SHPidlToPathEx((*it1).first.GetPidl(),sPath,psfCurr);
- TRACE1("Deleting item %s in tree refreshn",sPath);
- #endif
- DeleteItem(hDelItem);
- }
- HTREEITEM hSortItem=NULL;
- for(vecPidl::iterator it2=vPidlNew.begin();it2 != vPidlNew.end();it2++)
- {
- AddFolder(hItem,*it2,psfCurr);
- hSortItem = hItem;
- }
- if (hSortItem)
- Sort(hSortItem,psfCurr);
- // Remove all items from the map
- mPidlCurr.erase(mPidlCurr.begin(),mPidlCurr.end());
- vPidlNew.erase(vPidlNew.begin(),vPidlNew.end());
- psfCurr->Release();
- // Now repeat this procedure for hItem's children.
- hChild = GetChildItem(hItem);
- while (hChild != NULL)
- {
- RefreshNode(hChild);
- hChild = GetNextSiblingItem (hChild);
- }
- }
- void CIEFolderTreeCtrl::Init()
- {
- CUITreeCtrl::Init();
- GetShellSettings().GetSettings();
- // TODO: Add your specialized code here and/or call the base class
- // Get the handle to the system image list, for our icons
- SHFILEINFO sfi;
- m_hImageList = (HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C:\"),
- 0,
- &sfi,
- sizeof(SHFILEINFO),
- SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
- // Attach ImageList to TreeCtrl
- if (m_hImageList)
- ::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM) TVSIL_NORMAL,(LPARAM)m_hImageList);
- }
- void CIEFolderTreeCtrl::OnDestroy()
- {
- SetImageList(NULL,TVSIL_NORMAL);
- CUITreeCtrl::OnDestroy();
- }
- LRESULT CIEFolderTreeCtrl::OnSettingChange(WPARAM wParam,LPARAM lParam)
- {
- LPCTSTR lpszSection=(LPCTSTR)lParam;
- if (lpszSection == NULL)
- return 0L;
- if (lstrcmpi(lpszSection, _T("ShellState")) == 0)
- {
- GetShellSettings().GetSettings();
- Refresh();
- }
- return 1L;
- }