Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2183 lines
64 KiB

  1. // TreeCtrl.cpp : implementation file
  2. //
  3. //+-------------------------------------------------------------------------
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1999
  7. //
  8. // File: amctreectrl.cpp
  9. //
  10. // Contents: AMC Tree control implementation
  11. //
  12. // History: 16-Jul-96 WayneSc Created
  13. //
  14. //
  15. //--------------------------------------------------------------------------
  16. #include "stdafx.h"
  17. #include "AMCDoc.h" // AMC Console Document
  18. #include "amcview.h"
  19. #include "childfrm.h"
  20. #include "macros.h"
  21. #include "AMCPriv.h"
  22. #include "AMC.h"
  23. #include "mainfrm.h"
  24. #include "TreeCtrl.h"
  25. #include "resource.h"
  26. #include "guidhelp.h" // LoadRootDisplayName
  27. #include "histlist.h"
  28. #include "websnk.h"
  29. #include "webctrl.h"
  30. #include "..\inc\mmcutil.h"
  31. #include "amcmsgid.h"
  32. #include "resultview.h"
  33. #include "eventlock.h"
  34. extern "C" UINT dbg_count;
  35. //############################################################################
  36. //############################################################################
  37. //
  38. // Traces
  39. //
  40. //############################################################################
  41. //############################################################################
  42. #ifdef DBG
  43. CTraceTag tagTree(TEXT("Tree View"), TEXT("Tree View"));
  44. #endif //DBG
  45. //############################################################################
  46. //############################################################################
  47. //
  48. // Implementation of class CTreeViewMap
  49. //
  50. //############################################################################
  51. //############################################################################
  52. /*+-------------------------------------------------------------------------*
  53. *
  54. * CTreeViewMap::ScOnItemAdded
  55. *
  56. * PURPOSE: Called when an item is added. Indexes the item.
  57. *
  58. * PARAMETERS:
  59. * TVINSERTSTRUCT * pTVInsertStruct :
  60. * HTREEITEM hti :
  61. * HMTNODE hMTNode :
  62. *
  63. * RETURNS:
  64. * SC
  65. *
  66. *+-------------------------------------------------------------------------*/
  67. SC
  68. CTreeViewMap::ScOnItemAdded (TVINSERTSTRUCT *pTVInsertStruct, HTREEITEM hti, HMTNODE hMTNode)
  69. {
  70. DECLARE_SC(sc, TEXT("CTreeViewMap::ScOnItemAdded"));
  71. // validate parameters
  72. sc = ScCheckPointers(pTVInsertStruct);
  73. if(sc)
  74. return sc;
  75. if(!hti || !hMTNode)
  76. return (sc = E_INVALIDARG);
  77. // create a new map info structure.
  78. TreeViewMapInfo *pMapInfo = new TreeViewMapInfo;
  79. if(!pMapInfo)
  80. return (sc = E_OUTOFMEMORY);
  81. // fill in the values
  82. pMapInfo->hNode = CAMCTreeView::NodeFromLParam (pTVInsertStruct->item.lParam);
  83. pMapInfo->hti = hti;
  84. pMapInfo->hMTNode = hMTNode;
  85. // set up the indexes
  86. ASSERT(m_hMTNodeMap.find(pMapInfo->hMTNode) == m_hMTNodeMap.end());
  87. ASSERT(m_hNodeMap.find(pMapInfo->hNode) == m_hNodeMap.end());
  88. m_hMTNodeMap [pMapInfo->hMTNode] = pMapInfo;
  89. m_hNodeMap [pMapInfo->hNode] = pMapInfo;
  90. return sc;
  91. }
  92. /*+-------------------------------------------------------------------------*
  93. *
  94. * CTreeViewMap::ScOnItemDeleted
  95. *
  96. * PURPOSE: Called when a tree item is deleted. Removes the item from the
  97. * indexes.
  98. *
  99. * PARAMETERS:
  100. * HNODE hNode :
  101. * HTREEITEM hti :
  102. *
  103. * RETURNS:
  104. * SC
  105. *
  106. *+-------------------------------------------------------------------------*/
  107. SC
  108. CTreeViewMap::ScOnItemDeleted (HNODE hNode, HTREEITEM hti)
  109. {
  110. DECLARE_SC(sc, TEXT("CTreeViewMap::ScOnItemDeleted"));
  111. // validate parameters
  112. sc = ScCheckPointers((LPVOID) hNode, (LPVOID) hti);
  113. if(sc)
  114. return sc;
  115. // remove the TreeViewMapInfo pointer from all the maps
  116. HNodeLookupMap::iterator iter = m_hNodeMap.find(hNode);
  117. if(iter == m_hNodeMap.end())
  118. return (sc = E_UNEXPECTED);
  119. TreeViewMapInfo *pMapInfo = iter->second; // find the map info structure.
  120. if(!pMapInfo)
  121. return (sc = E_UNEXPECTED);
  122. HMTNODE hMTNode = pMapInfo->hMTNode;
  123. #ifdef DBG
  124. // verify that the same structure is pointed to by the other maps.
  125. ASSERT(m_hMTNodeMap.find(hMTNode)->second == pMapInfo);
  126. #endif
  127. m_hMTNodeMap.erase(hMTNode);
  128. m_hNodeMap.erase(hNode);
  129. // finally delete the TreeViewMapInfo structure
  130. delete pMapInfo;
  131. return sc;
  132. }
  133. // Fast lookup methods
  134. /*+-------------------------------------------------------------------------*
  135. *
  136. * CTreeViewMap::ScGetHNodeFromHMTNode
  137. *
  138. * PURPOSE: Quickly (log n time) retrieves the HNODE for an HMTNODE.
  139. *
  140. * PARAMETERS:
  141. * HMTNODE hMTNode :
  142. * ou t :
  143. *
  144. * RETURNS:
  145. * SC
  146. *
  147. *+-------------------------------------------------------------------------*/
  148. SC
  149. CTreeViewMap::ScGetHNodeFromHMTNode (HMTNODE hMTNode, /*out*/ HNODE* phNode) // fast conversion from hNode to hMTNode.
  150. {
  151. DECLARE_SC(sc, TEXT("CTreeViewMap::ScGetHNode"));
  152. // validate parameters
  153. sc = ScCheckPointers((LPVOID) hMTNode, phNode);
  154. if(sc)
  155. return sc;
  156. // find the mapinfo structure.
  157. HMTNodeLookupMap::iterator iter = m_hMTNodeMap.find(hMTNode);
  158. if(iter == m_hMTNodeMap.end())
  159. return (sc = ScFromMMC(IDS_NODE_NOT_FOUND));
  160. TreeViewMapInfo *pMapInfo = iter->second; // find the map info structure.
  161. if(!pMapInfo)
  162. return (sc = E_UNEXPECTED);
  163. *phNode = pMapInfo->hNode;
  164. return sc;
  165. }
  166. /*+-------------------------------------------------------------------------*
  167. *
  168. * CTreeViewMap::ScGetHTreeItemFromHNode
  169. *
  170. * PURPOSE: Quickly (log n time) retrieves the HTREEITEM for an HNODE.
  171. *
  172. * PARAMETERS:
  173. * HNODE hNode :
  174. * ou t :
  175. *
  176. * RETURNS:
  177. * SC
  178. *
  179. *+-------------------------------------------------------------------------*/
  180. SC
  181. CTreeViewMap::ScGetHTreeItemFromHNode(HNODE hNode, /*out*/ HTREEITEM* phti) // fast conversion from HTREEITEM to HNODE
  182. {
  183. DECLARE_SC(sc, TEXT("CTreeViewMap::ScGetHTreeItem"));
  184. // validate parameters
  185. sc = ScCheckPointers((LPVOID) hNode, phti);
  186. if(sc)
  187. return sc;
  188. // find the mapinfo structure.
  189. HNodeLookupMap::iterator iter = m_hNodeMap.find(hNode);
  190. if(iter == m_hNodeMap.end())
  191. return (sc = E_UNEXPECTED);
  192. TreeViewMapInfo *pMapInfo = iter->second; // find the map info structure.
  193. if(!pMapInfo)
  194. return (sc = E_UNEXPECTED);
  195. *phti = pMapInfo->hti;
  196. return sc;
  197. }
  198. /*+-------------------------------------------------------------------------*
  199. *
  200. * CTreeViewMap::ScGetHTreeItemFromHMTNode
  201. *
  202. * PURPOSE: Quickly (log n time) retrieves the HTREEITEM for an HMTNODE.
  203. *
  204. * PARAMETERS:
  205. * HMTNODE hMTNode :
  206. * ou t :
  207. *
  208. * RETURNS:
  209. * SC
  210. *
  211. *+-------------------------------------------------------------------------*/
  212. SC
  213. CTreeViewMap::ScGetHTreeItemFromHMTNode(HMTNODE hMTNode, /*out*/ HTREEITEM* phti) // fast conversion from HMTNode to HTREEITEM.
  214. {
  215. DECLARE_SC(sc, TEXT("CTreeViewMap::ScGetHTreeItem"));
  216. // validate parameters
  217. //sc = ScCheckPointers(hMTNode, phti);
  218. if(sc)
  219. return sc;
  220. // find the mapinfo structure.
  221. HMTNodeLookupMap::iterator iter = m_hMTNodeMap.find(hMTNode);
  222. if(iter == m_hMTNodeMap.end())
  223. return (sc = E_UNEXPECTED);
  224. TreeViewMapInfo *pMapInfo = iter->second; // find the map info structure.
  225. if(!pMapInfo)
  226. return (sc = E_UNEXPECTED);
  227. *phti = pMapInfo->hti;
  228. return sc;
  229. }
  230. //############################################################################
  231. //############################################################################
  232. //
  233. // Implementation of class CAMCTreeView
  234. //
  235. //############################################################################
  236. //############################################################################
  237. /////////////////////////////////////////////////////////////////////////////
  238. // CAMCTreeView
  239. DEBUG_DECLARE_INSTANCE_COUNTER(CAMCTreeView);
  240. CAMCTreeView::CAMCTreeView()
  241. : m_FontLinker (this)
  242. {
  243. DEBUG_INCREMENT_INSTANCE_COUNTER(CAMCTreeView);
  244. m_fInCleanUp = FALSE;
  245. m_fInExpanding = FALSE;
  246. m_pAMCView = NULL;
  247. SetHasList(TRUE);
  248. SetTempSelectedItem (NULL);
  249. ASSERT (!IsTempSelectionActive());
  250. AddObserver(static_cast<CTreeViewObserver&>(m_treeMap)); // add an observer to this control.
  251. }
  252. CAMCTreeView::~CAMCTreeView()
  253. {
  254. DEBUG_DECREMENT_INSTANCE_COUNTER(CAMCTreeView);
  255. // Smart pointer are released during their destructor
  256. }
  257. IMPLEMENT_DYNCREATE(CAMCTreeView, CTreeView)
  258. BEGIN_MESSAGE_MAP(CAMCTreeView, CTreeView)
  259. //{{AFX_MSG_MAP(CAMCTreeView)
  260. ON_WM_CREATE()
  261. ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChanged)
  262. ON_NOTIFY_REFLECT(TVN_SELCHANGING, OnSelChanging)
  263. ON_NOTIFY_REFLECT(TVN_GETDISPINFO, OnGetDispInfo)
  264. ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemExpanding)
  265. ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemExpanded)
  266. ON_WM_DESTROY()
  267. ON_WM_KEYDOWN()
  268. ON_WM_SYSKEYDOWN()
  269. ON_WM_SYSCHAR()
  270. ON_WM_MOUSEACTIVATE()
  271. ON_WM_SETFOCUS()
  272. ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
  273. ON_NOTIFY_REFLECT(TVN_BEGINRDRAG, OnBeginRDrag)
  274. ON_WM_KILLFOCUS()
  275. //}}AFX_MSG_MAP
  276. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
  277. END_MESSAGE_MAP()
  278. /*+-------------------------------------------------------------------------*
  279. * CAMCTreeView::ScSetTempSelection
  280. *
  281. * Applies temporary selection to the specified HTREEITEM.
  282. *--------------------------------------------------------------------------*/
  283. SC CAMCTreeView::ScSetTempSelection (HTREEITEM htiTempSelect)
  284. {
  285. AFX_MANAGE_STATE (AfxGetAppModuleState());
  286. DECLARE_SC (sc, _T("CAMCTreeView::ScSetTempSelection"));
  287. /*
  288. * Don't use ScSetTempSelection(NULL) to remove temporary selection;
  289. * use ScRemoveTempSelection instead.
  290. */
  291. ASSERT (htiTempSelect != NULL);
  292. if (htiTempSelect == NULL)
  293. return (sc = E_FAIL);
  294. /*
  295. * If this fails, you must first call ScRemoveTempSelection to remove
  296. * the temporary selection state (TVIS_SELECTED) from the current
  297. * temporary selection.
  298. */
  299. ASSERT (!IsTempSelectionActive());
  300. SetTempSelectedItem (htiTempSelect);
  301. ASSERT (GetTempSelectedItem() == htiTempSelect);
  302. HTREEITEM htiSelected = GetSelectedItem();
  303. if (htiSelected != htiTempSelect)
  304. {
  305. SetItemState (htiSelected, 0, TVIS_SELECTED);
  306. SetItemState (htiTempSelect, TVIS_SELECTED, TVIS_SELECTED);
  307. }
  308. ASSERT (IsTempSelectionActive());
  309. return (sc);
  310. }
  311. /*+-------------------------------------------------------------------------*
  312. * CAMCTreeView::ScRemoveTempSelection
  313. *
  314. * Removes the temporary selection from the current temporarily selected
  315. * item, if there is one, and restores it to the item that was selected
  316. * when the temp selection was applied.
  317. *--------------------------------------------------------------------------*/
  318. SC CAMCTreeView::ScRemoveTempSelection ()
  319. {
  320. AFX_MANAGE_STATE (AfxGetAppModuleState());
  321. DECLARE_SC (sc, _T("CAMCTreeView::ScRemoveTempSelection"));
  322. if (!IsTempSelectionActive())
  323. return (sc = S_FALSE);
  324. HTREEITEM htiTempSelect = GetTempSelectedItem();
  325. HTREEITEM htiSelected = GetSelectedItem();
  326. if (htiTempSelect != htiSelected)
  327. {
  328. SetItemState (htiTempSelect, 0, TVIS_SELECTED);
  329. SetItemState (htiSelected, TVIS_SELECTED, TVIS_SELECTED);
  330. }
  331. SetTempSelectedItem (NULL);
  332. ASSERT (!IsTempSelectionActive());
  333. return (sc);
  334. }
  335. /*+-------------------------------------------------------------------------*
  336. * CAMCTreeView::ScReselect
  337. *
  338. *
  339. *--------------------------------------------------------------------------*/
  340. SC CAMCTreeView::ScReselect ()
  341. {
  342. AFX_MANAGE_STATE (AfxGetAppModuleState());
  343. NM_TREEVIEW nmtv;
  344. nmtv.itemOld.hItem = nmtv.itemNew.hItem = GetSelectedItem();
  345. if (nmtv.itemOld.hItem)
  346. {
  347. nmtv.itemOld.lParam = nmtv.itemNew.lParam = GetItemData(nmtv.itemOld.hItem);
  348. LRESULT lUnused;
  349. OnSelChangingWorker (&nmtv, &lUnused);
  350. OnSelChangedWorker (&nmtv, &lUnused);
  351. }
  352. return (S_OK);
  353. }
  354. /////////////////////////////////////////////////////////////////////////////
  355. // CAMCTreeView message handlers
  356. BOOL CAMCTreeView::PreCreateWindow(CREATESTRUCT& cs)
  357. {
  358. cs.style |= TVS_EDITLABELS | TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS;
  359. cs.dwExStyle |= WS_EX_CLIENTEDGE;
  360. // do not paint over the children
  361. cs.style |= WS_CLIPCHILDREN;
  362. return CTreeView::PreCreateWindow(cs);
  363. }
  364. INodeCallback* CAMCTreeView::GetNodeCallback()
  365. {
  366. return m_pAMCView->GetNodeCallback();
  367. }
  368. inline IScopeTreeIter* CAMCTreeView::GetScopeIterator()
  369. {
  370. return m_pAMCView->GetScopeIterator();
  371. }
  372. inline IScopeTree* CAMCTreeView::GetScopeTree()
  373. {
  374. return m_pAMCView->GetScopeTree();
  375. }
  376. void CAMCTreeView::OnGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult)
  377. {
  378. HRESULT hr;
  379. TV_DISPINFO* ptvdi = (TV_DISPINFO*)pNMHDR;
  380. HNODE hNode = NodeFromLParam (ptvdi->item.lParam);
  381. ASSERT(m_pAMCView != NULL);
  382. INodeCallback* spCallback = GetNodeCallback();
  383. ASSERT(spCallback != NULL);
  384. if (hNode)
  385. {
  386. if (ptvdi->item.mask & TVIF_TEXT)
  387. {
  388. tstring strName;
  389. hr = spCallback->GetDisplayName(hNode, strName);
  390. if (hr != S_OK)
  391. {
  392. ptvdi->item.pszText[0] = _T('\0');
  393. ASSERT(FALSE);
  394. }
  395. else
  396. {
  397. // copy the text, but not too much
  398. ASSERT (!IsBadWritePtr (ptvdi->item.pszText, ptvdi->item.cchTextMax));
  399. _tcsncpy (ptvdi->item.pszText, strName.data(), ptvdi->item.cchTextMax);
  400. /*
  401. * _tcsncpy won't terminate the destination if the
  402. * source is bigger than the buffer; make sure the
  403. * string is NULL-terminated
  404. */
  405. ptvdi->item.pszText[ptvdi->item.cchTextMax-1] = _T('\0');
  406. /*
  407. * If this is the selected item and it's text has changed,
  408. * fire an event so observers can know.
  409. */
  410. if ((m_strSelectedItemText != strName.data()) &&
  411. (GetSelectedItem() == ptvdi->item.hItem))
  412. {
  413. m_strSelectedItemText = strName.data();
  414. SC sc = ScFireEvent (CTreeViewObserver::ScOnSelectedItemTextChanged,
  415. (LPCTSTR) m_strSelectedItemText);
  416. if (sc)
  417. sc.TraceAndClear();
  418. }
  419. }
  420. }
  421. int nImage, nSelectedImage;
  422. hr = spCallback->GetImages(hNode, &nImage, &nSelectedImage);
  423. #ifdef DBG
  424. if (hr != S_OK)
  425. {
  426. ASSERT(nImage == 0 && nSelectedImage == 0);
  427. }
  428. #endif
  429. if (ptvdi->item.mask & TVIF_IMAGE)
  430. ptvdi->item.iImage = nImage;
  431. if (ptvdi->item.mask & TVIF_SELECTEDIMAGE)
  432. ptvdi->item.iSelectedImage = nSelectedImage;
  433. // We will get this request once, the first time the scope item comes into view
  434. if (ptvdi->item.mask & TVIF_CHILDREN)
  435. {
  436. ptvdi->item.cChildren = (spCallback->IsExpandable(hNode) != S_FALSE);
  437. // set children to fixed value, to avoid any more callbacks
  438. SetCountOfChildren(ptvdi->item.hItem, ptvdi->item.cChildren);
  439. }
  440. }
  441. else
  442. {
  443. ASSERT(0 && "OnGetDispInfo(HNODE is NULL)");
  444. }
  445. *pResult = 0;
  446. }
  447. //
  448. // Description: This method will set the folders Button(+/-) on or
  449. // of depending on the value of bState
  450. //
  451. // Parameters:
  452. // hItem: the tree item affected
  453. // bState: TRUE = Enable for folder to show it has children
  454. // FALSE = Disable for folder to show it has NO children
  455. //
  456. void CAMCTreeView::SetButton(HTREEITEM hItem, BOOL bState)
  457. {
  458. ASSERT(hItem != NULL);
  459. TV_ITEM item;
  460. ZeroMemory(&item, sizeof(item));
  461. item.hItem = hItem;
  462. item.mask = TVIF_HANDLE | TVIF_CHILDREN;
  463. item.cChildren = bState;
  464. SetItem(&item);
  465. }
  466. //+-------------------------------------------------------------------
  467. //
  468. // Member: CAMCTreeView::ExpandNode
  469. //
  470. // Synopsis: This method populates hItem's(parent folder) children into
  471. // the tree control.
  472. // In the first phase, Expand notifications are sent to the snapin
  473. // which causes all children to be inserted to the master scope
  474. // tree.
  475. // In the second phase, we step through these children and insert
  476. // them to the tree controls.
  477. // For performance reasons, we walk the child list in reverse order
  478. // (last child to first child) inserting the current item at the
  479. // first position.
  480. // If we were to walk the child list in normal order (first to last
  481. // child) inserting the current item at the last position -- the
  482. // underlying tree control takes time that grows exponentially in
  483. // the number of children (as opposed to linearly).
  484. //
  485. // Arguments: hItem: the parent
  486. //
  487. // Returns: TRUE on success and FALSE on failure
  488. //
  489. //--------------------------------------------------------------------
  490. BOOL CAMCTreeView::ExpandNode(HTREEITEM hItem)
  491. {
  492. TRACE_METHOD(CAMCTreeView, ExpandNode);
  493. // not frequently, but... snap-in will display the dialog, dismissing that will
  494. // activate the frame again. Tree item will be automatically selected if there
  495. // is none selected yet. Following will prevent the recursion.
  496. if (m_fInExpanding)
  497. return FALSE;
  498. HRESULT hr;
  499. // Get the HNODE from the tree node
  500. HNODE hNode = GetItemNode(hItem);
  501. ASSERT(hNode != NULL);
  502. ASSERT(m_pAMCView != NULL);
  503. HMTNODE hMTNode;
  504. INodeCallback* spCallback = GetNodeCallback();
  505. ASSERT(spCallback != NULL);
  506. hr = spCallback->GetMTNode(hNode, &hMTNode);
  507. ASSERT(hr == S_OK);
  508. if (hr == S_OK)
  509. {
  510. // The notify will return S_FALSE to indicate already expanded
  511. // or E_xxxx to indicate an error.
  512. hr = spCallback->Notify(hNode, NCLBK_EXPAND, FALSE, 0);
  513. if (hr == S_FALSE)
  514. {
  515. __try
  516. {
  517. m_fInExpanding = TRUE;
  518. hr = spCallback->Notify(hNode, NCLBK_EXPAND, TRUE, 0);
  519. }
  520. __finally
  521. {
  522. m_fInExpanding = FALSE;
  523. }
  524. if (SUCCEEDED(hr))
  525. {
  526. IScopeTreeIter* spIterator = m_pAMCView->GetScopeIterator();
  527. hr = spIterator->SetCurrent(hMTNode);
  528. HMTNODE hMTChildNode;
  529. // Get the last child for the current iterator node:
  530. // (Starting node for walking the child list in reverse order)
  531. if ((spIterator->LastChild(&hMTChildNode) == S_OK) &&
  532. (hMTChildNode)) // Do nothing if last child is NULL
  533. {
  534. IScopeTree* spScopeTree = m_pAMCView->GetScopeTree();
  535. HNODE hNewNode;
  536. // Set the last child as the "current" iterator node
  537. if (spIterator->SetCurrent(hMTChildNode) == S_OK)
  538. {
  539. HMTNODE hCurrentChildNode = hMTChildNode;
  540. do
  541. {
  542. // Insert current node into the tree control
  543. spScopeTree->CreateNode(hCurrentChildNode,
  544. reinterpret_cast<LONG_PTR>(m_pAMCView->GetViewData()),
  545. FALSE, &hNewNode);
  546. #include "pushwarn.h"
  547. #pragma warning(disable: 4552) // "!=" operator has no effect
  548. // Insert at the first position
  549. VERIFY(InsertNode(hItem, hNewNode, TVI_FIRST) != NULL);
  550. #include "popwarn.h"
  551. // give 'em a chance to do the "preload" thing, if applicable
  552. spCallback->PreLoad (hNewNode);
  553. // Traverse the child list in reverse order:
  554. // Set current iterator node to the previous sibling
  555. hr = spIterator->Prev(&hCurrentChildNode);
  556. if(FAILED(hr))
  557. return FALSE;
  558. // child list completely traversed.
  559. if (!hCurrentChildNode)
  560. break;
  561. } while (1);
  562. }
  563. }
  564. spCallback->Notify(hNode, NCLBK_EXPANDED, 0, 0);
  565. }
  566. }
  567. }
  568. return SUCCEEDED(hr);
  569. }
  570. HTREEITEM CAMCTreeView::InsertNode(HTREEITEM hParent, HNODE hNode,
  571. HTREEITEM hInsertAfter)
  572. {
  573. DECLARE_SC(sc, TEXT("CAMCTreeView::InsertNode"));
  574. ASSERT(hParent != NULL);
  575. ASSERT(hNode != NULL);
  576. HRESULT hr;
  577. TV_INSERTSTRUCT tvInsertStruct;
  578. TV_ITEM& item = tvInsertStruct.item;
  579. ZeroMemory(&tvInsertStruct, sizeof(tvInsertStruct));
  580. // Insert item at the end of the hItem chain
  581. tvInsertStruct.hParent = hParent;
  582. tvInsertStruct.hInsertAfter = hInsertAfter;
  583. item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN |
  584. TVIF_PARAM | TVIF_TEXT;
  585. item.pszText = LPSTR_TEXTCALLBACK;
  586. item.lParam = LParamFromNode (hNode);
  587. INodeCallback* spCallback = GetNodeCallback();
  588. ASSERT(spCallback != NULL);
  589. // Set callback mode for children, so we don't have to determine this
  590. // until the scope item becomes visible (it can be expensive).
  591. item.cChildren = I_CHILDRENCALLBACK;
  592. spCallback->GetImages(hNode, &item.iImage, &item.iSelectedImage);
  593. HTREEITEM hti = InsertItem(&tvInsertStruct);
  594. HMTNODE hMTNode = NULL;
  595. sc = spCallback->GetMTNode(hNode, &hMTNode);
  596. if(sc)
  597. sc.TraceAndClear();
  598. // send an event to all interested observers
  599. sc = ScFireEvent(CTreeViewObserver::ScOnItemAdded, &tvInsertStruct, hti, hMTNode);
  600. if(sc)
  601. sc.TraceAndClear();
  602. if (hParent != TVI_ROOT && hti != NULL)
  603. SetCountOfChildren(hParent, 1);
  604. return hti;
  605. }
  606. void CAMCTreeView::ResetNode(HTREEITEM hItem)
  607. {
  608. if (hItem == NULL)
  609. return;
  610. TV_ITEM item;
  611. ZeroMemory(&item, sizeof(item));
  612. item.hItem = hItem;
  613. item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE |
  614. TVIF_STATE | TVIF_TEXT | TVIF_CHILDREN;
  615. item.pszText = LPSTR_TEXTCALLBACK;
  616. item.iImage = I_IMAGECALLBACK;
  617. item.iSelectedImage = I_IMAGECALLBACK;
  618. item.cChildren = I_CHILDRENCALLBACK;
  619. item.lParam = GetItemData(hItem);
  620. SetItem(&item);
  621. }
  622. void CAMCTreeView::OnItemExpanding(NMHDR* pNMHDR, LRESULT* pResult)
  623. {
  624. TRACE_METHOD(CAMCTreeView, OnItemExpanding);
  625. HRESULT hr;
  626. NM_TREEVIEW* pNotify = (NM_TREEVIEW*)pNMHDR;
  627. ASSERT(pNotify != NULL);
  628. HTREEITEM &hItem = pNotify->itemNew.hItem;
  629. ASSERT(hItem != NULL);
  630. BOOL bExpand = FALSE;
  631. // Iteratate the folders below this item
  632. if (pNotify->action == TVE_EXPAND)
  633. {
  634. /*
  635. * Bug 333971: Node expansion might take awhile. Supply a wait cursor
  636. * for all of the UI-challenged snap-ins out there.
  637. */
  638. SetCursor (LoadCursor (NULL, IDC_WAIT));
  639. ExpandNode(hItem);
  640. bExpand = TRUE;
  641. /*
  642. * return the arrow
  643. */
  644. SetCursor (LoadCursor (NULL, IDC_ARROW));
  645. }
  646. INodeCallback* pCallback = GetNodeCallback();
  647. ASSERT(pCallback != NULL);
  648. HNODE hNode = GetItemNode (hItem);
  649. pCallback->Notify(hNode, NCLBK_SETEXPANDEDVISUALLY, bExpand, 0);
  650. // If item has no children remove the + sign
  651. if (GetChildItem(hItem) == NULL)
  652. SetButton(hItem, FALSE);
  653. *pResult = 0;
  654. }
  655. /*+-------------------------------------------------------------------------*
  656. * CAMCTreeView::OnItemExpanded
  657. *
  658. * TVN_ITEMEXPANDED handler for CAMCTreeView.
  659. *--------------------------------------------------------------------------*/
  660. void CAMCTreeView::OnItemExpanded(NMHDR* pNMHDR, LRESULT* pResult)
  661. {
  662. DECLARE_SC (sc, _T("CAMCTreeView::OnItemExpanded"));
  663. NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR;
  664. sc = ScCheckPointers (pnmtv);
  665. if (sc)
  666. return;
  667. /*
  668. * Bug 23153: when collapsing, totally collapse the tree beneath the
  669. * collapsing item. We do this in OnItemExpanded rather than
  670. * OnItemExpanding so we won't see the collapse happen.
  671. */
  672. if (pnmtv->action == TVE_COLLAPSE)
  673. {
  674. CWaitCursor wait;
  675. CollapseChildren (pnmtv->itemNew.hItem);
  676. }
  677. }
  678. /*+-------------------------------------------------------------------------*
  679. * CAMCTreeView::CollapseChildren
  680. *
  681. * Collapses each descendent node of htiParent.
  682. *--------------------------------------------------------------------------*/
  683. void CAMCTreeView::CollapseChildren (HTREEITEM htiParent)
  684. {
  685. HTREEITEM htiChild;
  686. for (htiChild = GetChildItem (htiParent);
  687. htiChild != NULL;
  688. htiChild = GetNextItem (htiChild, TVGN_NEXT))
  689. {
  690. Expand (htiChild, TVE_COLLAPSE);
  691. CollapseChildren (htiChild);
  692. }
  693. }
  694. void CAMCTreeView::OnDeSelectNode(HNODE hNode)
  695. {
  696. DECLARE_SC(sc, TEXT("CAMCTreeView::OnDeSelectNode"));
  697. {
  698. // tell all interested observers about the deselection.
  699. // NOTE: the order is important - legacy snapins believe they can access the
  700. // result pane at this point and have the items still there.
  701. // But this is intermediate state, so Com events are locked out until the
  702. // results are cleared.
  703. // see windows bug (ntbug09) bug# 198660. (10/11/00)
  704. LockComEventInterface(AppEvents);
  705. sc = ScFireEvent(CTreeViewObserver::ScOnItemDeselected, hNode);
  706. if(sc)
  707. return;
  708. // Ensure the result view is clean.
  709. if (HasList())
  710. {
  711. // First findout if the result view is properly
  712. // set in the nodemgr by asking IFramePrivate.
  713. IFramePrivatePtr spFrame = m_spResultData;
  714. if (NULL != spFrame)
  715. {
  716. BOOL bIsResultViewSet = FALSE;
  717. sc = spFrame->IsResultViewSet(&bIsResultViewSet);
  718. // The result view is set, clean it up.
  719. if (bIsResultViewSet)
  720. {
  721. m_spResultData->DeleteAllRsltItems();
  722. m_spResultData->ResetResultData();
  723. }
  724. }
  725. }
  726. }
  727. // don't have a valid result pane type anymore.
  728. SetHasList(false);
  729. }
  730. // Note that OnSelectNode will return S_FALSE if the snap-in changes
  731. // the selection during the process of selecting the requested node.
  732. // A caller that gets an S_FALSE should assume that a different node
  733. // is selected and continue accordingly.
  734. HRESULT CAMCTreeView::OnSelectNode(HTREEITEM hItem, HNODE hNode)
  735. {
  736. DECLARE_SC(sc, _T("CAMCTreeView::OnSelectNode"));
  737. if (!hItem)
  738. {
  739. TraceError(_T("Null hItem ptr\n"), sc);
  740. sc = S_FALSE;
  741. return sc.ToHr();
  742. }
  743. if (!hNode)
  744. {
  745. TraceError(_T("Null hNode ptr\n"), sc);
  746. sc = S_FALSE;
  747. return sc.ToHr();
  748. }
  749. // First ensure that the node has been enumerated by calling expand node.
  750. ExpandNode(hItem);
  751. // set up the AMCView correctly.
  752. BOOL bAddSubFolders = FALSE;
  753. sc = m_pAMCView->ScOnSelectNode(hNode, bAddSubFolders);
  754. if(sc)
  755. return sc.ToHr();
  756. SetHasList(m_pAMCView->HasList());
  757. // add subfolders if necessary.
  758. if(bAddSubFolders)
  759. {
  760. sc = AddSubFolders(hItem, m_spResultData);
  761. if (sc)
  762. return sc.ToHr();
  763. }
  764. if (HasList())
  765. m_spResultData->SetLoadMode(FALSE); // SetLoadMode(FALSE) was called by CAMCView::OnSelectNode.
  766. // Need to change so that both calls are from the same function.
  767. // get the node callback
  768. INodeCallback* spNodeCallBack = GetNodeCallback();
  769. sc = ScCheckPointers(spNodeCallBack, E_UNEXPECTED);
  770. if (sc)
  771. return sc.ToHr();
  772. // send preload notify to children
  773. HTREEITEM hti = GetChildItem (hItem);
  774. while (hti != NULL)
  775. {
  776. HNODE hNode = GetItemNode (hti);
  777. if (hNode != 0)
  778. spNodeCallBack->PreLoad (hNode);
  779. hti = GetNextItem(hti, TVGN_NEXT);
  780. }
  781. return S_OK;
  782. }
  783. /*+-------------------------------------------------------------------------*
  784. * CAMCTreeView::SetNavigatingWithKeyboard
  785. *
  786. *
  787. *--------------------------------------------------------------------------*/
  788. void CAMCTreeView::SetNavigatingWithKeyboard (bool fKeyboardNav)
  789. {
  790. /*
  791. * if the requested state doesn't match the current state,
  792. * change the current state to match the request
  793. */
  794. if (fKeyboardNav != IsNavigatingWithKeyboard())
  795. {
  796. m_spKbdNavDelay = std::auto_ptr<CKeyboardNavDelay>(
  797. (fKeyboardNav)
  798. ? new CKeyboardNavDelay (this)
  799. : NULL /*assigning NULL deletes*/);
  800. }
  801. }
  802. /*+-------------------------------------------------------------------------*
  803. * CAMCTreeView::OnSelChanging
  804. *
  805. * TVN_SELCHANGING handler for CAMCTreeView.
  806. *--------------------------------------------------------------------------*/
  807. void CAMCTreeView::OnSelChanging(NMHDR* pNMHDR, LRESULT* pResult)
  808. {
  809. *pResult = 0;
  810. if (!IsNavigatingWithKeyboard())
  811. OnSelChangingWorker ((NM_TREEVIEW*) pNMHDR, pResult);
  812. }
  813. /*+-------------------------------------------------------------------------*
  814. * CAMCTreeView::OnSelChanged
  815. *
  816. * TVN_SELCHANGED handler for CAMCTreeView.
  817. *--------------------------------------------------------------------------*/
  818. void CAMCTreeView::OnSelChanged(NMHDR* pNMHDR, LRESULT* pResult)
  819. {
  820. NM_TREEVIEW* pnmtv = (NM_TREEVIEW*) pNMHDR;
  821. *pResult = 0;
  822. if (IsNavigatingWithKeyboard())
  823. m_spKbdNavDelay->ScStopTimer();
  824. SetNavigatingWithKeyboard (pnmtv->action == TVC_BYKEYBOARD);
  825. bool fDelayedSelection = IsNavigatingWithKeyboard() &&
  826. !m_spKbdNavDelay->ScStartTimer(pnmtv).IsError();
  827. if (!fDelayedSelection)
  828. OnSelChangedWorker (pnmtv, pResult);
  829. }
  830. /*+-------------------------------------------------------------------------*
  831. * CAMCTreeView::CKeyboardNavDelay::CKeyboardNavDelay
  832. *
  833. *
  834. *--------------------------------------------------------------------------*/
  835. CAMCTreeView::CKeyboardNavDelay::CKeyboardNavDelay (CAMCTreeView* pTreeView) :
  836. m_pTreeView (pTreeView)
  837. {
  838. ZeroMemory (&m_nmtvSelChanged, sizeof (m_nmtvSelChanged));
  839. }
  840. /*+-------------------------------------------------------------------------*
  841. * CAMCTreeView::CKeyboardNavDelay::OnTimer
  842. *
  843. * Called when the keyboard navigation delay timer fires. When that happens,
  844. * we need to perform the selection
  845. *--------------------------------------------------------------------------*/
  846. void CAMCTreeView::CKeyboardNavDelay::OnTimer()
  847. {
  848. /*
  849. * we don't need any more ticks from this timer (ignoring errors)
  850. */
  851. ScStopTimer();
  852. Trace (tagKeyboardNavDelay, _T("Applying delayed scope selection change"));
  853. LRESULT lUnused = 0;
  854. m_pTreeView->OnSelChangedWorker (&m_nmtvSelChanged, &lUnused);
  855. m_pTreeView->SetNavigatingWithKeyboard (false);
  856. /*
  857. * HANDS OFF! CAMCTreeView::SetNavigatingWithKeyboard deleted this object!
  858. */
  859. }
  860. /*+-------------------------------------------------------------------------*
  861. * CAMCTreeView::CKeyboardNavDelay::ScStartTimer
  862. *
  863. *
  864. *--------------------------------------------------------------------------*/
  865. SC CAMCTreeView::CKeyboardNavDelay::ScStartTimer(NMTREEVIEW* pnmtv)
  866. {
  867. DECLARE_SC (sc, _T("CAMCTreeView:CKeyboardNavDelay::ScStartTimer"));
  868. /*
  869. * let the base class start the timer
  870. */
  871. sc = BaseClass::ScStartTimer();
  872. if (sc)
  873. return (sc);
  874. /*
  875. * copy the notification struct so we can send it when our timer ticks
  876. */
  877. m_nmtvSelChanged = *pnmtv;
  878. return (sc);
  879. }
  880. void CAMCTreeView::OnSelChangedWorker(NM_TREEVIEW* pnmtv, LRESULT* pResult)
  881. {
  882. TRACE_METHOD(CAMCTreeView, OnSelChangedWorker);
  883. if (m_fInCleanUp == TRUE)
  884. return;
  885. // See which pane has focus. Some snapins/ocx may steal the focus
  886. // so we restore the focus after selecting the node.
  887. ASSERT (m_pAMCView != NULL);
  888. const CConsoleView::ViewPane ePane = m_pAMCView->GetFocusedPane();
  889. //
  890. // Select the new node
  891. //
  892. // Disable drawing to avoid seeing intermediate tree states.
  893. UpdateWindow();
  894. HRESULT hr = OnSelectNode(pnmtv->itemNew.hItem, (HNODE)pnmtv->itemNew.lParam);
  895. if (hr == S_OK)
  896. {
  897. CStandardToolbar* pStdToolbar = m_pAMCView->GetStdToolbar();
  898. ASSERT(NULL != pStdToolbar);
  899. if (NULL != pStdToolbar)
  900. {
  901. pStdToolbar->ScEnableUpOneLevel(GetRootItem() != pnmtv->itemNew.hItem);
  902. pStdToolbar->ScEnableExportList(m_pAMCView->HasListOrListPad());
  903. }
  904. *pResult = 0;
  905. }
  906. else if (hr == S_FALSE)
  907. {
  908. // snap-in changed the selection on us, so don't continue with this node.
  909. return;
  910. }
  911. else
  912. {
  913. // something wrong with the node we are trying to select, reselect the old one
  914. // SelectItem(pnmtv->itemOld.hItem);
  915. MMCMessageBox(IDS_SNAPIN_FAILED_INIT);
  916. *pResult = hr;
  917. }
  918. /*
  919. * Even if the active view hasn't changed always restore the active view.
  920. * Reason being, for OCX's even though they have the focus, they require
  921. * MMC to inform that OCX being selected. (see bug: 180964)
  922. */
  923. switch (ePane)
  924. {
  925. case CConsoleView::ePane_ScopeTree:
  926. {
  927. // if another view was made active, switch it back.
  928. // View could still be active, but have focus stolen by
  929. // a snap-in or ocx, so ensure view has focus too.
  930. CFrameWnd* pFrame = GetParentFrame();
  931. if (pFrame->GetActiveView() != this)
  932. pFrame->SetActiveView(this);
  933. else if (::GetFocus() != m_hWnd)
  934. SetFocus();
  935. break;
  936. }
  937. case CConsoleView::ePane_Results:
  938. // If the result pane has the focus before and after
  939. // the node was selected, then the last event snapin
  940. // receives is scope selected which is incorrect.
  941. // So we first set scope pane as active view but do
  942. // not send notifications. Then we set result pane
  943. // as active view which sends scope de-select and
  944. // result pane select.
  945. // Set Scope pane as active view and we also want to
  946. // be notified about this active view so that our
  947. // view activation observers will know who is the
  948. // active view.
  949. GetParentFrame()->SetActiveView(this, true);
  950. // Now set result pane as active view and ask for notifications.
  951. m_pAMCView->ScDeferSettingFocusToResultPane();
  952. break;
  953. case CConsoleView::ePane_None:
  954. // no pane is active, do nothing
  955. break;
  956. default:
  957. m_pAMCView->ScSetFocusToPane (ePane);
  958. break;
  959. }
  960. /*
  961. * Bug 345402: Make sure the focus rect is on the list control (if it
  962. * actually has the focus) to wake up any accessibility tools that might
  963. * be watching for input and focus changes.
  964. */
  965. m_pAMCView->ScJiggleListViewFocus ();
  966. }
  967. void CAMCTreeView::OnSelChangingWorker (NM_TREEVIEW* pnmtv, LRESULT* pResult)
  968. {
  969. TRACE_METHOD(CAMCTreeView, OnSelChangingWorker);
  970. if (m_fInCleanUp == TRUE)
  971. return;
  972. //
  973. // De-select the current node
  974. //
  975. OnDeSelectNode ((HNODE)pnmtv->itemOld.lParam);
  976. *pResult = 0;
  977. }
  978. HRESULT CAMCTreeView::AddSubFolders(MTNODEID* pIDs, int length)
  979. {
  980. ASSERT(pIDs != NULL && length != 0);
  981. HRESULT hr = E_FAIL;
  982. // first make sure the specified node is expanded in the tree ctrl
  983. HTREEITEM hti = ExpandNode(pIDs, length, TRUE, false /*bExpandVisually*/);
  984. ASSERT(hti != NULL);
  985. // if successful, add the node's subfolders to the list view
  986. if (hti != NULL)
  987. {
  988. hr = AddSubFolders(hti, m_spResultData);
  989. ASSERT(SUCCEEDED(hr));
  990. }
  991. return hr;
  992. }
  993. HRESULT CAMCTreeView::AddSubFolders(HTREEITEM hti, LPRESULTDATA pResultData)
  994. {
  995. HRESULT hr;
  996. RESULTDATAITEM tRDI;
  997. ::ZeroMemory(&tRDI, sizeof(tRDI));
  998. tRDI.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  999. tRDI.nCol = 0;
  1000. tRDI.str = MMC_TEXTCALLBACK;
  1001. tRDI.nImage = MMC_IMAGECALLBACK;
  1002. tRDI.nIndex = -1;
  1003. hti = GetChildItem(hti);
  1004. ASSERT(m_pAMCView != NULL);
  1005. INodeCallback* spCallback = GetNodeCallback();
  1006. ASSERT(spCallback != NULL);
  1007. while (hti != NULL)
  1008. {
  1009. HNODE hNode = GetItemNode (hti);
  1010. if (hNode != 0)
  1011. {
  1012. tRDI.lParam = LParamFromNode (hNode);
  1013. hr = pResultData->InsertItem(&tRDI);
  1014. CHECK_HRESULT(hr);
  1015. if (SUCCEEDED(hr))
  1016. hr = spCallback->SetResultItem(hNode, tRDI.itemID);
  1017. // add custom image if any
  1018. spCallback->AddCustomFolderImage (hNode, m_spRsltImageList);
  1019. }
  1020. hti = GetNextItem(hti, TVGN_NEXT);
  1021. }
  1022. return S_OK;
  1023. }
  1024. int CAMCTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  1025. {
  1026. DECLARE_SC (sc, _T("CAMCTreeView::OnCreate"));
  1027. TRACE_METHOD(CAMCTreeView, OnCreate);
  1028. if (CTreeView::OnCreate(lpCreateStruct) == -1)
  1029. return -1;
  1030. m_pAMCView = ::GetAMCView (this);
  1031. if (NULL == m_pAMCView)
  1032. {
  1033. ASSERT(m_pAMCView != NULL);
  1034. sc = E_UNEXPECTED;
  1035. return (-1);
  1036. }
  1037. IScopeTree* spScopeTree = m_pAMCView->GetScopeTree();
  1038. ASSERT(spScopeTree != NULL);
  1039. HIMAGELIST hImageList;
  1040. spScopeTree->GetImageList(reinterpret_cast<PLONG_PTR>(&hImageList));
  1041. CBitmap bmp;
  1042. bmp.LoadBitmap(MAKEINTRESOURCE(IDB_AMC_NODES16));
  1043. int i = ImageList_AddMasked(hImageList, (HBITMAP) bmp.GetSafeHandle(), RGB(255,0,255));
  1044. ASSERT(i != -1 && "ImageList_Add failed.");
  1045. TreeView_SetImageList( *this, hImageList, TVSIL_NORMAL );
  1046. sc = ScRegisterAsDropTarget(m_hWnd);
  1047. if (sc)
  1048. return (-1);
  1049. sc = CreateNodeManager();
  1050. if (sc)
  1051. return (-1);
  1052. return 0;
  1053. }
  1054. BOOL CAMCTreeView::DestroyWindow()
  1055. {
  1056. TRACE_METHOD(CAMCTreeView, DestroyWindow);
  1057. CleanUp();
  1058. return CTreeView::DestroyWindow();
  1059. }
  1060. void
  1061. CAMCTreeView::DeleteNode(
  1062. HTREEITEM htiToDelete,
  1063. BOOL fDeleteThis)
  1064. {
  1065. // Ensure curr sel is not a child of the item to be deleted.
  1066. for (HTREEITEM hti = GetSelectedItem();
  1067. hti != NULL;
  1068. hti = GetParentItem(hti))
  1069. {
  1070. if (htiToDelete == hti)
  1071. {
  1072. if (fDeleteThis == TRUE)
  1073. {
  1074. hti = GetParentItem(hti);
  1075. if (hti)
  1076. SelectItem(hti);
  1077. }
  1078. break;
  1079. }
  1080. }
  1081. // There are two paths to this function. Path 1, the view is deleted and there is no
  1082. // longer a root node. Path 2. When a node is manually deleted, the selection is updated
  1083. // in CAMCView::OnUpdateSelectionForDelete, therefore, the above code traverses to the root node
  1084. ASSERT(hti == NULL || fDeleteThis == FALSE);
  1085. // Collapse the node for performance reasons:
  1086. // For each node deleted, the underlying tree control re-adjusts
  1087. // the scroll bar dimensions. This involves walking the succeeding
  1088. // visible nodes; collapsing reduces the number of such nodes.
  1089. Expand(htiToDelete, TVE_COLLAPSE);
  1090. SDeleteNodeInfo dniLocal = {htiToDelete, hti, fDeleteThis};
  1091. _DeleteNode(dniLocal);
  1092. }
  1093. void CAMCTreeView::_DeleteNode(SDeleteNodeInfo& dni)
  1094. {
  1095. ASSERT(&dni != NULL);
  1096. ASSERT(dni.htiToDelete != NULL);
  1097. if (dni.htiToDelete == NULL)
  1098. return;
  1099. SDeleteNodeInfo dniLocal = {GetChildItem(dni.htiToDelete),
  1100. dni.htiSelected, TRUE};
  1101. // delete all the child nodes of the node being deleted
  1102. while (dniLocal.htiToDelete != NULL)
  1103. {
  1104. _DeleteNode(dniLocal);
  1105. dniLocal.htiToDelete = GetChildItem(dni.htiToDelete);
  1106. }
  1107. if (dni.fDeleteThis == TRUE)
  1108. {
  1109. // Reset the temp selection cache.
  1110. // This deals with items that are right click selected (temporary) on the context
  1111. // menu
  1112. if (IsTempSelectionActive() && (GetTempSelectedItem() == dni.htiToDelete))
  1113. {
  1114. SC sc = ScRemoveTempSelection ();
  1115. if (sc)
  1116. sc.TraceAndClear();
  1117. }
  1118. HNODE hNode = (HNODE)GetItemData(dni.htiToDelete);
  1119. HTREEITEM htiParentOfItemToDelete = GetParentItem(dni.htiToDelete);
  1120. // If the item is in list view remove it. We do not want to do this
  1121. // if it is virtual list or if selected item is "Console Root"
  1122. // in which case then parent is NULL.
  1123. if (HasList() && !m_pAMCView->IsVirtualList() &&
  1124. (NULL != htiParentOfItemToDelete) &&
  1125. (htiParentOfItemToDelete == dni.htiSelected) )
  1126. {
  1127. HRESULTITEM itemID;
  1128. HRESULT hr;
  1129. hr = m_spResultData->FindItemByLParam(LParamFromNode(hNode), &itemID);
  1130. if (SUCCEEDED(hr))
  1131. {
  1132. hr = m_spResultData->DeleteItem(itemID, 0);
  1133. ASSERT(SUCCEEDED(hr));
  1134. }
  1135. }
  1136. // tell the tree control to nuke it
  1137. DeleteItem(dni.htiToDelete);
  1138. // send an event to all interested observers
  1139. SC sc = ScFireEvent(CTreeViewObserver::ScOnItemDeleted, hNode, dni.htiToDelete);
  1140. if(sc)
  1141. sc.TraceAndClear();
  1142. // tell the master tree to nuke it.
  1143. m_pAMCView->GetScopeTree()->DestroyNode(hNode);
  1144. // maintain history
  1145. m_pAMCView->GetHistoryList()->DeleteEntry (hNode);
  1146. }
  1147. }
  1148. void CAMCTreeView::DeleteScopeTree()
  1149. {
  1150. DECLARE_SC(sc, _T("CAMCTreeView::DeleteScopeTree"));
  1151. m_fInCleanUp = TRUE;
  1152. // Release the ResultView from the IFrame in the primary snapin in
  1153. // the selected node.
  1154. // This is necessary to release the result view if the selected node
  1155. // is a snap-in node.
  1156. // Free all the nodes
  1157. HTREEITEM htiRoot = GetRootItem();
  1158. if (htiRoot != NULL)
  1159. DeleteNode(htiRoot, TRUE);
  1160. // First findout if the result view is properly
  1161. // set in the nodemgr by asking IFramePrivate.
  1162. IFramePrivatePtr spFrame = m_spResultData;
  1163. if (NULL != spFrame)
  1164. {
  1165. BOOL bIsResultViewSet = FALSE;
  1166. sc = spFrame->IsResultViewSet(&bIsResultViewSet);
  1167. // The result view is set, clean it up.
  1168. if (bIsResultViewSet)
  1169. sc = m_spResultData->DeleteAllRsltItems();
  1170. }
  1171. m_fInCleanUp = FALSE;
  1172. }
  1173. void CAMCTreeView::CleanUp()
  1174. {
  1175. TRACE_METHOD(CAMCTreeView, CleanUp);
  1176. m_fInCleanUp = TRUE;
  1177. m_spNodeManager = NULL;
  1178. m_spHeaderCtrl = NULL;
  1179. m_spResultData = NULL;
  1180. m_spRsltImageList = NULL;
  1181. m_spScopeData = NULL;
  1182. m_fInCleanUp = FALSE;
  1183. }
  1184. void CAMCTreeView::OnDestroy()
  1185. {
  1186. TRACE_METHOD(CAMCTreeView, OnDestroy);
  1187. //CleanUp();
  1188. CTreeView::OnDestroy();
  1189. CleanUp();
  1190. }
  1191. HRESULT CAMCTreeView::CreateNodeManager(void)
  1192. {
  1193. TRACE_METHOD(CAMCTreeView, CreateNodeManager);
  1194. if (m_spScopeData)
  1195. return S_OK;
  1196. #if _MSC_VER >= 1100
  1197. IFramePrivatePtr pIFrame(CLSID_NodeInit, NULL, MMC_CLSCTX_INPROC);
  1198. #else
  1199. IFramePrivatePtr pIFrame(CLSID_NodeInit, MMC_CLSCTX_INPROC);
  1200. #endif
  1201. ASSERT(pIFrame != NULL); if (pIFrame == NULL) return E_FAIL;
  1202. m_spScopeData = pIFrame;
  1203. m_spHeaderCtrl = pIFrame;
  1204. if (m_spHeaderCtrl)
  1205. pIFrame->SetHeader(m_spHeaderCtrl);
  1206. m_spResultData = pIFrame;
  1207. m_spRsltImageList = pIFrame;
  1208. m_spNodeManager = pIFrame;
  1209. pIFrame->SetComponentID(TVOWNED_MAGICWORD);
  1210. return S_OK;
  1211. }
  1212. HTREEITEM CAMCTreeView::GetClickedNode()
  1213. {
  1214. TV_HITTESTINFO tvhi;
  1215. tvhi.pt = (POINT)GetCaretPos();
  1216. tvhi.flags = TVHT_ONITEMLABEL;
  1217. tvhi.hItem = 0;
  1218. HTREEITEM htiClicked = HitTest(&tvhi);
  1219. return htiClicked;
  1220. }
  1221. void CAMCTreeView::GetCountOfChildren(HTREEITEM hItem, LONG* pcChildren)
  1222. {
  1223. TV_ITEM tvi;
  1224. tvi.hItem = hItem;
  1225. tvi.mask = TVIF_CHILDREN;
  1226. tvi.cChildren = 0;
  1227. GetItem(&tvi);
  1228. *pcChildren = tvi.cChildren;
  1229. }
  1230. void CAMCTreeView::SetCountOfChildren(HTREEITEM hItem, int cChildren)
  1231. {
  1232. TV_ITEM tvi;
  1233. tvi.hItem = hItem;
  1234. tvi.mask = TVIF_HANDLE | TVIF_CHILDREN;
  1235. tvi.cChildren = cChildren;
  1236. SetItem(&tvi);
  1237. }
  1238. HTREEITEM CAMCTreeView::FindNode(HTREEITEM hti, MTNODEID id)
  1239. {
  1240. INodeCallback* pCallback = GetNodeCallback();
  1241. static MTNODEID nID = -1;
  1242. static HRESULT hr = S_OK;
  1243. hr = pCallback->GetMTNodeID(GetItemNode(hti), &nID);
  1244. ASSERT(SUCCEEDED(hr));
  1245. if (FAILED(hr))
  1246. return NULL;
  1247. if (nID == id)
  1248. return hti;
  1249. HTREEITEM htiTemp = GetChildItem(hti);
  1250. if (htiTemp != NULL)
  1251. htiTemp = FindNode(htiTemp, id);
  1252. if (htiTemp == NULL)
  1253. {
  1254. htiTemp = GetNextSiblingItem(hti);
  1255. if (htiTemp != NULL)
  1256. htiTemp = FindNode(htiTemp, id);
  1257. }
  1258. return htiTemp;
  1259. }
  1260. HTREEITEM CAMCTreeView::FindSiblingItem(HTREEITEM hti, MTNODEID id)
  1261. {
  1262. INodeCallback* pCallback = GetNodeCallback();
  1263. if (!pCallback)
  1264. return NULL;
  1265. static MTNODEID nID = -1;
  1266. static HRESULT hr = S_OK;
  1267. while (hti != NULL)
  1268. {
  1269. hr = pCallback->GetMTNodeID(GetItemNode(hti), &nID);
  1270. if (FAILED(hr))
  1271. return NULL;
  1272. if (nID == id)
  1273. return hti;
  1274. hti = GetNextSiblingItem(hti);
  1275. }
  1276. return NULL;
  1277. }
  1278. //+-------------------------------------------------------------------
  1279. //
  1280. // Member: CAMCTreeView::SelectNode
  1281. //
  1282. // Synopsis: Given path to a node, select the node. If bSelectExactNode
  1283. // is false then walk the path as much as possible and select
  1284. // the last node in the best matched path. If bSelectExactNode
  1285. // is true then select the node if available else do nothing.
  1286. //
  1287. // Arguments: [pIDs] - [in] Array of node-id's (the path)
  1288. // [length] - [in] length of the above array
  1289. // [bSelectExactNode] - [in] select the exact node or not?
  1290. //
  1291. // Returns: SC, return ScFromMMC(IDS_NODE_NOT_FOUND) if select exact node is specified
  1292. // and it cannot be selected
  1293. //
  1294. //--------------------------------------------------------------------
  1295. SC CAMCTreeView::ScSelectNode(MTNODEID* pIDs, int length, bool bSelectExactNode /*= false*/)
  1296. {
  1297. DECLARE_SC(sc, TEXT("CAMCTreeView::ScSelectNode"));
  1298. sc = ScCheckPointers(pIDs);
  1299. if (sc)
  1300. return sc;
  1301. if (m_fInExpanding)
  1302. return (sc);
  1303. HTREEITEM hti = GetRootItem();
  1304. sc = ScCheckPointers( (void*)hti, E_UNEXPECTED);
  1305. if (sc)
  1306. return sc;
  1307. if (pIDs[0] != ROOTNODEID)
  1308. return (sc = E_INVALIDARG);
  1309. INodeCallback* pCallback = GetNodeCallback();
  1310. sc = ScCheckPointers(pCallback, E_UNEXPECTED);
  1311. if (sc)
  1312. return sc;
  1313. MTNODEID nID = 0;
  1314. sc = pCallback->GetMTNodeID(GetItemNode(hti), &nID);
  1315. if (sc)
  1316. return sc;
  1317. bool bExactNodeFound = false;
  1318. for (int i=0; i<length; ++i)
  1319. {
  1320. if (pIDs[i] == nID)
  1321. break;
  1322. }
  1323. for (++i; i < length; ++i)
  1324. {
  1325. if (GetChildItem(hti) == NULL)
  1326. Expand(hti, TVE_EXPAND);
  1327. hti = FindSiblingItem(GetChildItem(hti), pIDs[i]);
  1328. if (hti == NULL)
  1329. break;
  1330. }
  1331. if (length == i)
  1332. bExactNodeFound = true;
  1333. if (hti)
  1334. {
  1335. // If exact node is to be selected make sure we have walked through the entire path.
  1336. if ( (bSelectExactNode) && (! bExactNodeFound) )
  1337. return ScFromMMC(IDS_NODE_NOT_FOUND); // do not trace this error.
  1338. if (GetSelectedItem() == hti)
  1339. ScReselect();
  1340. else
  1341. SelectItem(hti);
  1342. }
  1343. return sc;
  1344. }
  1345. /*+-------------------------------------------------------------------------*
  1346. *
  1347. * CAMCTreeView::Expand
  1348. *
  1349. * PURPOSE: Expands a particular tree item. This is just a wrapper around the
  1350. * tree control's expand method, which allows items to be expanded
  1351. * without changing the visual appearance of the tree.
  1352. *
  1353. * PARAMETERS:
  1354. * HTREEITEM hItem :
  1355. * UINT nCode :
  1356. * bool bExpandVisually :
  1357. *
  1358. * RETURNS:
  1359. * BOOL
  1360. *
  1361. *+-------------------------------------------------------------------------*/
  1362. BOOL
  1363. CAMCTreeView::Expand(HTREEITEM hItem, UINT nCode, bool bExpandVisually)
  1364. {
  1365. if( (nCode==TVE_EXPAND) && (!bExpandVisually) )
  1366. {
  1367. bool bExpand = true;
  1368. // code repeated here from OnItemExpand - we just mimic the effect of TVN_ITEMEXPANDING.
  1369. ExpandNode(hItem);
  1370. INodeCallback* pCallback = GetNodeCallback();
  1371. ASSERT(pCallback != NULL);
  1372. HNODE hNode = GetItemNode(hItem);
  1373. pCallback->Notify(hNode, NCLBK_SETEXPANDEDVISUALLY, bExpand, 0);
  1374. // If item has no children remove the + sign
  1375. if (GetChildItem(hItem) == NULL)
  1376. SetButton(hItem, FALSE);
  1377. return true;
  1378. }
  1379. else
  1380. return Expand(hItem, nCode);
  1381. }
  1382. /*+-------------------------------------------------------------------------*
  1383. *
  1384. * CAMCTreeView::ExpandNode
  1385. *
  1386. * PURPOSE: Expands a particular node in the tree.
  1387. *
  1388. * PARAMETERS:
  1389. * MTNODEID* pIDs :
  1390. * int length :
  1391. * bool bExpand :
  1392. * bool bExpandVisually : valid only if bExpand is true. If bExpandVisually
  1393. * is true, the items appear in the tree. If false,
  1394. * the tree appears unchanged, although items have been
  1395. * added.
  1396. *
  1397. * RETURNS:
  1398. * HTREEITEM
  1399. *
  1400. *+-------------------------------------------------------------------------*/
  1401. HTREEITEM
  1402. CAMCTreeView::ExpandNode(MTNODEID* pIDs, int length, bool bExpand, bool bExpandVisually)
  1403. {
  1404. HTREEITEM hti = GetRootItem();
  1405. ASSERT(hti != NULL);
  1406. ASSERT(pIDs[0] == ROOTNODEID);
  1407. INodeCallback* pCallback = GetNodeCallback();
  1408. if (!pCallback)
  1409. return NULL;
  1410. MTNODEID nID = 0;
  1411. HRESULT hr = pCallback->GetMTNodeID(GetItemNode(hti), &nID);
  1412. if (FAILED(hr))
  1413. return NULL;
  1414. for (int i=0; i<length; ++i)
  1415. {
  1416. if (pIDs[i] == nID)
  1417. break;
  1418. }
  1419. for (++i; i < length; ++i)
  1420. {
  1421. if (GetChildItem(hti) == NULL)
  1422. Expand(hti, TVE_EXPAND, bExpandVisually);
  1423. hti = FindSiblingItem(GetChildItem(hti), pIDs[i]);
  1424. if (hti == NULL)
  1425. break;
  1426. }
  1427. if (hti)
  1428. Expand(hti, bExpand ? TVE_EXPAND : TVE_COLLAPSE, bExpandVisually);
  1429. return hti;
  1430. }
  1431. /*+-------------------------------------------------------------------------*
  1432. * CAMCTreeView::OnKeyDown
  1433. *
  1434. * WM_KEYDOWN handler for CAMCTreeView.
  1435. *--------------------------------------------------------------------------*/
  1436. void CAMCTreeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  1437. {
  1438. switch (nChar)
  1439. {
  1440. case VK_DELETE:
  1441. if (m_pAMCView->IsVerbEnabled(MMC_VERB_DELETE))
  1442. {
  1443. HTREEITEM hti = GetSelectedItem();
  1444. if (hti != NULL)
  1445. {
  1446. HNODE hNodeSel = GetItemNode(hti);
  1447. ASSERT(hNodeSel != NULL);
  1448. INodeCallback* pNC = GetNodeCallback();
  1449. ASSERT(pNC != NULL);
  1450. pNC->Notify(hNodeSel, NCLBK_DELETE, TRUE, 0);
  1451. }
  1452. return;
  1453. }
  1454. break;
  1455. }
  1456. CTreeView::OnKeyDown(nChar, nRepCnt, nFlags);
  1457. }
  1458. #ifdef DBG
  1459. void CAMCTreeView::DbgDisplayNodeName(HNODE hNode)
  1460. {
  1461. ASSERT(hNode != NULL);
  1462. INodeCallback* spCallback = GetNodeCallback();
  1463. ASSERT(spCallback != NULL);
  1464. tstring strName;
  1465. HRESULT hr = spCallback->GetDisplayName(hNode, strName);
  1466. ::MMCMessageBox( strName.data() );
  1467. }
  1468. void CAMCTreeView::DbgDisplayNodeName(HTREEITEM hti)
  1469. {
  1470. DbgDisplayNodeName((HNODE)GetItemData(hti));
  1471. }
  1472. #endif
  1473. /*+-------------------------------------------------------------------------*
  1474. *
  1475. * CAMCTreeView::OnSysKeyDown and CAMCTreeView::OnSysChar
  1476. *
  1477. * PURPOSE: Handle the WM_SYSKEYDOWN and WM_SYSCHAR messages. Note:
  1478. * VK_RETURN causes a beep if handled in WM_SYSKEYDOWN. And VK_LEFT and
  1479. * VK_RIGHT don't cause a WM_SYSCHAR. Thats why we need to handle these
  1480. * differently.
  1481. *
  1482. * PARAMETERS:
  1483. * UINT nChar :
  1484. * UINT nRepCnt :
  1485. * UINT nFlags :
  1486. *
  1487. * RETURNS:
  1488. * void
  1489. *
  1490. *+-------------------------------------------------------------------------*/
  1491. void CAMCTreeView::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  1492. {
  1493. switch (nChar)
  1494. {
  1495. case VK_LEFT:
  1496. case VK_RIGHT:
  1497. {
  1498. CWnd* pwndParent = GetParent();
  1499. ASSERT(pwndParent != NULL);
  1500. if (pwndParent != NULL)
  1501. pwndParent->SendMessage (WM_SYSKEYDOWN, nChar,
  1502. MAKELPARAM (nRepCnt, nFlags));
  1503. return;
  1504. }
  1505. default:
  1506. break;
  1507. }
  1508. CTreeView::OnSysKeyDown(nChar, nRepCnt, nFlags);
  1509. }
  1510. void CAMCTreeView::OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  1511. {
  1512. DECLARE_SC(sc, TEXT("CAMCTreeView::OnSysChar"));
  1513. switch (nChar)
  1514. {
  1515. case VK_RETURN:
  1516. {
  1517. INodeCallback* pCallback = GetNodeCallback();
  1518. CAMCView* pAMCView = GetAMCView();
  1519. sc = ScCheckPointers(pAMCView, pCallback, E_UNEXPECTED);
  1520. if (sc)
  1521. return;
  1522. if (! pAMCView->IsVerbEnabled(MMC_VERB_PROPERTIES))
  1523. return;
  1524. HTREEITEM hti = GetSelectedItem();
  1525. if (!hti)
  1526. break;
  1527. HNODE hNode = (HNODE)GetItemData(hti);
  1528. if (hNode != 0)
  1529. pCallback->Notify(hNode, NCLBK_PROPERTIES, TRUE, 0);
  1530. return;
  1531. }
  1532. default:
  1533. break;
  1534. }
  1535. CTreeView::OnSysChar(nChar, nRepCnt, nFlags);
  1536. }
  1537. BOOL CAMCTreeView::OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo )
  1538. {
  1539. // Do normal command routing
  1540. if (CTreeView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  1541. return TRUE;
  1542. // if view didn't handle it, give parent view a chance
  1543. if (m_pAMCView != NULL)
  1544. return static_cast<CWnd*>(m_pAMCView)->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  1545. else
  1546. return FALSE;
  1547. }
  1548. int CAMCTreeView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
  1549. {
  1550. /*------------------------------------------------------------------------*/
  1551. /* Short out the WM_MOUSEACTIVATE here to prevent default processing, */
  1552. /* which is to send the message on to succeeding parent windows until */
  1553. /* one answers the message. In our case, it goes all the way up to */
  1554. /* the main frame, which invariably decides to activate. This is a */
  1555. /* problem for two reasons: */
  1556. /* */
  1557. /* 1. On the way back down from the main frame, the message passes */
  1558. /* through CAMCView, which lets CView::OnMouseActivate do the */
  1559. /* work. CView::OnMouseActivate will set itself (CAMCView) as */
  1560. /* the active view, which in turn causes focus to be set to */
  1561. /* the view. CAMCView never wants the focus, since it is just */
  1562. /* a frame for the scope and result panes, so it will deflect */
  1563. /* the activation to the scope pane (CAMCTreeView) in */
  1564. /* CAMCView::OnSetFocus, which is where we want it to be. If */
  1565. /* we short out the processing here, we avoid excessive focus */
  1566. /* churn. It is essential that CAMCTreeView::OnSetFocus set */
  1567. /* itself as the active view to keep the bookkeeping straight. */
  1568. /* */
  1569. /* 2. If we don't short out here and avoid excessive focus churn, */
  1570. /* we have a problem with sometimes erroneously entering rename */
  1571. /* mode when the tree isn't active and the user clicks (once) on */
  1572. /* the selected item. An ordinary activation sequence goes like */
  1573. /* this: WM_MOUSEACTIVATE, WM_xBUTTONDOWN, WM_SETFOUS -- all to */
  1574. /* the tree view. The tree's button down processing doesn't enter */
  1575. /* the label edit (i.e. rename) sequence because it recognizes */
  1576. /* that it doesn't have the focus when the click happens. When */
  1577. /* the tree view is a CView, as in this case, CView::OnMouseActivate */
  1578. /* sets the focus to the tree view, causing the activation sequence */
  1579. /* to look like this: WM_MOUSEACTIVATE, WM_SETFOCUS, WM_xBUTTONDOWN. */
  1580. /* Now the tree's button down processing sees that the tree has */
  1581. /* the focus, so it enters label edit mode. BUG! Shorting out */
  1582. /* here (and relying on CAMCTreeView::OnSetFocus to properly activate */
  1583. /* the view) fixes all that. */
  1584. /*------------------------------------------------------------------------*/
  1585. return (MA_ACTIVATE);
  1586. }
  1587. /*+-------------------------------------------------------------------------*
  1588. * CAMCTreeView::OnSetFocus
  1589. *
  1590. * WM_SETFOCUS handler for CAMCTreeView.
  1591. *--------------------------------------------------------------------------*/
  1592. void CAMCTreeView::OnSetFocus(CWnd* pOldWnd)
  1593. {
  1594. Trace(tagTree, TEXT("OnSetFocus"));
  1595. /*
  1596. * if this view has the focus, it should be the active view
  1597. */
  1598. GetParentFrame()->SetActiveView (this);
  1599. CTreeView::OnSetFocus(pOldWnd);
  1600. }
  1601. /*+-------------------------------------------------------------------------*
  1602. * CAMCTreeView::OnKillFocus
  1603. *
  1604. * WM_KILLFOCUS handler for CAMCTreeView.
  1605. *--------------------------------------------------------------------------*/
  1606. void CAMCTreeView::OnKillFocus(CWnd* pNewWnd)
  1607. {
  1608. Trace(tagTree, TEXT("OnKillFocus"));
  1609. CTreeView::OnKillFocus(pNewWnd);
  1610. /*
  1611. * Bug 114948 (from the "Windows NT Bugs" database, aka "the overlapping
  1612. * rectangle problem"): The tree control has code to invalidate the
  1613. * selected item when focus is lost. If we have a temp selection, we've
  1614. * made a temporary item appear selected by fiddling with TVIS_SELECTED
  1615. * states (see ScSet/RemoveTempSelection). We need to do it that way
  1616. * instead of sending TVM_SELECTITEM so we don't get unwanted
  1617. * TVN_SELCHANGED notifications, but it has the side effect of fooling
  1618. * the tree control's WM_KILLFOCUS handler into invalidating the non-temp
  1619. * selected item instead of the item that is really showing selection, the
  1620. * temp item.
  1621. *
  1622. * This bug was originally fixed with a sledgehammer, specifically by
  1623. * forcing the entire main frame and all of its children to be totally
  1624. * redrawn after displaying any context menu. This caused bug 139541
  1625. * (in the "Windows Bugs" database).
  1626. *
  1627. * A much more surgical fix to 114948, which also avoids 139541, is to
  1628. * manually invalidate the temporarily selected item. It's important
  1629. * that we do this after calling the base class so it will be redrawn
  1630. * in the "we don't have the focus" color (usually gray), rather than
  1631. * the standard selection color.
  1632. */
  1633. if (IsTempSelectionActive())
  1634. {
  1635. CRect rectItem;
  1636. GetItemRect (GetTempSelectedItem(), rectItem, false);
  1637. RedrawWindow (rectItem);
  1638. }
  1639. }
  1640. void CAMCTreeView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
  1641. {
  1642. DECLARE_SC(sc, TEXT("CAMCTreeView::OnActivateView"));
  1643. #ifdef DBG
  1644. Trace(tagTree, _T("TreeView::OnActivateView (%s, pAct=0x%08x, pDeact=0x%08x))\n"),
  1645. (bActivate) ? _T("true") : _T("false"), pActivateView, pDeactiveView);
  1646. #endif
  1647. if ( (pActivateView != pDeactiveView) &&
  1648. (bActivate) )
  1649. {
  1650. sc = ScFireEvent(CTreeViewObserver::ScOnTreeViewActivated);
  1651. if (sc)
  1652. sc.TraceAndClear();
  1653. }
  1654. CTreeView::OnActivateView(bActivate, pActivateView, pDeactiveView);
  1655. }
  1656. /*+-------------------------------------------------------------------------*
  1657. * CAMCTreeView::OnCustomDraw
  1658. *
  1659. * NM_CUSTOMDRAW handler for CAMCTreeView.
  1660. *--------------------------------------------------------------------------*/
  1661. void CAMCTreeView::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
  1662. {
  1663. NMCUSTOMDRAW* pnmcd = reinterpret_cast<NMCUSTOMDRAW *>(pNMHDR);
  1664. ASSERT (CWnd::FromHandle (pnmcd->hdr.hwndFrom) == this);
  1665. *pResult = m_FontLinker.OnCustomDraw (pnmcd);
  1666. }
  1667. /*+-------------------------------------------------------------------------*
  1668. * CTreeFontLinker::GetItemText
  1669. *
  1670. *
  1671. *--------------------------------------------------------------------------*/
  1672. std::wstring CTreeFontLinker::GetItemText (NMCUSTOMDRAW* pnmcd) const
  1673. {
  1674. USES_CONVERSION;
  1675. HTREEITEM hItem = reinterpret_cast<HTREEITEM>(pnmcd->dwItemSpec);
  1676. CTreeCtrl& tc = m_pTreeView->GetTreeCtrl();
  1677. return (std::wstring (T2CW (tc.GetItemText (hItem))));
  1678. }
  1679. //+-------------------------------------------------------------------
  1680. //
  1681. // Member: CAMCTreeView::ScGetTreeItemIconInfo
  1682. //
  1683. // Synopsis: Get the given node's small icon.
  1684. //
  1685. // Arguments: [hNode] - for which info is needed.
  1686. // [phIcon] - [out], ptr to HICON.
  1687. //
  1688. // Note: Caller calls DestroyIcon on the HICON returned.
  1689. //
  1690. // Returns: SC
  1691. //
  1692. //--------------------------------------------------------------------
  1693. SC CAMCTreeView::ScGetTreeItemIconInfo(HNODE hNode, HICON *phIcon)
  1694. {
  1695. DECLARE_SC(sc, TEXT("CAMCTreeView::ScGetTreeItemIconInfo"));
  1696. sc = ScCheckPointers(hNode, phIcon);
  1697. if (sc)
  1698. return sc;
  1699. INodeCallback* spNodeCallBack = GetNodeCallback();
  1700. sc = ScCheckPointers(spNodeCallBack, m_pAMCView, E_UNEXPECTED);
  1701. if (sc)
  1702. return sc;
  1703. // Get the index.
  1704. int nImage = -1;
  1705. int nSelectedImage = -1;
  1706. sc = spNodeCallBack->GetImages(hNode, &nImage, &nSelectedImage);
  1707. if (sc)
  1708. return sc;
  1709. // Get the imagelist.
  1710. HIMAGELIST hImageList = NULL;
  1711. hImageList = TreeView_GetImageList(GetSafeHwnd(), TVSIL_NORMAL);
  1712. if (! hImageList)
  1713. return (sc = E_FAIL);
  1714. *phIcon = ImageList_GetIcon(hImageList, nImage, ILD_TRANSPARENT);
  1715. if (!*phIcon)
  1716. return (sc = E_FAIL);
  1717. return sc;
  1718. }
  1719. /*+-------------------------------------------------------------------------*
  1720. *
  1721. * CAMCTreeView::ScRenameScopeNode
  1722. *
  1723. * PURPOSE: put the specified scope node into rename mode.
  1724. *
  1725. * PARAMETERS:
  1726. * HMTNODE hMTNode :
  1727. *
  1728. * RETURNS:
  1729. * SC
  1730. *
  1731. *+-------------------------------------------------------------------------*/
  1732. SC
  1733. CAMCTreeView::ScRenameScopeNode(HMTNODE hMTNode)
  1734. {
  1735. DECLARE_SC(sc, TEXT("CAMCTreeView::ScRenameScopeNode"));
  1736. if(!IsWindowVisible())
  1737. return (sc = E_FAIL);
  1738. HTREEITEM hti = NULL;
  1739. sc = m_treeMap.ScGetHTreeItemFromHMTNode(hMTNode, &hti);
  1740. if(sc)
  1741. return sc;
  1742. // must have the focus to rename
  1743. if (::GetFocus() != m_hWnd)
  1744. SetFocus();
  1745. if(NULL==EditLabel(hti))
  1746. return (sc = E_FAIL); // if for any reason the operation failed, return an error
  1747. return sc;
  1748. }