📄 shelltree.cpp
字号:
* PURPOSE: Call this function if for example you want to put the path of the folder
* selected inside a combobox or an edit window. You would pass the
* parameters from OnSelChanged() to this function along with a CString object
* that will hold the folder path. If the path is not
* in the filesystem(eg MyComputer) it returns false.
*
* MESSAGEMAP: TVN_SELCHANGED
*
****************************************************************************/
BOOL CShellTree::OnFolderSelected(NMHDR* pNMHDR, LRESULT* pResult, CString &szFolderPath)
{
// TODO: Add your control notification handler code here
LPTVITEMDATA lptvid; //Long pointer to TreeView item data
LPSHELLFOLDER lpsf2=NULL;
static char szBuff[MAX_PATH];
HRESULT hr;
BOOL bRet=false;
TV_SORTCB tvscb;
HTREEITEM hItem=NULL;
if((hItem = GetSelectedItem()))
{
lptvid=(LPTVITEMDATA)GetItemData(hItem);
if (lptvid && lptvid->lpsfParent && lptvid->lpi)
{
hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,
0,IID_IShellFolder,(LPVOID *)&lpsf2);
if (SUCCEEDED(hr))
{
ULONG ulAttrs = SFGAO_FILESYSTEM;
// Determine what type of object we have.
lptvid->lpsfParent->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lptvid->lpi, &ulAttrs);
if (ulAttrs & (SFGAO_FILESYSTEM))
{
if(SHGetPathFromIDList(lptvid->lpifq,szBuff)){
szFolderPath = szBuff;
bRet = true;
}
}
//non standard from here(NEW CODE)
NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR;
if ((pnmtv->itemNew.cChildren == 1) && !(pnmtv->itemNew.state & TVIS_EXPANDEDONCE)){
FillTreeView(lpsf2,lptvid->lpifq,pnmtv->itemNew.hItem);
tvscb.hParent = pnmtv->itemNew.hItem;
tvscb.lParam = 0;
tvscb.lpfnCompare = TreeViewCompareProc;
SortChildrenCB(&tvscb);
pnmtv->itemNew.state |= TVIS_EXPANDEDONCE;
pnmtv->itemNew.stateMask |= TVIS_EXPANDEDONCE;
pnmtv->itemNew.mask |= TVIF_STATE;
SetItem(&pnmtv->itemNew);
}
}
}
if(lpsf2)
lpsf2->Release();
}
*pResult = 0;
return bRet;
}
/****************************************************************************
*
* FUNCTION: OnDeleteShellItem(NMHDR* pNMHDR, LRESULT* pResult)
*
* PURPOSE: Releases the memory allocated by the shell folders
*
* MESSAGEMAP: TVN_DELETEITEM
*
* MISC: failure to call this function will result in a memory leak
*
****************************************************************************/
void CShellTree::OnDeleteShellItem(NMHDR* pNMHDR, LRESULT* pResult)
{
LPTVITEMDATA lptvid=NULL;
HRESULT hr;
LPMALLOC lpMalloc;
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
//Let's free the memory for the TreeView item data...
hr=SHGetMalloc(&lpMalloc);
if (FAILED(hr))
return;
lptvid=(LPTVITEMDATA)pNMTreeView->itemOld.lParam;
lptvid->lpsfParent->Release();
lpMalloc->Free(lptvid->lpi);
lpMalloc->Free(lptvid->lpifq);
lpMalloc->Free(lptvid);
lpMalloc->Release();
}
/****************************************************************************
*
* FUNCTION: EnableImages()
*
* PURPOSE: Obtains a handle to the system image list and attaches it
* to the tree control. DO NOT DELETE the imagelist
*
* MESSAGEMAP: NONE
*
****************************************************************************/
void CShellTree::EnableImages()
{
// Get the handle to the system image list, for our icons
HIMAGELIST hImageList;
SHFILEINFO sfi;
hImageList = (HIMAGELIST)SHGetFileInfo((LPCSTR)_T("C:\\"),
0,
&sfi,
sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
// Attach ImageList to TreeView
if (hImageList)
::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM) TVSIL_NORMAL,
(LPARAM)hImageList);
}
/****************************************************************************
*
* FUNCTION: GetSelectedFolderPath(CString &szFolderPath)
*
* PURPOSE: Retrieves the path of the currently selected string.
* Pass a CString object that will hold the folder path.
* If the path is not in the filesystem(eg MyComputer)
* or none is selected it returns false.
*
* MESSAGEMAP: NONE
*
****************************************************************************/
BOOL CShellTree::GetSelectedFolderPath(CString &szFolderPath)
{
LPTVITEMDATA lptvid; //Long pointer to TreeView item data
LPSHELLFOLDER lpsf2=NULL;
static char szBuff[MAX_PATH];
HTREEITEM hItem=NULL;
HRESULT hr;
BOOL bRet=false;
if((hItem = GetSelectedItem()))
{
lptvid=(LPTVITEMDATA)GetItemData(hItem);
if (lptvid && lptvid->lpsfParent && lptvid->lpi)
{
hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,
0,IID_IShellFolder,(LPVOID *)&lpsf2);
if (SUCCEEDED(hr))
{
ULONG ulAttrs = SFGAO_FILESYSTEM;
// Determine what type of object we have.
lptvid->lpsfParent->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lptvid->lpi, &ulAttrs);
if (ulAttrs & (SFGAO_FILESYSTEM))
{
if(SHGetPathFromIDList(lptvid->lpifq,szBuff)){
szFolderPath = szBuff;
bRet = true;
}
}
}
}
if(lpsf2)
lpsf2->Release();
}
return bRet;
}
/****************************************************************************
*
* FUNCTION: GetParentShellFolder(HTREEITEM folderNode)
*
* PURPOSE: Retrieves the pointer to the ISHELLFOLDER interface
* of the tree node passed as the paramter.
*
* MESSAGEMAP: NONE
*
****************************************************************************/
LPSHELLFOLDER CShellTree::GetParentShellFolder(HTREEITEM folderNode)
{
LPTVITEMDATA lptvid; //Long pointer to TreeView item data
lptvid=(LPTVITEMDATA)GetItemData(folderNode);
if(lptvid)
return lptvid->lpsfParent;
else
return NULL;
}
/****************************************************************************
*
* FUNCTION: GetRelativeIDLIST(HTREEITEM folderNode)
*
* PURPOSE: Retrieves the Pointer to an ITEMIDLIST structure that
* identifies the subfolder relative to its parent folder.
* see GetParentShellFolder();
*
* MESSAGEMAP: NONE
*
****************************************************************************/
LPITEMIDLIST CShellTree::GetRelativeIDLIST(HTREEITEM folderNode)
{
LPTVITEMDATA lptvid; //Long pointer to TreeView item data
lptvid=(LPTVITEMDATA)GetItemData(folderNode);
if(lptvid)
return lptvid->lpifq;
else
return NULL;
}
/****************************************************************************
*
* FUNCTION: GetFullyQualifiedIDLIST(HTREEITEM folderNode)
*
* PURPOSE: Retrieves the Retrieves the Pointer to an ITEMIDLIST
* structure that identifies the subfolder relative to the
* desktop. This is a fully qualified Item Identifier
*
* MESSAGEMAP: NONE
*
****************************************************************************/
LPITEMIDLIST CShellTree::GetFullyQualifiedID(HTREEITEM folderNode)
{
LPTVITEMDATA lptvid; //Long pointer to TreeView item data
lptvid=(LPTVITEMDATA)GetItemData(folderNode);
if(lptvid)
return lptvid->lpifq;
else
return NULL;
}
/****************************************************************************
*
* FUNCTION: SearchTree( HTREEITEM treeNode,
* CString szSearchName )
*
* PURPOSE: Too crude to explain, just use it
*
* WARNING: Only works if you use the default PopulateTree()
* Not guaranteed to work on any future or existing
* version of windows. Use with caution. Pretty much
* ok if you're using on local drives
*
****************************************************************************/
bool CShellTree::SearchTree(HTREEITEM treeNode,
CString szSearchName,
FindAttribs attr)
{
LPTVITEMDATA lptvid; //Long pointer to TreeView item data
LPSHELLFOLDER lpsf2=NULL;
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
bool bRet=false;
HRESULT hr;
CString szCompare;
szSearchName.MakeUpper();
while(treeNode && bRet==false)
{
lptvid=(LPTVITEMDATA)GetItemData(treeNode);
if (lptvid && lptvid->lpsfParent && lptvid->lpi)
{
hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,
0,IID_IShellFolder,(LPVOID *)&lpsf2);
if (SUCCEEDED(hr))
{
ULONG ulAttrs = SFGAO_FILESYSTEM;
lptvid->lpsfParent->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lptvid->lpi, &ulAttrs);
if (ulAttrs & (SFGAO_FILESYSTEM))
{
if(SHGetPathFromIDList(lptvid->lpifq,szCompare.GetBuffer(MAX_PATH)))
{
switch(attr)
{
case type_drive:
_splitpath(szCompare,drive,dir,fname,ext);
szCompare=drive;
break;
case type_folder:
szCompare = GetItemText(treeNode);
break;
}
szCompare.MakeUpper();
if(szCompare == szSearchName)
{
EnsureVisible(treeNode);
SelectItem(treeNode);
bRet=true;
}
}
}
lpsf2->Release();
}
}
treeNode = GetNextSiblingItem(treeNode);
}
return bRet;
}
/****************************************************************************
*
* FUNCTION: TunnelTree(CString szFindPath)
*
* PURPOSE: Too crude to explain, just use it
*
* WARNING: Only works if you use the default PopulateTree()
* Not guaranteed to work on any future or existing
* version of windows. Use with caution. Pretty much
* ok if you're using on local drives
*
****************************************************************************/
void CShellTree::TunnelTree(CString szFindPath)
{
HTREEITEM subNode = GetRootItem();
CString szPathHop;
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
char delimiter[]=_T("\\");
CSHFileInfo checkPath(szFindPath);
if(!checkPath.Exist())
{
MessageBox(szFindPath,_T("Folder not found"),MB_ICONERROR);
return;
}
if(szFindPath.ReverseFind(_T('\\')) != szFindPath.GetLength()-1)
{
szFindPath += _T("\\");
}
_splitpath(szFindPath,drive,dir,fname,ext);
//search the drive first
szPathHop=drive;
subNode=GetChildItem(subNode);
if(subNode)
{
if(SearchTree(subNode,szPathHop, CShellTree::type_drive))
{
//break down subfolders and search
char *p=strtok(dir,delimiter);
while(p)
{
subNode = GetSelectedItem();
subNode = GetChildItem(subNode);
if(SearchTree(subNode,p,CShellTree::type_folder))
p=strtok(NULL,delimiter);
else
p=NULL;
}
}
}
}
/****************************************************************************
*
* FUNCTION: PopulateTree(LPCTSTR lpPath)
*
* PURPOSE: Populates tree based upon path.
*
* AUTHOR: Takehiko Mizoguti [mizoguti@m2.sys.to.casio.co.jp]
*
****************************************************************************/
void CShellTree::PopulateTree(LPCTSTR lpPath)
{
LPSHELLFOLDER lpsf=NULL,lpsf2=NULL;
LPITEMIDLIST lpi=NULL;
HRESULT hr;
TV_SORTCB tvscb;
LPTSTR lpFolder = (LPTSTR)lpPath;
LPTSTR lpNextFolder;
TCHAR strPath[_MAX_PATH];
LPMALLOC pMalloc;
if (::SHGetMalloc(&pMalloc) == NOERROR)
{
// Get a pointer to the desktop folder.
hr=SHGetDesktopFolder(&lpsf);
if (SUCCEEDED(hr))
{
USES_CONVERSION;
// Initialize the tree view to be empty.
DeleteAllItems();
do{
// Get the Next Component
lpNextFolder = PathFindNextComponent( lpFolder );
if( lpNextFolder && *lpNextFolder ){
memcpy( strPath, lpFolder, ( lpNextFolder - lpFolder ) );
strPath[lpNextFolder - lpFolder] = _T('\0');
}
else{
_tcscpy( strPath, lpFolder );
lpNextFolder = NULL;
}
// Get ShellFolder Pidl
ULONG eaten;
hr = lpsf->ParseDisplayName( NULL, NULL, T2OLE(strPath), &eaten, &lpi, NULL );
if( FAILED( hr ) ){
break;
}
hr=lpsf->BindToObject(lpi, 0, IID_IShellFolder,(LPVOID *)&lpsf2);
if( FAILED( hr ) ){
break;
}
pMalloc->Free( lpi );
// Release the Parent Folder pointer.
lpsf->Release();
// Chenge Folder Info
lpsf = lpsf2;
lpFolder = lpNextFolder;
}
while( lpNextFolder );
FillTreeView(lpsf,NULL,TVI_ROOT);
}
}
tvscb.hParent = TVI_ROOT;
tvscb.lParam = 0;
tvscb.lpfnCompare = TreeViewCompareProc;
// Sort the items in the tree view
SortChildrenCB(&tvscb/*, FALSE*/);
HTREEITEM hItem;
hItem = GetRootItem();
Expand(hItem,TVE_EXPAND);
Select(GetRootItem(),TVGN_CARET);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -