// Recursively sorts a node and its children using an application // specific sorting function void CMyTreeCtrl::SortNodeAndChildren(HTREEITEM hItem, PFNTVCOMPARE lpfnCompare) { // Create the sorting structure TVSORTCB sort; sort.hParent=hItem; sort.lParam=0; sort.lpfnCompare=lpfnCompare; // Sort the node SortChildrenCB(&sort); // Determine if this item has children if (ItemHasChildren(hItem)) { // Get the first child item HTREEITEM hChild=GetChildItem(hItem); // Sort the child SortNodeAndChildren(hChild, lpfnCompare); // Sort the rest of the children HTREEITEM hSibling=GetNextSiblingItem(hChild); while (hSibling) { SortNodeAndChildren(hSibling, lpfnCompare); hSibling=GetNextSiblingItem(hSibling); } } }
void CCJShellTree::OnFill(bool bRefresh/*=false*/) { LPSHELLFOLDER lpsf=NULL; HRESULT hr; TV_SORTCB tvscb; m_bRefresh = bRefresh; // Get a pointer to the desktop folder. hr=SHGetDesktopFolder(&lpsf); if (SUCCEEDED(hr)) { // Initialize the tree view to be empty. DeleteAllItems(); // Fill in the tree view from the root. FillTreeView(lpsf, NULL, TVI_ROOT); // Release the folder pointer. lpsf->Release(); } tvscb.hParent = TVI_ROOT; tvscb.lParam = 0; tvscb.lpfnCompare = TreeViewCompareProc; // Sort the items in the tree view SortChildrenCB(&tvscb/*, FALSE*/); Expand(GetRootItem(), TVE_EXPAND); }
// Recursively sort the entire tree void CMultiSelTreeCtrl::SortTree(HTREEITEM topNode/*=NULL*/, HTREEITEM parentNode/*=NULL*/) { HTREEITEM item; // Sort things at the this level if (parentNode && (m_SortByExtension || m_SortByResolveStat || m_SortByAction || m_SortByFilename)) { TVSORTCB tvsortcb; tvsortcb.hParent = topNode; tvsortcb.lParam = (m_SortByResolveStat ? 2 : 0) + (m_SortByExtension ? 1 : 0) + (m_SortByFilename ? 8 : 0) + (m_SortByAction ? 4 : 0); tvsortcb.lpfnCompare = SortTreeCB; SortChildrenCB(&tvsortcb); } else SortChildren(topNode); // Get the first item at this level if(topNode == NULL) item=GetNextItem(TVI_ROOT, TVGN_ROOT); else item=GetChildItem(topNode); // Get first child // Recurse all items that have children while(item != NULL) { if(ItemHasChildren(item)) SortTree(item, topNode); item=GetNextSiblingItem(item); } }
/**************************************************************************** * * FUNCTION: PopulateTree() * * PURPOSE: Processes the File.Fill/RefreshTree command * ****************************************************************************/ void CShellTreeCtrl::PopulateTree() { LPSHELLFOLDER lpsf=NULL; LPITEMIDLIST lpi=NULL; HRESULT hr; TV_SORTCB tvscb; // Get a pointer to the desktop folder. hr=SHGetDesktopFolder(&lpsf); if (SUCCEEDED(hr)) { // Initialize the tree view to be empty. DeleteAllItems(); // Fill in the tree view from the root. FillTreeView(lpsf, NULL, TVI_ROOT); //TunnelFillTree(lpsf, NULL, TVI_ROOT); // Release the folder pointer. lpsf->Release(); } 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); }
/**************************************************************************** * * FUNCTION: OnFolderSelected(NMHDR* pNMHDR, LRESULT* pResult, CString &szFolderPath) * * 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 CShellTreeCtrl::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; }
void CTreeCtrlEx::Sort(HTREEITEM parent) { TVSORTCB tvs; tvs.hParent=parent; tvs.lpfnCompare=MyCompareProc; tvs.lParam=(LPARAM)this; SortChildrenCB(&tvs); }
BOOL CTreeListCtrl::SortItems( int nCol, BOOL bAscending, HTREEITEM low) { TV_SORTCB tSort; tSort.hParent = low; tSort.lpfnCompare = CompareFunc; SSortType *pSortType = new SSortType; pSortType->nCol = nCol; pSortType->bAscending = bAscending; tSort.lParam = (LPARAM)pSortType; BOOL m_bReturn = SortChildrenCB(&tSort); delete pSortType; return m_bReturn; }
BOOL CMyTreeView::GetChildItems(HTREEITEM hParentItem) { TVITEM tvItem = {0}; tvItem.mask = TVIF_PARAM; tvItem.hItem = hParentItem; if (!GetItem(tvItem)) return FALSE; //change the cursor HCURSOR hCursor = ::SetCursor(LoadCursor(NULL, IDC_WAIT)); //turn redawing off in the TreeView. This will speed things up as we add items SendMessage(WM_SETREDRAW, FALSE, 0); TreeItemData* pItem = (TreeItemData*)tvItem.lParam; CShellFolder cParentFolder; HRESULT hr; //if the parent folder is NULL, then we are at the root of the namespace, so the parent of this item is the desktop folder if (!pItem->GetParentFolder().GetIShellFolder()) hr = cParentFolder.SHGetDesktopFolder(); //otherwise we need to get the IShellFolder for this item else hr = pItem->GetParentFolder().BindToObject(pItem->GetRelCpidl(), NULL, IID_IShellFolder, cParentFolder); if (FAILED(hr)) return FALSE; EnumObjects(hParentItem, cParentFolder, pItem->GetFullCpidl()); //sort the new items TV_SORTCB tvSort; tvSort.hParent = hParentItem; tvSort.lpfnCompare = CompareProc; tvSort.lParam = 0; SortChildrenCB(tvSort, 0); //turn redawing back on in the TreeView SendMessage(WM_SETREDRAW, TRUE, 0); UpdateWindow(); ::SetCursor(hCursor); return TRUE; }
/**************************************************************************** * * FUNCTION: OnFolderExpanding(NMHDR* pNMHDR, LRESULT* pResult) * * PURPOSE: Reponds to an TVN_ITEMEXPANDING message in order to fill up * subdirectories. Pass the parameters from OnItemExpanding() to * this function. You need to do that or your folders won't * expand. * * OTHER: It can also be used to update a corresponding listview. Seem MFCENUM * * MESSAGEMAP: TVN_ITEMEXPANDING * ****************************************************************************/ void CShellTreeCtrl::OnFolderExpanding(NMHDR* pNMHDR, LRESULT* pResult) { LPTVITEMDATA lptvid; //Long pointer to TreeView item data HRESULT hr; LPSHELLFOLDER lpsf2=NULL; static char szBuff[MAX_PATH]; TV_SORTCB tvscb; NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE)) { return; } lptvid=(LPTVITEMDATA)pnmtv->itemNew.lParam; if (lptvid) { hr=lptvid->lpsfParent->BindToObject(lptvid->lpi, 0, IID_IShellFolder,(LPVOID *)&lpsf2); if (SUCCEEDED(hr)) { FillTreeView(lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem); } tvscb.hParent = pnmtv->itemNew.hItem; tvscb.lParam = 0; tvscb.lpfnCompare = TreeViewCompareProc; SortChildrenCB(&tvscb /*, FALSE*/); } *pResult = 0; }
/* #FN# Reponds to TVN_ITEMEXPANDING message in order to fill up subdirectories. Pass the parameters from OnItemExpanding() to this function. You need to do that or your folders won't expand */ void /* #AS# Nothing */ CShellTree:: OnFolderExpanding( NMHDR *pNMHDR, /* #IN# */ LRESULT *pResult /* #OUT# */ ) { LPTVITEMDATA lptvid; /* Long pointer to TreeView item data */ LPSHELLFOLDER lpsf2 = NULL; TV_SORTCB tvscb; static char szBuff[ MAX_PATH + 1 ]; HRESULT hr; NM_TREEVIEW *pnmtv = (NM_TREEVIEW *)pNMHDR; if( pnmtv->itemNew.state & TVIS_EXPANDEDONCE ) return; lptvid = (LPTVITEMDATA)pnmtv->itemNew.lParam; if( lptvid ) { hr = lptvid->lpsfParent->BindToObject( lptvid->lpi, 0, IID_IShellFolder, (LPVOID *)&lpsf2 ); if( SUCCEEDED(hr) ) FillTreeView( lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem ); tvscb.hParent = pnmtv->itemNew.hItem; tvscb.lParam = 0; tvscb.lpfnCompare = TreeViewCompareProc; SortChildrenCB( &tvscb /*, FALSE*/ ); } *pResult = 0; } /* #OF# CShellTree::OnFolderExpanding */
/* #FN# Populates the tree view control with file list */ void /* #AS# Nothing */ CShellTree:: PopulateTree() { LPSHELLFOLDER lpsf = NULL; LPITEMIDLIST lpi = NULL; HRESULT hr; /* Get a pointer to the desktop folder */ hr = SHGetDesktopFolder( &lpsf ); if( SUCCEEDED(hr) ) { /* Initialize the tree view to be empty */ DeleteAllItems(); /* Fill in the tree view from the root */ FillTreeView( lpsf, NULL, TVI_ROOT ); /* Release the folder pointer */ lpsf->Release(); } TV_SORTCB tvscb; tvscb.hParent = TVI_ROOT; tvscb.lParam = 0; tvscb.lpfnCompare = TreeViewCompareProc; /* Sort the items in the tree view */ SortChildrenCB( &tvscb /*, FALSE*/ ); HTREEITEM hItem = GetRootItem(); Expand( hItem, TVE_EXPAND ); Select( GetRootItem(), TVGN_CARET ); } /* #OF# CShellTree::PopulateTree */
void CCJShellTree::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; *pResult = 0; LPTVITEMDATA lptvid; //Long pointer to TreeView item data HRESULT hr; LPSHELLFOLDER lpsf2=NULL; static char szBuff[MAX_PATH]; TV_SORTCB tvscb; if ((pNMTreeView->itemNew.state & TVIS_EXPANDEDONCE)) return; SetRedraw(FALSE); lptvid=(LPTVITEMDATA)pNMTreeView->itemNew.lParam; if (lptvid) { hr=lptvid->lpsfParent->BindToObject(lptvid->lpi, 0, IID_IShellFolder,(LPVOID *)&lpsf2); if (SUCCEEDED(hr)) { FillTreeView(lpsf2, lptvid->lpifq, pNMTreeView->itemNew.hItem); } tvscb.hParent = pNMTreeView->itemNew.hItem; tvscb.lParam = 0; tvscb.lpfnCompare = TreeViewCompareProc; SortChildrenCB(&tvscb/*, FALSE*/); } SetRedraw(); }
void FolderTree::DisplayPath(const tstring &sPath, HTREEITEM hParent, bool bUseSetRedraw /* = true */) { //CWaitCursor c; //Speed up the job by turning off redraw if (bUseSetRedraw) SetRedraw(false); //Remove all the items currently under hParent HTREEITEM hChild = GetChildItem(hParent); while (hChild) { DeleteItem(hChild); hChild = GetChildItem(hParent); } //Should we display the root folder if (m_bShowRootedFolder && (hParent == TVI_ROOT)) { FolderTreeItemInfo* pItem = new FolderTreeItemInfo; pItem->m_sFQPath = m_sRootFolder; pItem->m_sRelativePath = m_sRootFolder; m_hRootedFolder = InsertFileItem(TVI_ROOT, pItem, false, GetIconIndex(m_sRootFolder), GetSelIconIndex(m_sRootFolder), true); Expand(m_hRootedFolder, TVE_EXPAND); return; } //find all the directories underneath sPath int nDirectories = 0; tstring sFile; if (sPath[sPath.size()-1] != _T('\\')) sFile = sPath + _T("\\"); else sFile = sPath; WIN32_FIND_DATA fData; HANDLE hFind; hFind = FindFirstFile((sFile + _T("*")).c_str(), &fData); if(hFind != INVALID_HANDLE_VALUE) { do { tstring filename = fData.cFileName; if((fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (filename != _T(".")) && (filename != _T(".."))) { ++nDirectories; tstring path = sFile + filename; TCHAR szPath[_MAX_PATH]; TCHAR szFname[_MAX_FNAME]; TCHAR szExt[_MAX_EXT]; _tsplitpath(path.c_str(), NULL, NULL, szFname, szExt); _tmakepath(szPath, NULL, NULL, szFname, szExt); FolderTreeItemInfo* pItem = new FolderTreeItemInfo; pItem->m_sFQPath = path; pItem->m_sRelativePath = szPath; InsertFileItem(hParent, pItem, m_bShowSharedUsingDifferentIcon && IsShared(path), GetIconIndex(path), GetSelIconIndex(path), true); } } while (FindNextFile(hFind, &fData)); } FindClose(hFind); //Now sort the items we just added TVSORTCB tvsortcb; tvsortcb.hParent = hParent; tvsortcb.lpfnCompare = CompareByFilenameNoCase; tvsortcb.lParam = 0; SortChildrenCB(&tvsortcb); //We want to add them before sorting checkRemovedDirs(sFile, hParent); //If no items were added then remove the "+" indicator from hParent if(nDirectories == 0) SetHasPlusButton(hParent, FALSE); //Turn back on the redraw flag if(bUseSetRedraw) SetRedraw(true); }
void CCJShellTree::PopulateTree(LPCTSTR lpszPath) { LPSHELLFOLDER lpsf=NULL,lpsf2=NULL; LPITEMIDLIST lpi=NULL; HRESULT hr; TV_SORTCB tvscb; LPTSTR lpFolder = (LPTSTR)lpszPath; 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); }