📄 iefoldertreectrl.cpp
字号:
//*******************************************************************************
// 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 %s\n",sPath);
#endif
hr = psfDesktop->BindToObject(pidl, 0, IID_IShellFolder,(LPVOID*)&pSubFolder);
}
else
{
if (pszPath && *pszPath != '\0')
{
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -