📄 loadtreectrl.cpp
字号:
// LoadTreeCtrl.cpp : implementation file//#include "stdafx.h"#include "LoadTreeCtrl.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// RxLoadTreeCtrlint CALLBACK Tree_CompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort){ UNREFERENCED_PARAMETER(lParamSort); LPITEMINFO pItem1 = (LPITEMINFO)lParam1; LPITEMINFO pItem2 = (LPITEMINFO)lParam2; HRESULT hr; hr = pItem1->pParentFolder->CompareIDs(0, pItem1->pidlRel, pItem2->pidlRel); if (FAILED(hr)) return 0; return (short)SCODE_CODE(GetScode(hr));}RxLoadTreeCtrl::RxLoadTreeCtrl(){ m_pidlIE = m_pidlRecycle = m_pidlCP = NULL;}RxLoadTreeCtrl::~RxLoadTreeCtrl(){ LPMALLOC pMalloc; if (SUCCEEDED(SHGetMalloc(&pMalloc))) { if (m_pidlIE) Pidl_Free(m_pidlIE); if (m_pidlRecycle) Pidl_Free(m_pidlRecycle); if (m_pidlCP) Pidl_Free(m_pidlCP); pMalloc->Release(); } m_ilFolderTree.Detach();}BEGIN_MESSAGE_MAP(RxLoadTreeCtrl, CTreeCtrl) //{{AFX_MSG_MAP(RxLoadTreeCtrl) ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteItem) ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemExpanding) //}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// RxLoadTreeCtrl message handlersvoid RxLoadTreeCtrl::Initialize(){ HIMAGELIST hImageList; SHFILEINFO sfi; hImageList = (HIMAGELIST)SHGetFileInfo( TEXT("C:\\"), 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON); m_ilFolderTree.Attach(hImageList); SetImageList(&m_ilFolderTree, TVSIL_NORMAL); // Get ItemIDList for Recycle Bin & Internet Explorer & Control Panel SHGetSpecialFolderLocation(GetSafeHwnd(), CSIDL_INTERNET, &m_pidlIE); SHGetSpecialFolderLocation(GetSafeHwnd(), CSIDL_BITBUCKET, &m_pidlRecycle); SHGetSpecialFolderLocation(GetSafeHwnd(), CSIDL_CONTROLS, &m_pidlCP); DeleteAllItems(); GetRootItems();}BOOL RxLoadTreeCtrl::GetRootItems(){ //LOG_MESSAGE("GetRootItems function is called."); LPITEMIDLIST pidl; if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl))) { TV_ITEM tvItem; TV_INSERTSTRUCT tvInsert; LPSHELLFOLDER pDesktop; LPITEMINFO pItem; HTREEITEM hParentItem; SHFILEINFO sfi; LPTSTR pszBuffer; if (FAILED(SHGetDesktopFolder(&pDesktop))) return FALSE; tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; //put the private information in the lParam pItem = (LPITEMINFO) new BYTE[sizeof(ITEMINFO)]; pItem->pidlRel = pidl; pItem->pidlFQ = Pidl_Copy(pidl); pItem->pParentFolder = NULL; tvItem.lParam = (LPARAM)pItem; if (SHGetFileInfo((LPCTSTR)pItem->pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_DISPLAYNAME)) { pszBuffer = new TCHAR[lstrlen(sfi.szDisplayName) + 1]; lstrcpy(pszBuffer, sfi.szDisplayName); pItem->pszText = tvItem.pszText = pszBuffer; tvItem.cchTextMax = lstrlen(sfi.szDisplayName) + 1; //tvItem.pszText = sfi.szDisplayName; } else pItem->pszText = tvItem.pszText = NULL; if (SHGetFileInfo((LPCTSTR)pItem->pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_LINKOVERLAY)) { tvItem.iImage = sfi.iIcon; } if (SHGetFileInfo((LPCTSTR)pItem->pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON)) { tvItem.iSelectedImage = sfi.iIcon; } //text and images are done on a callback basis //tvItem.pszText = LPSTR_TEXTCALLBACK; //tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK; //assume the desktop has children tvItem.cChildren = TRUE; //fill in the TV_INSERTSTRUCT structure for this item tvInsert.item = tvItem; tvInsert.hInsertAfter = TVI_LAST; tvInsert.hParent = TVI_ROOT; hParentItem = InsertItem(&tvInsert); //LOG_MESSAGE("Expand root item."); Expand(hParentItem, TVE_EXPAND); pDesktop->Release(); return TRUE; } return FALSE;}void RxLoadTreeCtrl::OnDeleteItem(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; LPITEMINFO pItem = (LPITEMINFO)pNMTreeView->itemOld.lParam; LPMALLOC pMalloc; // display name阑 瘤款促 if (pItem->pszText) delete[] pItem->pszText; if (SUCCEEDED(SHGetMalloc(&pMalloc))) { //free up the pidls that we allocated Pidl_Free(pItem->pidlFQ); Pidl_Free(pItem->pidlRel); pMalloc->Release(); } if(pItem->pParentFolder) pItem->pParentFolder->Release(); delete[] pItem; *pResult = 0;}void RxLoadTreeCtrl::OnItemExpanding(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; switch (pNMTreeView->action) { case TVE_EXPAND: GetChildItems(pNMTreeView->itemNew.hItem); break; case TVE_COLLAPSE: Expand(pNMTreeView->itemNew.hItem, TVE_COLLAPSE | TVE_COLLAPSERESET); break; } *pResult = 0;}BOOL RxLoadTreeCtrl::GetChildItems(HTREEITEM hParentItem){ //LOG_MESSAGE("GetChildItems function is called."); TVITEM tvItem; LPITEMINFO pItem; LPSHELLFOLDER pParentFolder = NULL; HRESULT hr; HCURSOR hCursor; TV_SORTCB tvSort; //get the parent item's pidl ZeroMemory(&tvItem, sizeof(tvItem)); tvItem.mask = TVIF_PARAM; tvItem.hItem = hParentItem; if(!GetItem(&tvItem)) return FALSE; //change the cursor 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); pItem = (LPITEMINFO)tvItem.lParam; //LOG_MESSAGE("Binding pidl to folder in GetChildItems function."); //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->pParentFolder) hr = SHGetDesktopFolder(&pParentFolder); //otherwise we need to get the IShellFolder for this item else hr = pItem->pParentFolder->BindToObject(pItem->pidlRel, NULL, IID_IShellFolder, (LPVOID*)&pParentFolder); if (FAILED(hr)) return FALSE; if (!EnumFolders(hParentItem, pParentFolder, pItem->pidlFQ)) { // if there is no child tvItem.mask = TVIF_HANDLE | TVIF_CHILDREN; tvItem.hItem = hParentItem; tvItem.cChildren = 0; SetItem(&tvItem); } //LOG_MESSAGE("End EnumFolders in GetChildItems func."); //sort the new items tvSort.hParent = hParentItem; tvSort.lpfnCompare = Tree_CompareProc; tvSort.lParam = 0; SortChildrenCB(&tvSort); //turn redawing back on in the TreeView //SendMessage(WM_SETREDRAW, TRUE, 0); //UpdateWindow(hwndTreeView); pParentFolder->Release(); SetCursor(hCursor); return TRUE;}BOOL RxLoadTreeCtrl::EnumFolders(HTREEITEM hParentItem, LPSHELLFOLDER pParentFolder, LPITEMIDLIST pidlParent){ //LOG_MESSAGE("EnumFolders function starts."); BOOL bHasChildren = FALSE; LPENUMIDLIST pEnum;#ifdef _LOG_ON_ TVITEM tvItemTest; ZeroMemory(&tvItemTest, sizeof(tvItemTest)); tvItemTest.mask = TVIF_TEXT; tvItemTest.hItem = hParentItem; if(!GetItem(&tvItemTest)) return FALSE; CString strFolder; strFolder.Format("Parent Folder is [%s]", tvItemTest.pszText); //LOG_MESSAGE(strFolder);#endif if (SUCCEEDED(pParentFolder->EnumObjects(NULL, SHCONTF_FOLDERS, &pEnum))) { LPITEMIDLIST pidlTemp; DWORD dwFetched = 1; LPITEMINFO pItem; //enumerate the item's PIDLs while(SUCCEEDED(pEnum->Next(1, &pidlTemp, &dwFetched)) && dwFetched) { TVITEM tvItem; TVINSERTSTRUCT tvInsert; //DWORD dwAttribs; SHFILEINFO sfi; LPTSTR pszBuffer; LPITEMIDLIST pidlTest; //LOG_MESSAGE("Enumeration loop....."); // continue if folder is IE or Recycle Bin pidlTest = Pidl_Concatenate(pidlParent, pidlTemp); if (!Pidl_Compare(pidlTest, m_pidlIE, 1) || !Pidl_Compare(pidlTest, m_pidlRecycle, 1) || !Pidl_Compare(pidlTest, m_pidlCP, 1)) { Pidl_Free(pidlTest); continue; } Pidl_Free(pidlTest); //LOG_MESSAGE("After IE, Recycle Bin, Control panel test."); ZeroMemory(&tvItem, sizeof(tvItem)); //fill in the TV_ITEM structure for this item tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; //AddRef the parent folder so it's pointer stays valid pParentFolder->AddRef(); //put the private information in the lParam pItem = (LPITEMINFO) new BYTE[sizeof(ITEMINFO)]; pItem->pidlRel = pidlTemp; pItem->pidlFQ = Pidl_Concatenate(pidlParent, pidlTemp); pItem->pParentFolder = pParentFolder; tvItem.lParam = (LPARAM)pItem; //LOG_MESSAGE("Getting folder name.."); if (SHGetFileInfo((LPCTSTR)pItem->pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_DISPLAYNAME)) { pszBuffer = new TCHAR[lstrlen(sfi.szDisplayName) + 1]; lstrcpy(pszBuffer, sfi.szDisplayName); pItem->pszText = tvItem.pszText = pszBuffer; tvItem.cchTextMax = lstrlen(sfi.szDisplayName) + 1; //tvItem.pszText = sfi.szDisplayName; } else pItem->pszText = tvItem.pszText = NULL; if (SHGetFileInfo((LPCTSTR)pItem->pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_LINKOVERLAY)) { tvItem.iImage = sfi.iIcon; } if (SHGetFileInfo((LPCTSTR)pItem->pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON)) { tvItem.iSelectedImage = sfi.iIcon; } //text and images are done on a callback basis //tvItem.pszText = LPSTR_TEXTCALLBACK; //tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK; //determine if the item has children //dwAttribs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_DISPLAYATTRMASK | SFGAO_CANRENAME; //pParentFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidlTemp, &dwAttribs); //tvItem.cChildren = (dwAttribs & SFGAO_HASSUBFOLDER); //determine if the item is shared /* if(dwAttribs & SFGAO_SHARE) { tvItem.mask |= TVIF_STATE; tvItem.stateMask |= TVIS_OVERLAYMASK; tvItem.state |= INDEXTOOVERLAYMASK(1); //1 is the index for the shared overlay image } */ tvItem.cChildren = TRUE; //fill in the TV_INSERTSTRUCT structure for this item tvInsert.item = tvItem; tvInsert.hInsertAfter = TVI_LAST; tvInsert.hParent = hParentItem; //LOG_MESSAGE("Insert tree item..."); InsertItem(&tvInsert); dwFetched = 0; bHasChildren = TRUE; } pEnum->Release(); } //LOG_MESSAGE("EnumFolders function ends."); return bHasChildren;}void RxLoadTreeCtrl::DisplayFolder(LPITEMINFO pItemInfo){ // IShellFolder客 PIDL 阑 掘绰促 IShellFolder *psfCurFolder = NULL; LPITEMIDLIST pidlCurFQ = NULL; if (pItemInfo && pItemInfo->pParentFolder) { pItemInfo->pParentFolder->BindToObject(pItemInfo->pidlRel, NULL, IID_IShellFolder, (LPVOID*)&psfCurFolder); pidlCurFQ = Pidl_Copy(pItemInfo->pidlFQ); } else { SHGetDesktopFolder(&psfCurFolder); if (pItemInfo) pidlCurFQ = Pidl_Copy(pItemInfo->pidlFQ); } if (psfCurFolder) EnumFiles(psfCurFolder, pidlCurFQ); // IShellFolder客 PIDL 阑 馆券茄促. if (psfCurFolder) { psfCurFolder->Release(); psfCurFolder = NULL; Pidl_Free(pidlCurFQ); pidlCurFQ = NULL; }}void RxLoadTreeCtrl::EnumFiles(LPSHELLFOLDER pParentFolder, LPITEMIDLIST pidlParent){ LPENUMIDLIST pEnum; BOOL bRecursive = FALSE; CStdioFile fileText; fileText.Open(_T("Uhaha.txt"), CFile::modeCreate | CFile::modeWrite); if (SUCCEEDED(pParentFolder->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnum))) { LPITEMIDLIST pidlTemp; DWORD dwFetched = 1; //enumerate the item's PIDLs while (SUCCEEDED(pEnum->Next(1, &pidlTemp, &dwFetched)) && dwFetched) { DWORD dwAttr; LPITEMIDLIST pidlFQ; TCHAR szPath[MAX_PATH]; CString strText; //if (SHGetFileInfo((LPCTSTR)pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_DISPLAYNAME)) { // TRACE("%s\n", sfi.szDisplayName); //} //determine if the item is shared dwAttr = SFGAO_FILESYSTEM | SFGAO_FOLDER; pParentFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidlTemp, &dwAttr); if (dwAttr & SFGAO_FILESYSTEM) { if (dwAttr & SFGAO_FOLDER) { /* pParentFolder->AddRef(); pItem = (LPITEMINFO)new BYTE[sizeof(ITEMINFO)]; pItem->pidlRel = pidlTemp; pItem->pidlFQ = Pidl_Concatenate(pidlParent, pidlTemp); pItem->pParentFolder = pParentFolder; DisplayFolder(pItem); Pidl_Free(pItem->pidlFQ); Pidl_Free(pItem->pidlRel); //this may be NULL if this is the root item if(pItem->pParentFolder) pItem->pParentFolder->Release(); delete[] pItem; */ } else { pidlFQ = Pidl_Concatenate(pidlParent, pidlTemp); if (SHGetPathFromIDList(pidlFQ, szPath)) { strText.Format(_T("%s\n"), szPath); fileText.WriteString(strText); TRACE(_T("%s\n"), szPath); } //if (SHGetFileInfo((LPCTSTR)pidlFQ, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_DISPLAYNAME)) // TRACE("%s\n", sfi.szDisplayName); Pidl_Free(pidlFQ); } } dwFetched = 0; } pEnum->Release(); } fileText.Close();}LPITEMIDLIST RxLoadTreeCtrl::GetCurPidl(){ HTREEITEM hSelItem = GetSelectedItem(); TVITEM tvItem; LPITEMINFO pItem; if (!hSelItem) return NULL; tvItem.mask = TVIF_PARAM; tvItem.hItem = hSelItem; GetItem(&tvItem); pItem = (LPITEMINFO)tvItem.lParam; return pItem->pidlFQ;}BOOL RxLoadTreeCtrl::SetCurPidl(LPITEMIDLIST pidl){ //LOG_MESSAGE("Setting current PIDL."); HTREEITEM hItem; TVITEM tvItem; LPITEMINFO pItem; LPITEMIDLIST pidlOriginal = pidl; hItem = GetRootItem(); if (!hItem) return FALSE; Expand(hItem, TVE_EXPAND); //LOG_MESSAGE("Before match pidl loop."); while (pidl) { hItem = GetChildItem(hItem); while (hItem) { //LOG_MESSAGE("Getting child items in tree."); ZeroMemory(&tvItem, sizeof(tvItem)); tvItem.hItem = hItem; if (GetItem(&tvItem)) { pItem = (LPITEMINFO)tvItem.lParam; if (!Pidl_Compare(pidl, pItem->pidlRel, 0)) { break; } } hItem = GetNextItem(hItem, TVGN_NEXT); } //LOG_MESSAGE("Compare full pidl in loop."); if (!Pidl_Compare(pidlOriginal, pItem->pidlFQ, 1)) break; if (!hItem) return FALSE; Expand(hItem, TVE_EXPAND); pidl = Pidl_GetNextItem(pidl); } //LOG_MESSAGE("After match pidl loop."); SelectItem(hItem); //LOG_MESSAGE("End SetCurPidl func."); return TRUE;}LPITEMINFO RxLoadTreeCtrl::GetCurItem(){ HTREEITEM hSelItem = GetSelectedItem(); TVITEM tvItem; LPITEMINFO pItem; if (!hSelItem) return NULL; tvItem.mask = TVIF_PARAM; tvItem.hItem = hSelItem; GetItem(&tvItem); pItem = (LPITEMINFO)tvItem.lParam; return pItem;}CString WindowName( CString sName ){ CString sRet; //Scan all charactors to determine if their are any lower case items for( int n = 0; n < sName.GetLength(); n++ ) { TCHAR ch = sName[n]; if ((ch >= 'a') && (ch <= 'z') ) return sName; } sName.MakeLower(); if( sName.GetLength() > 0 ) { CString sFirstChar = sName[0]; sFirstChar.MakeUpper(); sName = sFirstChar + sName.Mid( 1 ); } return sName;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -