1 //////////////////////////////////////////////////////////
\r
3 // Definitions for the CMyTreeView and TreeItemData classes
\r
6 #include "ExplorerApp.h"
\r
8 #include "MyTreeView.h"
\r
9 #include "MyListView.h"
\r
10 #include "resource.h"
\r
12 ////////////////////////////////
\r
13 //CMyTreeView function definitions
\r
14 CMyTreeView::CMyTreeView()
\r
19 CMyTreeView::~CMyTreeView()
\r
24 int CALLBACK CMyTreeView::CompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
\r
26 UNREFERENCED_PARAMETER(lParamSort);
\r
27 TreeItemData* pItem1 = (TreeItemData*)lParam1;
\r
28 TreeItemData* pItem2 = (TreeItemData*)lParam2;
\r
31 hr = pItem1->GetParentFolder().CompareIDs(0, pItem1->GetRelCpidl(), pItem2->GetRelCpidl());
\r
35 return (short)SCODE_CODE(GetScode(hr));
\r
38 void CMyTreeView::DeleteItems()
\r
43 void CMyTreeView::DoContextMenu(CPoint& ptScreen)
\r
45 TVHITTESTINFO tvhti;
\r
46 tvhti.pt = ptScreen;
\r
47 ScreenToClient(tvhti.pt);
\r
48 tvhti.flags = LVHT_NOWHERE;
\r
51 if(TVHT_ONITEM & tvhti.flags)
\r
52 DoItemMenu(tvhti.hItem , ptScreen);
\r
55 void CMyTreeView::DoItemMenu(HTREEITEM hItem, CPoint& ptScreen)
\r
57 TVITEM tvItem = {0};
\r
58 tvItem.mask = TVIF_PARAM;
\r
59 tvItem.hItem = hItem;
\r
64 TreeItemData* pInfo = (TreeItemData*)tvItem.lParam;
\r
68 if (pInfo->GetParentFolder().GetIShellFolder() != NULL)
\r
69 sf = pInfo->GetParentFolder();
\r
71 sf.SHGetDesktopFolder();
\r
73 if(sf.GetIShellFolder())
\r
75 hr = sf.GetUIObjectOf(m_hWnd, 1, &(pInfo->GetRelCpidl()), IID_IContextMenu, 0, cm);
\r
80 Popup.CreatePopupMenu();
\r
81 if(Popup.GetHandle())
\r
83 hr = cm.QueryContextMenu(Popup, 0, 1, 0x7fff, CMF_NORMAL | CMF_EXPLORE);
\r
87 cm.QueryInterface(IID_IContextMenu2, m_ccm2);
\r
89 UINT idCmd = Popup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON ,
\r
90 ptScreen.x, ptScreen.y, this, NULL);
\r
92 //A Treeview control sometimes requires this to end the
\r
93 // TrackPopupMenu properly
\r
94 GetParent()->PostMessage(WM_CANCELMODE, 0, 0);
\r
98 CMINVOKECOMMANDINFO cmi = {0};
\r
99 cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
\r
101 cmi.lpVerb = (LPCSTR)(INT_PTR)(idCmd - 1);
\r
102 cmi.nShow = SW_SHOWNORMAL;
\r
103 cm.InvokeCommand(cmi);
\r
114 LRESULT CMyTreeView::OnNotifyReflect(WPARAM, LPARAM lParam)
\r
116 LPNMHDR lpnmh = (LPNMHDR) lParam;
\r
118 switch(lpnmh->code)
\r
123 ::GetCursorPos(&ptScreen);
\r
124 DoContextMenu(ptScreen);
\r
127 case TVN_GETDISPINFO:
\r
129 LPNMTVDISPINFO lpdi = (LPNMTVDISPINFO)lParam;
\r
130 TreeItemData* pItem = (TreeItemData*)lpdi->item.lParam;
\r
132 //do we need to supply the text?
\r
133 if(lpdi->item.mask & TVIF_TEXT)
\r
135 SHFILEINFO sfi = {0};
\r
137 //get the display name of the item
\r
138 if(pItem->GetFullCpidl().SHGetFileInfo(0, sfi, SHGFI_PIDL | SHGFI_DISPLAYNAME))
\r
139 ::lstrcpyn(lpdi->item.pszText, sfi.szDisplayName, lpdi->item.cchTextMax -1);
\r
142 //do we need to supply the unselected image?
\r
143 if(lpdi->item.mask & TVIF_IMAGE)
\r
145 SHFILEINFO sfi = {0};
\r
147 //get the unselected image for this item
\r
148 if(pItem->GetFullCpidl().SHGetFileInfo(0, sfi, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_LINKOVERLAY))
\r
149 lpdi->item.iImage = sfi.iIcon;
\r
152 //do we need to supply the selected image?
\r
153 if(lpdi->item.mask & TVIF_SELECTEDIMAGE)
\r
155 SHFILEINFO sfi = {0};
\r
157 //get the selected image for this item
\r
158 if(pItem->GetFullCpidl().SHGetFileInfo(0, sfi, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON))
\r
159 lpdi->item.iSelectedImage = sfi.iIcon;
\r
164 case TVN_ITEMEXPANDING:
\r
166 LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
\r
168 switch(pnmtv->action)
\r
172 UINT ExpandedOnce = pnmtv->itemNew.state & TVIS_EXPANDEDONCE;
\r
174 GetChildItems(pnmtv->itemNew.hItem);
\r
181 case TVN_SELCHANGED:
\r
183 LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
\r
184 TreeItemData* pItem = (TreeItemData*)pnmtv->itemNew.lParam;
\r
186 CMyListView* LeftView = GetExplorerApp().GetMainFrame().GetListView();
\r
187 LeftView->DisplayFolder(pItem->GetParentFolder(), pItem->GetFullCpidl(), pItem->GetRelCpidl());
\r
190 } // switch(lpnmh->code)
\r
195 void CMyTreeView::EnumObjects(HTREEITEM hParentItem, CShellFolder& cParentFolder, Cpidl& cpidlParent)
\r
198 if(SUCCEEDED(cParentFolder.EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN, cEnum)))
\r
200 ULONG ulFetched = 1;
\r
203 //enumerate the item's PIDLs
\r
204 while(S_OK == (cEnum.Next(1, cpidlRel, ulFetched)) && ulFetched)
\r
206 TVITEM tvItem = {0};
\r
207 TVINSERTSTRUCT tvInsert = {0};
\r
210 //fill in the TV_ITEM structure for this item
\r
211 tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
\r
213 //Store a pointer to the TreeItemData in the lParam and m_pItems
\r
214 TreeItemData* pItem = new TreeItemData(cpidlParent, cpidlRel, cParentFolder);
\r
215 tvItem.lParam = (LPARAM)pItem;
\r
216 m_pItems.push_back(pItem);
\r
218 //text and images are done on a callback basis
\r
219 tvItem.pszText = LPSTR_TEXTCALLBACK;
\r
220 tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK;
\r
222 //determine if the item has children or shared
\r
223 ulAttribs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_SHARE;
\r
224 cParentFolder.GetAttributesOf(1, cpidlRel, ulAttribs);
\r
225 tvItem.cChildren = (ulAttribs & SFGAO_HASSUBFOLDER);
\r
227 //determine if the item is shared
\r
228 if(ulAttribs & SFGAO_SHARE)
\r
230 tvItem.mask |= TVIF_STATE;
\r
231 tvItem.stateMask |= TVIS_OVERLAYMASK;
\r
232 tvItem.state |= INDEXTOOVERLAYMASK(1); //1 is the index for the shared overlay image
\r
235 //fill in the TV_INSERTSTRUCT structure for this item
\r
236 tvInsert.item = tvItem;
\r
237 tvInsert.hInsertAfter = TVI_LAST;
\r
238 tvInsert.hParent = hParentItem;
\r
240 InsertItem(tvInsert);
\r
246 BOOL CMyTreeView::GetChildItems(HTREEITEM hParentItem)
\r
248 TVITEM tvItem = {0};
\r
249 tvItem.mask = TVIF_PARAM;
\r
250 tvItem.hItem = hParentItem;
\r
251 if (!GetItem(tvItem))
\r
254 //change the cursor
\r
255 HCURSOR hCursor = ::SetCursor(LoadCursor(NULL, IDC_WAIT));
\r
257 //turn redawing off in the TreeView. This will speed things up as we add items
\r
258 SendMessage(WM_SETREDRAW, FALSE, 0);
\r
260 TreeItemData* pItem = (TreeItemData*)tvItem.lParam;
\r
261 CShellFolder cParentFolder;
\r
264 //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
\r
265 if(!pItem->GetParentFolder().GetIShellFolder())
\r
266 hr = cParentFolder.SHGetDesktopFolder();
\r
268 //otherwise we need to get the IShellFolder for this item
\r
270 hr = pItem->GetParentFolder().BindToObject(pItem->GetRelCpidl(), NULL, IID_IShellFolder, cParentFolder);
\r
275 EnumObjects(hParentItem, cParentFolder, pItem->GetFullCpidl());
\r
277 //sort the new items
\r
279 tvSort.hParent = hParentItem;
\r
280 tvSort.lpfnCompare = CompareProc;
\r
282 SortChildrenCB(tvSort, 0);
\r
284 //turn redawing back on in the TreeView
\r
285 SendMessage(WM_SETREDRAW, TRUE, 0);
\r
288 ::SetCursor(hCursor);
\r
293 HIMAGELIST CMyTreeView::GetImageList(BOOL bLarge)
\r
296 return m_hLargeImageList;
\r
298 return m_hSmallImageList;
\r
301 BOOL CMyTreeView::GetRootItems()
\r
306 cpidlDesk.SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP);
\r
307 if (cpidlDesk.GetPidl())
\r
309 TV_ITEM tvItem = {0};
\r
310 TV_INSERTSTRUCT tvInsert = {0};
\r
311 HTREEITEM hParentItem;
\r
313 //fill in the TVITEM structure for this item
\r
314 tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
\r
316 //Store a pointer to the TreeItemData in the lParam and m_pItems
\r
317 TreeItemData* pItem = new TreeItemData(cpidlDesk);
\r
318 tvItem.lParam = (LPARAM)pItem;
\r
319 m_pItems.push_back(pItem);
\r
321 //text and images are done on a callback basis
\r
322 tvItem.pszText = LPSTR_TEXTCALLBACK;
\r
323 tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK;
\r
325 //assume the desktop has children
\r
326 tvItem.cChildren = TRUE;
\r
328 //fill in the TV_INSERTSTRUCT structure for this item
\r
329 tvInsert.item = tvItem;
\r
330 tvInsert.hInsertAfter = TVI_LAST;
\r
331 tvInsert.hParent = TVI_ROOT;
\r
336 hParentItem = InsertItem(tvInsert);
\r
338 //go ahead and expand this item
\r
339 Expand(hParentItem, TVE_EXPAND);
\r
341 //Select the next item
\r
342 HTREEITEM hNext = GetNextItem(hParentItem, TVGN_CHILD);
\r
345 Expand(hNext, TVE_EXPAND);
\r
350 //Scroll this item into view
\r
351 SelectSetFirstVisible(hNext);
\r
359 void CMyTreeView::OnInitialUpdate()
\r
361 //Set the image list
\r
362 SendMessage(TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM) GetImageList(FALSE));
\r
365 void CMyTreeView::PreCreate(CREATESTRUCT &cs)
\r
367 cs.dwExStyle = WS_EX_CLIENTEDGE;
\r
368 cs.style = WS_TABSTOP | WS_CHILD | WS_VISIBLE | TVS_HASLINES |
\r
369 TVS_HASBUTTONS | TVS_NOTOOLTIPS | TVS_SHOWSELALWAYS ;
\r
372 BOOL CMyTreeView::SelectFromListView(Cpidl& cpidlFull)
\r
374 HTREEITEM hItem = GetSelection();
\r
376 //Set parent item's has Children flag
\r
377 TVITEM tvItem = {0};
\r
378 tvItem.mask = TVIF_CHILDREN;
\r
379 tvItem.cChildren = 1;
\r
380 tvItem.hItem = hItem;
\r
383 //Expand the tree item
\r
384 Expand(hItem, TVE_EXPAND);
\r
387 HTREEITEM hChild = GetChild(hItem);
\r
389 while (hChild != NULL)
\r
391 //Get the TVITEM structure for this item
\r
392 TVITEM tvItem = {0};
\r
393 tvItem.mask = TVIF_PARAM;
\r
394 tvItem.hItem = hChild;
\r
395 if(!GetItem(tvItem))
\r
398 //Get the TreeItemData pointer from the item's lParam
\r
399 TreeItemData* pTD = (TreeItemData*)tvItem.lParam;
\r
401 //Compare the pidls
\r
402 if (pTD->GetFullCpidl() == cpidlFull)
\r
404 SelectItem(hChild);
\r
409 hChild = GetNextSibling(hChild);
\r
411 TRACE(_T("Item NOT found\n"));
\r
416 void CMyTreeView::SetImageLists()
\r
420 // Get the system image list
\r
421 m_hLargeImageList = (HIMAGELIST)::SHGetFileInfo(_T("C:\\"), 0, &sfi,
\r
422 sizeof(SHFILEINFO), SHGFI_SYSICONINDEX);
\r
424 m_hSmallImageList = (HIMAGELIST)::SHGetFileInfo(_T("C:\\"), 0, &sfi,
\r
425 sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
\r
428 LRESULT CMyTreeView::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
434 case WM_MEASUREITEM:
\r
435 case WM_INITMENUPOPUP:
\r
437 if(m_ccm2.GetIContextMenu2())
\r
438 m_ccm2.HandleMenuMsg(uMsg, wParam, lParam);
\r
447 return WndProcDefault(uMsg, wParam, lParam);
\r
450 ///////////////////////////////////
\r
451 //TreeItemData function definitions
\r
452 CMyTreeView::TreeItemData::TreeItemData(Cpidl& cpidl)
\r
454 m_cpidlRel = cpidl;
\r
455 m_cpidlFull = cpidl;
\r
458 CMyTreeView::TreeItemData::TreeItemData(Cpidl& cpidlParent, Cpidl& cpidlRel, CShellFolder& cParentFolder)
\r
460 m_cParentFolder = cParentFolder;
\r
461 m_cpidlFull = cpidlParent + cpidlRel;
\r
462 m_cpidlRel = cpidlRel;
\r
465 CMyTreeView::TreeItemData::~TreeItemData()
\r