Source code of Windows XP (NT5)
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.

1334 lines
38 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-1997 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // TreeView.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CClusterTreeView class.
  10. //
  11. // Author:
  12. // David Potter (davidp) May 1, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "CluAdmin.h"
  21. #include "ConstDef.h"
  22. #include "ClusDoc.h"
  23. #include "TreeView.h"
  24. #include "ListView.h"
  25. #include "SplitFrm.h"
  26. #include "TreeItem.inl"
  27. #include "TraceTag.h"
  28. #include "ExcOper.h"
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Global Variables
  36. /////////////////////////////////////////////////////////////////////////////
  37. #ifdef _DEBUG
  38. CTraceTag g_tagTreeView(_T("UI"), _T("TREE VIEW"), 0);
  39. CTraceTag g_tagTreeDrag(_T("Drag&Drop"), _T("TREE VIEW DRAG"), 0);
  40. CTraceTag g_tagTreeDragMouse(_T("Drag&Drop"), _T("TREE VIEW DRAG MOUSE"), 0);
  41. CTraceTag g_tagTreeViewSelect(_T("UI"), _T("TREE VIEW SELECT"), 0);
  42. #endif
  43. /////////////////////////////////////////////////////////////////////////////
  44. // CClusterTreeView
  45. /////////////////////////////////////////////////////////////////////////////
  46. IMPLEMENT_DYNCREATE(CClusterTreeView, CTreeView)
  47. /////////////////////////////////////////////////////////////////////////////
  48. // Message Maps
  49. BEGIN_MESSAGE_MAP(CClusterTreeView, CTreeView)
  50. //{{AFX_MSG_MAP(CClusterTreeView)
  51. ON_WM_DESTROY()
  52. ON_COMMAND(ID_FILE_RENAME, OnCmdRename)
  53. ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChanged)
  54. ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnBeginLabelEdit)
  55. ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndLabelEdit)
  56. ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemExpanded)
  57. ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
  58. ON_NOTIFY_REFLECT(TVN_BEGINRDRAG, OnBeginDrag)
  59. ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeyDown)
  60. //}}AFX_MSG_MAP
  61. END_MESSAGE_MAP()
  62. /////////////////////////////////////////////////////////////////////////////
  63. //++
  64. //
  65. // CClusterTreeView::CClusterTreeView
  66. //
  67. // Routine Description:
  68. // Default constructor.
  69. //
  70. // Arguments:
  71. // None.
  72. //
  73. // Return Value:
  74. // None.
  75. //
  76. //--
  77. /////////////////////////////////////////////////////////////////////////////
  78. CClusterTreeView::CClusterTreeView(void)
  79. {
  80. m_pframe = NULL;
  81. // Initialize label editing.
  82. m_ptiBeingEdited = NULL;
  83. m_bShiftPressed = FALSE;
  84. m_bControlPressed = FALSE;
  85. m_bAltPressed = FALSE;
  86. // Initialize drag & drop.
  87. m_htiDrag = NULL;
  88. m_ptiDrag = NULL;
  89. m_htiDrop = NULL;
  90. } //*** CClusterTreeView::CClusterTreeView()
  91. /////////////////////////////////////////////////////////////////////////////
  92. //++
  93. //
  94. // CClusterTreeView::~CClusterTreeView
  95. //
  96. // Routine Description:
  97. // Destructor.
  98. //
  99. // Arguments:
  100. // None.
  101. //
  102. // Return Value:
  103. // None.
  104. //
  105. //--
  106. /////////////////////////////////////////////////////////////////////////////
  107. CClusterTreeView::~CClusterTreeView(void)
  108. {
  109. } //*** CClusterTreeView::~CClusterTreeView()
  110. /////////////////////////////////////////////////////////////////////////////
  111. //++
  112. //
  113. // CClusterTreeView::PreCreateWindow
  114. //
  115. // Routine Description:
  116. // Called before the window has been created.
  117. //
  118. // Arguments:
  119. // cs CREATESTRUCT
  120. //
  121. // Return Value:
  122. // TRUE Successful.
  123. // FALSE Failed.
  124. //
  125. //--
  126. /////////////////////////////////////////////////////////////////////////////
  127. BOOL CClusterTreeView::PreCreateWindow(CREATESTRUCT & cs)
  128. {
  129. // TODO: Modify the Window class or styles here by modifying
  130. // the CREATESTRUCT cs
  131. return CTreeView::PreCreateWindow(cs);
  132. } //*** CClusterTreeView::PreCreateWindow()
  133. /////////////////////////////////////////////////////////////////////////////
  134. //++
  135. //
  136. // CClusterTreeView::Create
  137. //
  138. // Routine Description:
  139. // Create the window.
  140. //
  141. // Arguments:
  142. // lpszClassName [IN] Name of the window class to create.
  143. // lpszWindowName [IN] Name of the window (used as the caption).
  144. // dwStyle [IN] Window styles.
  145. // rect [IN] Size and position of the window
  146. // pParentWnd [IN OUT] Parent window.
  147. // nID [IN] ID of the window.
  148. // pContext [IN OUT] Create context of the window.
  149. //
  150. // Return Value:
  151. // 0 Successful.
  152. // !0 Unsuccessful.
  153. //
  154. //--
  155. /////////////////////////////////////////////////////////////////////////////
  156. BOOL CClusterTreeView::Create(
  157. LPCTSTR lpszClassName,
  158. LPCTSTR lpszWindowName,
  159. DWORD dwStyle,
  160. const RECT & rect,
  161. CWnd * pParentWnd,
  162. UINT nID,
  163. CCreateContext * pContext
  164. )
  165. {
  166. dwStyle |= TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_EDITLABELS | TVS_SHOWSELALWAYS;
  167. return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
  168. } //*** CClusterTreeView::Create()
  169. /////////////////////////////////////////////////////////////////////////////
  170. //++
  171. //
  172. // CClusterTreeView::OnDraw
  173. //
  174. // Routine Description:
  175. // Called to draw the view.
  176. //
  177. // Arguments:
  178. // pDC [IN OUT] Device Context for the view.
  179. //
  180. // Return Value:
  181. // None.
  182. //
  183. //--
  184. /////////////////////////////////////////////////////////////////////////////
  185. void CClusterTreeView::OnDraw(IN OUT CDC* pDC)
  186. {
  187. #if 0
  188. CClusterDoc* pDoc = GetDocument();
  189. ASSERT_VALID(pDoc);
  190. // TODO: add draw code for native data here
  191. #endif
  192. } //*** CClusterTreeView::OnDraw()
  193. /////////////////////////////////////////////////////////////////////////////
  194. //++
  195. //
  196. // CClusterTreeView::OnInitialUpdate
  197. //
  198. // Routine Description:
  199. // Do one-time initialization.
  200. //
  201. // Arguments:
  202. // None.
  203. //
  204. // Return Value:
  205. // None.
  206. //
  207. //--
  208. /////////////////////////////////////////////////////////////////////////////
  209. void CClusterTreeView::OnInitialUpdate(void)
  210. {
  211. CClusterAdminApp * papp = GetClusterAdminApp();
  212. CClusterDoc * pdocCluster = GetDocument();
  213. CString strSelection;
  214. CTreeView::OnInitialUpdate();
  215. // Save the frame pointer.
  216. // ASSERT(m_pframe == NULL);
  217. m_pframe = (CSplitterFrame *) GetParentFrame();
  218. ASSERT_VALID(m_pframe);
  219. ASSERT_KINDOF(CSplitterFrame, m_pframe);
  220. // Tell the tree control about our images. We are using the
  221. // same image list for both normal and state images.
  222. GetTreeCtrl().SetImageList(papp->PilSmallImages(), TVSIL_NORMAL);
  223. // GetTreeCtrl().SetImageList(papp->PilSmallImages(), TVSIL_STATE);
  224. // Read the last selection.
  225. ReadPreviousSelection(strSelection);
  226. // Recursively add items starting with the cluster.
  227. BAddItems(pdocCluster->PtiCluster(), strSelection, TRUE /*bExpanded*/);
  228. // Expand the Cluster item by default.
  229. // pdocCluster->PtiCluster()->BExpand(this, TVE_EXPAND);
  230. } //*** CClusterTreeView::OnInitialUpdate()
  231. /////////////////////////////////////////////////////////////////////////////
  232. //++
  233. //
  234. // CClusterTreeView::BAddItems
  235. //
  236. // Routine Description:
  237. // Add an item and then add all its children.
  238. //
  239. // Arguments:
  240. // pti [IN OUT] Item to add to the tree.
  241. // rstrSelection [IN] Previous selection.
  242. // bExpanded [IN] TRUE = add expanded.
  243. //
  244. // Return Value:
  245. // TRUE Parent needs to be expanded.
  246. // FALSE Parent does not need to be expanded.
  247. //
  248. //--
  249. /////////////////////////////////////////////////////////////////////////////
  250. BOOL CClusterTreeView::BAddItems(
  251. IN OUT CTreeItem * pti,
  252. IN const CString & rstrSelection,
  253. IN BOOL bExpanded // = FALSE
  254. )
  255. {
  256. POSITION posChild;
  257. CTreeItem * ptiChild;
  258. BOOL bRetExpanded = FALSE;
  259. ASSERT_VALID(pti);
  260. // Insert this item into the tree.
  261. pti->HtiInsertInTree(this);
  262. if (bExpanded || pti->BShouldBeExpanded(this))
  263. bRetExpanded = TRUE;
  264. // Add all the child items.
  265. posChild = pti->LptiChildren().GetHeadPosition();
  266. while (posChild != NULL)
  267. {
  268. ptiChild = pti->LptiChildren().GetNext(posChild);
  269. ASSERT_VALID(ptiChild);
  270. bExpanded = BAddItems(ptiChild, rstrSelection);
  271. if (bExpanded)
  272. bRetExpanded = TRUE;
  273. } // while: more child items
  274. if (bRetExpanded)
  275. pti->BExpand(this, TVE_EXPAND);
  276. if (rstrSelection == pti->StrProfileSection())
  277. {
  278. pti->Select(this, TRUE /*bSelectInTrue*/);
  279. bRetExpanded = TRUE;
  280. } // if: this is the selected item
  281. return bRetExpanded;
  282. } //*** CClusterTreeView::BAddItems()
  283. #ifdef NEVER
  284. /////////////////////////////////////////////////////////////////////////////
  285. //++
  286. //
  287. // CClusterTreeView::CleanupItems
  288. //
  289. // Routine Description:
  290. // Cleanup an item and all its children.
  291. //
  292. // Arguments:
  293. // ptiParent [IN OUT] Parent item to cleanup.
  294. //
  295. // Return Value:
  296. // None.
  297. //
  298. //--
  299. /////////////////////////////////////////////////////////////////////////////
  300. void CClusterTreeView::CleanupItems(IN OUT CTreeItem * ptiParent)
  301. {
  302. POSITION posChild;
  303. CTreeItem * ptiChild;
  304. // Cleanup all child items.
  305. if (ptiParent != NULL)
  306. {
  307. posChild = ptiParent->LptiChildren().GetHeadPosition();
  308. while (posChild != NULL)
  309. {
  310. ptiChild = ptiParent->LptiChildren().GetNext(posChild);
  311. ASSERT_VALID(ptiChild);
  312. CleanupItems(ptiChild);
  313. } // while: more items in the list
  314. // Cleanup this item.
  315. ptiParent->PreRemoveFromTree(this);
  316. } // if: parent was specified
  317. } //*** CClusterTreeView::CleanupItems()
  318. #endif
  319. /////////////////////////////////////////////////////////////////////////////
  320. // CClusterTreeView diagnostics
  321. #ifdef _DEBUG
  322. void CClusterTreeView::AssertValid(void) const
  323. {
  324. CTreeView::AssertValid();
  325. } //*** CClusterTreeView::AssertValid()
  326. void CClusterTreeView::Dump(CDumpContext & dc) const
  327. {
  328. CTreeView::Dump(dc);
  329. } //*** CClusterTreeView::Dump()
  330. CClusterDoc * CClusterTreeView::GetDocument(void) // non-debug version is inline
  331. {
  332. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CClusterDoc)));
  333. return (CClusterDoc *) m_pDocument;
  334. } //*** CClusterTreeView::GetDocument()
  335. #endif //_DEBUG
  336. /////////////////////////////////////////////////////////////////////////////
  337. //++
  338. //
  339. // CClusterTreeView::PtiSelected
  340. //
  341. // Routine Description:
  342. // Get the tree item that is selected.
  343. //
  344. // Arguments:
  345. // None.
  346. //
  347. // Return Value:
  348. // ptiSelected The selected item or NULL if no item is selected.
  349. //
  350. //--
  351. /////////////////////////////////////////////////////////////////////////////
  352. CTreeItem * CClusterTreeView::PtiSelected(void) const
  353. {
  354. HTREEITEM htiSelected;
  355. CTreeItem * ptiSelected;
  356. htiSelected = HtiSelected();
  357. if (htiSelected != NULL)
  358. {
  359. ptiSelected = (CTreeItem *) GetTreeCtrl().GetItemData(htiSelected);
  360. ASSERT_VALID(ptiSelected);
  361. } // if: selected item found
  362. else
  363. ptiSelected = NULL;
  364. return ptiSelected;
  365. } //*** CClusterTreeView::PtiSelected()
  366. /////////////////////////////////////////////////////////////////////////////
  367. //++
  368. //
  369. // CClusterTreeView::SaveCurrentSelection
  370. //
  371. // Routine Description:
  372. // Save the current selection.
  373. //
  374. // Arguments:
  375. // None.
  376. //
  377. // Return Value:
  378. // None.
  379. //
  380. //--
  381. /////////////////////////////////////////////////////////////////////////////
  382. void CClusterTreeView::SaveCurrentSelection(void)
  383. {
  384. CTreeItem * ptiSelected = PtiSelected();
  385. if (ptiSelected != NULL)
  386. {
  387. CString strSection;
  388. CString strValueName;
  389. ASSERT_VALID(Pframe());
  390. try
  391. {
  392. strSection.Format(
  393. REGPARAM_CONNECTIONS _T("\\%s"),
  394. GetDocument()->StrNode()
  395. );
  396. Pframe()->ConstructProfileValueName(strValueName, REGPARAM_SELECTION);
  397. AfxGetApp()->WriteProfileString(
  398. strSection,
  399. strValueName,
  400. ptiSelected->StrProfileSection()
  401. );
  402. } // try
  403. catch (CException * pe)
  404. {
  405. pe->Delete();
  406. } // catch: CException
  407. } // if: there is a current selection
  408. } //*** CClusterTreeView::SaveCurrentSelection()
  409. /////////////////////////////////////////////////////////////////////////////
  410. //++
  411. //
  412. // CClusterTreeView::ReadPreviousSelection
  413. //
  414. // Routine Description:
  415. // Read the previous selection.
  416. //
  417. // Arguments:
  418. // rstrSelection [OUT] Previous selection read from the user's profile.
  419. //
  420. // Return Value:
  421. // None.
  422. //
  423. //--
  424. /////////////////////////////////////////////////////////////////////////////
  425. void CClusterTreeView::ReadPreviousSelection(OUT CString & rstrSelection)
  426. {
  427. CString strSection;
  428. CString strValueName;
  429. ASSERT_VALID(Pframe());
  430. try
  431. {
  432. // Get the selected item.
  433. strSection.Format(
  434. REGPARAM_CONNECTIONS _T("\\%s"),
  435. GetDocument()->StrNode()
  436. );
  437. Pframe()->ConstructProfileValueName(strValueName, REGPARAM_SELECTION);
  438. rstrSelection = AfxGetApp()->GetProfileString(
  439. strSection,
  440. strValueName,
  441. _T("")
  442. );
  443. } // try
  444. catch (CException * pe)
  445. {
  446. pe->Delete();
  447. } // catch: CException
  448. } //*** CClusterTreeView::ReadPreviousSelection()
  449. /////////////////////////////////////////////////////////////////////////////
  450. //++
  451. //
  452. // CClusterTreeView::OnSelChanged
  453. //
  454. // Routine Description:
  455. // Handler method for the TVN_SELCHANGED message.
  456. //
  457. // Arguments:
  458. // pNMHDR [IN OUT] WM_NOTIFY structure.
  459. // pResult [OUT] LRESULT in which to return the result of this operation.
  460. //
  461. // Return Value:
  462. // None.
  463. //
  464. //--
  465. /////////////////////////////////////////////////////////////////////////////
  466. void CClusterTreeView::OnSelChanged(NMHDR * pNMHDR, LRESULT * pResult)
  467. {
  468. NM_TREEVIEW * pNMTreeView = (NM_TREEVIEW *) pNMHDR;
  469. CTreeItem * ptiSelected;
  470. if (!BDragging())
  471. {
  472. Trace(g_tagTreeViewSelect, _T("OnSelChanged() - BEGIN"));
  473. // Get the selected item.
  474. ptiSelected = (CTreeItem *) pNMTreeView->itemNew.lParam;
  475. ASSERT_VALID(ptiSelected);
  476. // Ask the list view to display the items for this tree item.
  477. ASSERT_VALID(ptiSelected->Pci());
  478. Trace(g_tagTreeViewSelect, _T("OnSelChanged() - '%s' selected"), ptiSelected->Pci()->StrName());
  479. ptiSelected->Select(this, FALSE /*bSelectInTree*/);
  480. // Tell the document of the new selection.
  481. if (m_pDocument != NULL) // this happens on system shutdown
  482. GetDocument()->OnSelChanged(ptiSelected->Pci());
  483. *pResult = 0;
  484. Trace(g_tagTreeViewSelect, _T("OnSelChanged() - END"));
  485. } // if: not dragging
  486. } //*** CClusterTreeView::OnSelChanged()
  487. /////////////////////////////////////////////////////////////////////////////
  488. //++
  489. //
  490. // CClusterTreeView::OnCmdMsg
  491. //
  492. // Routine Description:
  493. // Processes command messages. Attempts to pass them on to a selected
  494. // item first.
  495. //
  496. // Arguments:
  497. // nID [IN] Command ID.
  498. // nCode [IN] Notification code.
  499. // pExtra [IN OUT] Used according to the value of nCode.
  500. // pHandlerInfo [OUT] ???
  501. //
  502. // Return Value:
  503. // TRUE Message has been handled.
  504. // FALSE Message has NOT been handled.
  505. //
  506. //--
  507. /////////////////////////////////////////////////////////////////////////////
  508. BOOL CClusterTreeView::OnCmdMsg(
  509. UINT nID,
  510. int nCode,
  511. void * pExtra,
  512. AFX_CMDHANDLERINFO * pHandlerInfo
  513. )
  514. {
  515. BOOL bHandled = FALSE;
  516. // If there is a current item selected, give it a chance
  517. // to handle the message.
  518. if (HtiSelected() != NULL)
  519. bHandled = PtiSelected()->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  520. if (!bHandled)
  521. bHandled = CTreeView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  522. return bHandled;
  523. } //*** CClusterTreeView::OnCmdMsg()
  524. /////////////////////////////////////////////////////////////////////////////
  525. //++
  526. //
  527. // CClusterTreeView::PmenuPopup
  528. //
  529. // Routine Description:
  530. // Returns a popup menu.
  531. //
  532. // Arguments:
  533. // rpointScreen [IN OUT] Position of the cursor, in screen coordinates.
  534. // rpci [OUT] Pointer in which to return associated cluster item.
  535. //
  536. // Return Value:
  537. // pmenu A popup menu for the item.
  538. //
  539. //--
  540. /////////////////////////////////////////////////////////////////////////////
  541. CMenu * CClusterTreeView::PmenuPopup(
  542. IN OUT CPoint & rpointScreen,
  543. OUT CClusterItem *& rpci
  544. )
  545. {
  546. CTreeItem * pti = NULL;
  547. CMenu * pmenu = NULL;
  548. rpci = NULL;
  549. // If there are no coordinates (-1,-1), display a menu for the selected item.
  550. if ((rpointScreen.x == -1) && (rpointScreen.y == -1))
  551. {
  552. CRect rect;
  553. CTreeItem * ptiSelected = PtiSelected();
  554. if ((ptiSelected != NULL)
  555. && GetTreeCtrl().GetItemRect(HtiSelected(), &rect, FALSE))
  556. {
  557. pti = ptiSelected;
  558. } // if: selected item and it is visible
  559. else
  560. GetWindowRect(&rect);
  561. rpointScreen.x = (rect.right - rect.left) / 2;
  562. rpointScreen.y = (rect.bottom - rect.top) / 2;
  563. ClientToScreen(&rpointScreen);
  564. } // if: no coordinates
  565. else
  566. {
  567. CPoint pointClient;
  568. HTREEITEM hti;
  569. UINT uiFlags;
  570. // Get the coordinates of the point where the user clicked the right mouse
  571. // button. We need in both screen and client coordinates.
  572. pointClient = rpointScreen;
  573. ScreenToClient(&pointClient);
  574. // Get the item under the cursor and get its popup menu.
  575. hti = GetTreeCtrl().HitTest(pointClient, &uiFlags);
  576. if (hti != NULL)
  577. {
  578. // Get the tree item for the item under the cursor.
  579. pti = (CTreeItem *) GetTreeCtrl().GetItemData(hti);
  580. ASSERT_VALID(pti);
  581. // Select the item because that's the only way for it us process the menu.
  582. pti->BSelectItem(this);
  583. } // if: on an item
  584. } // else: coordinates specified
  585. if (pti != NULL)
  586. {
  587. // Get a menu from the item.
  588. pmenu = pti->PmenuPopup();
  589. rpci = pti->Pci();
  590. } // if: item found
  591. return pmenu;
  592. } //*** CClusterTreeView::PmenuPopup()
  593. /////////////////////////////////////////////////////////////////////////////
  594. //++
  595. //
  596. // CClusterTreeView::OnActivateView
  597. //
  598. // Routine Description:
  599. // Called when the view is activated.
  600. //
  601. // Arguments:
  602. // bActivate [IN] Indicates whether the view being activated or deactivated.
  603. // pActivateView [IN OUT] Points to the view object that is being activated.
  604. // peactiveView [IN OUT] Points to the view object that is being deactivated.
  605. //
  606. // Return Value:
  607. // None.
  608. //
  609. //--
  610. /////////////////////////////////////////////////////////////////////////////
  611. void CClusterTreeView::OnActivateView(
  612. BOOL bActivate,
  613. CView * pActivateView,
  614. CView * pDeactiveView
  615. )
  616. {
  617. CTreeItem * ptiSelected = PtiSelected();
  618. if (m_pDocument != NULL) // this happens on system shutdown
  619. {
  620. if (bActivate && (ptiSelected != NULL))
  621. {
  622. ASSERT_VALID(ptiSelected->Pci());
  623. Trace(g_tagTreeViewSelect, _T("OnActiveView: '%s' selected"), ptiSelected->Pci()->StrName());
  624. // Tell the document of the new selection.
  625. GetDocument()->OnSelChanged(ptiSelected->Pci());
  626. } // if: we are being activated
  627. } // if: document is available
  628. CTreeView::OnActivateView(bActivate, pActivateView, pDeactiveView);
  629. } //*** CClusterTreeView::OnActivateView()
  630. /////////////////////////////////////////////////////////////////////////////
  631. //++
  632. //
  633. // CClusterTreeView::OnDestroy
  634. //
  635. // Routine Description:
  636. // Handler method for the WM_DESTROY message.
  637. //
  638. // Arguments:
  639. // None.
  640. //
  641. // Return Value:
  642. // None.
  643. //
  644. //--
  645. /////////////////////////////////////////////////////////////////////////////
  646. void CClusterTreeView::OnDestroy(void)
  647. {
  648. // Clean up the control.
  649. if (m_pDocument != NULL) // this happens on system shutdown
  650. {
  651. // Save the currently selected item.
  652. SaveCurrentSelection();
  653. // Cleanup after ourselves.
  654. // CleanupItems(GetDocument()->PtiCluster());
  655. } // if: the document is still available
  656. CTreeView::OnDestroy();
  657. } //*** CClusterTreeView::OnDestroy()
  658. /////////////////////////////////////////////////////////////////////////////
  659. //++
  660. //
  661. // CClusterTreeView::OnItemExpanded
  662. //
  663. // Routine Description:
  664. // Handler method for the TVN_ITEMEXPANDED message.
  665. //
  666. // Arguments:
  667. // pNMHDR Notification message structure.
  668. // pResult Place in which to return the result.
  669. //
  670. // Return Value:
  671. // None.
  672. //
  673. //--
  674. /////////////////////////////////////////////////////////////////////////////
  675. void CClusterTreeView::OnItemExpanded(NMHDR * pNMHDR, LRESULT * pResult)
  676. {
  677. NM_TREEVIEW * pNMTreeView = (NM_TREEVIEW *) pNMHDR;
  678. if (pNMTreeView->itemNew.mask & TVIF_STATE)
  679. {
  680. BOOL bExpanded;
  681. CTreeItem * pti;
  682. bExpanded = (pNMTreeView->itemNew.state & TVIS_EXPANDED) != 0;
  683. ASSERT(pNMTreeView->itemNew.mask & TVIF_PARAM);
  684. pti = (CTreeItem *) pNMTreeView->itemNew.lParam;
  685. ASSERT_VALID(pti);
  686. ASSERT_KINDOF(CTreeItem, pti);
  687. pti->SetExpandedState(this, bExpanded);
  688. } // if: expanded state changed.
  689. *pResult = 0;
  690. } //*** CClusterTreeView::OnItemExpanded()
  691. /////////////////////////////////////////////////////////////////////////////
  692. //++
  693. //
  694. // CClusterTreeView::OnBeginLabelEdit
  695. //
  696. // Routine Description:
  697. // Handler method for the TVN_BEGINLABELEDIT message.
  698. //
  699. // Arguments:
  700. // pNMHDR Notification message structure.
  701. // pResult Place in which to return the result.
  702. // TRUE = don't edit, FALSE = edit.
  703. //
  704. // Return Value:
  705. // None.
  706. //
  707. //--
  708. /////////////////////////////////////////////////////////////////////////////
  709. void CClusterTreeView::OnBeginLabelEdit(NMHDR * pNMHDR, LRESULT * pResult)
  710. {
  711. ASSERT(pNMHDR != NULL);
  712. TV_DISPINFO * pTVDispInfo = (TV_DISPINFO *) pNMHDR;
  713. CTreeItem * pti = (CTreeItem *) pTVDispInfo->item.lParam;
  714. ASSERT(m_ptiBeingEdited == NULL);
  715. ASSERT_VALID(pti);
  716. ASSERT_VALID(pti->Pci());
  717. if (!BDragging() && pti->Pci()->BCanBeEdited())
  718. {
  719. pti->Pci()->OnBeginLabelEdit(GetTreeCtrl().GetEditControl());
  720. m_ptiBeingEdited = pti;
  721. *pResult = FALSE;
  722. } // if: not dragging and object can be edited
  723. else
  724. *pResult = TRUE;
  725. m_bShiftPressed = FALSE;
  726. m_bControlPressed = FALSE;
  727. m_bAltPressed = FALSE;
  728. } //*** CClusterTreeView::OnBeginLabelEdit()
  729. /////////////////////////////////////////////////////////////////////////////
  730. //++
  731. //
  732. // CClusterTreeView::OnEndLabelEdit
  733. //
  734. // Routine Description:
  735. // Handler method for the TVN_ENDLABELEDIT message.
  736. //
  737. // Arguments:
  738. // pNMHDR Notification message structure.
  739. // pResult Place in which to return the result.
  740. //
  741. // Return Value:
  742. // None.
  743. //
  744. //--
  745. /////////////////////////////////////////////////////////////////////////////
  746. void CClusterTreeView::OnEndLabelEdit(NMHDR * pNMHDR, LRESULT * pResult)
  747. {
  748. ASSERT(pNMHDR != NULL);
  749. TV_DISPINFO * pTVDispInfo = (TV_DISPINFO *) pNMHDR;
  750. CTreeItem * pti = (CTreeItem *) pTVDispInfo->item.lParam;
  751. ASSERT_VALID(pti);
  752. ASSERT(pti == m_ptiBeingEdited);
  753. ASSERT_VALID(pti->Pci());
  754. // If the edit wasn't cancelled, rename it.
  755. if (pTVDispInfo->item.mask & LVIF_TEXT)
  756. {
  757. ASSERT(pti->Pci()->BCanBeEdited());
  758. ASSERT(pTVDispInfo->item.pszText != NULL);
  759. Trace(g_tagTreeView, _T("Ending edit of item '%s' (Saving as '%s')"), pti->Pci()->StrName(), pTVDispInfo->item.pszText);
  760. if ( pti->Pci()->BIsLabelEditValueValid( pTVDispInfo->item.pszText ) )
  761. {
  762. try
  763. {
  764. pti->Pci()->Rename(pTVDispInfo->item.pszText);
  765. *pResult = TRUE;
  766. } // try
  767. catch (CException * pe)
  768. {
  769. pe->ReportError();
  770. pe->Delete();
  771. *pResult = FALSE;
  772. } // catch: CException
  773. } // if: name is valid
  774. else
  775. {
  776. *pResult = FALSE;
  777. }
  778. } // if: the edit wasn't cancelled
  779. else
  780. {
  781. Trace(g_tagTreeView, _T("Ending edit of item '%s' (Not Saving)"), pti->Pci()->StrName());
  782. *pResult = TRUE;
  783. } // else: edit was cancelled
  784. m_ptiBeingEdited = NULL;
  785. m_bShiftPressed = FALSE;
  786. m_bControlPressed = FALSE;
  787. m_bAltPressed = FALSE;
  788. } //*** CClusterTreeView::OnEndLabelEdit()
  789. /////////////////////////////////////////////////////////////////////////////
  790. //++
  791. //
  792. // CClusterTreeView::OnBeginDrag
  793. //
  794. // Routine Description:
  795. // Handler method for the TVN_BEGINDRAG and TVN_BEGINRDRAG messages.
  796. //
  797. // Arguments:
  798. // pNMHDR Notification message structure.
  799. // pResult Place in which to return the result.
  800. //
  801. // Return Value:
  802. // None.
  803. //
  804. //--
  805. /////////////////////////////////////////////////////////////////////////////
  806. void CClusterTreeView::OnBeginDrag(NMHDR * pNMHDR, LRESULT * pResult)
  807. {
  808. CTreeCtrl & rtc = GetTreeCtrl();
  809. CPoint ptScreen;
  810. CPoint ptFrame;
  811. CPoint ptView;
  812. UINT nFlags;
  813. CClusterItem * pci = NULL;
  814. CImageList * pimagelist;
  815. ASSERT_VALID(Pframe());
  816. // Get the current cursor position for identifying the item being dragged.
  817. GetCursorPos(&ptScreen);
  818. ptFrame = ptScreen;
  819. Pframe()->ScreenToClient(&ptFrame);
  820. ptView = ptScreen;
  821. rtc.ScreenToClient(&ptView);
  822. // Get the item being dragged.
  823. {
  824. HTREEITEM hti;
  825. CTreeItem * pti;
  826. hti = rtc.HitTest(ptView, &nFlags);
  827. if (hti == NULL)
  828. return;
  829. pti = (CTreeItem *) rtc.GetItemData(hti);
  830. ASSERT_VALID(pti);
  831. ASSERT_KINDOF(CTreeItem, pti);
  832. ASSERT_VALID(pti->Pci());
  833. // If the item can not be dragged, abort the operation.
  834. if (!pti->Pci()->BCanBeDragged())
  835. return;
  836. // Save info for later.
  837. m_htiDrag = hti;
  838. m_ptiDrag = pti;
  839. m_htiDrop = NULL;
  840. pci = pti->Pci();
  841. } // Get the item being dragged
  842. Trace(g_tagTreeDrag, _T("OnBeginDrag() - Dragging '%s' at (%d,%d)"), m_ptiDrag->StrName(), ptFrame.x, ptFrame.y);
  843. // Create an image list for the image being dragged.
  844. pimagelist = rtc.CreateDragImage(m_htiDrag);
  845. // Let the frame window initialize the drag operation.
  846. Pframe()->BeginDrag(pimagelist, pci, ptFrame, CPoint(0, -16));
  847. *pResult = 0;
  848. } //*** CClusterTreeView::OnBeginDrag(pNMHDR, pResult)
  849. /////////////////////////////////////////////////////////////////////////////
  850. //++
  851. //
  852. // CClusterTreeView::OnMouseMoveForDrag
  853. //
  854. // Routine Description:
  855. // Handler method for the WM_MOUSEMOVE message during a drag operation.
  856. // This function is only responsible for providing view-specific
  857. // functionality, such as selecting the drop target if it is valid.
  858. //
  859. // Arguments:
  860. // nFlags Indicates whether various virtual keys are down.
  861. // point Specifies the x- and y-coordinate of the cursor in frame
  862. // coordinates.
  863. // pwndDrop Specifies the window under the cursor.
  864. //
  865. // Return Value:
  866. // None.
  867. //
  868. //--
  869. /////////////////////////////////////////////////////////////////////////////
  870. void CClusterTreeView::OnMouseMoveForDrag(
  871. IN UINT nFlags,
  872. IN CPoint point,
  873. IN const CWnd * pwndDrop
  874. )
  875. {
  876. ASSERT(BDragging());
  877. ASSERT_VALID(Pframe());
  878. // If we are dragging, select the drop target.
  879. if (BDragging())
  880. {
  881. HTREEITEM hti;
  882. UINT flags;
  883. CPoint ptView;
  884. CTreeCtrl & rtc = GetTreeCtrl();
  885. // Convert the point to view coordinates.
  886. ptView = point;
  887. Pframe()->ClientToScreen(&ptView);
  888. rtc.ScreenToClient(&ptView);
  889. // If this window is the drop target, find the item under the cursor.
  890. if (pwndDrop == &rtc)
  891. {
  892. // If we are over a tree item, highlight it.
  893. hti = rtc.HitTest(ptView, &flags);
  894. if (hti != NULL)
  895. {
  896. CTreeItem * pti;
  897. // Get the item to be highlight.
  898. pti = (CTreeItem *) rtc.GetItemData(hti);
  899. ASSERT_VALID(pti);
  900. ASSERT_KINDOF(CTreeItem, pti);
  901. ASSERT_VALID(pti->Pci());
  902. // If this is not a drop target, change the cursor.
  903. if (pti->Pci()->BCanBeDropTarget(Pframe()->PciDrag()))
  904. Pframe()->ChangeDragCursor(IDC_ARROW);
  905. else
  906. Pframe()->ChangeDragCursor(IDC_NO);
  907. } // if: over a tree item
  908. } // if: this window is the drop target
  909. else
  910. hti = NULL;
  911. // Unlock window updates.
  912. VERIFY(Pimagelist()->DragShowNolock(FALSE /*bShow*/));
  913. // Highlight the new drop target.
  914. rtc.SelectDropTarget(hti);
  915. m_htiDrop = hti;
  916. VERIFY(Pimagelist()->DragShowNolock(TRUE /*bShow*/));
  917. } // if: tree item is being dragged
  918. } //*** CClusterTreeView::OnMouseMoveForDrag()
  919. /////////////////////////////////////////////////////////////////////////////
  920. //++
  921. //
  922. // CClusterTreeView::OnButtonUpForDrag
  923. //
  924. // Routine Description:
  925. // Called to handle a button up event during drag and drop.
  926. //
  927. // Arguments:
  928. // nFlags Indicates whether various virtual keys are down.
  929. // point Specifies the x- and y-coordinate of the cursor.
  930. //
  931. // Return Value:
  932. // None.
  933. //
  934. //--
  935. /////////////////////////////////////////////////////////////////////////////
  936. void CClusterTreeView::OnButtonUpForDrag(IN UINT nFlags, IN CPoint point)
  937. {
  938. ASSERT(BDragging());
  939. ASSERT_VALID(Pframe());
  940. ASSERT_VALID(Pframe()->PciDrag());
  941. // If we are dragging, process the drop.
  942. if (BDragging())
  943. {
  944. HTREEITEM hti;
  945. UINT flags;
  946. CPoint ptView;
  947. CTreeCtrl & rtc = GetTreeCtrl();
  948. Trace(g_tagTreeDrag, _T("OnButtonUpForDrag()"));
  949. // Convert the point to view coordinates.
  950. ptView = point;
  951. Pframe()->ClientToScreen(&ptView);
  952. rtc.ScreenToClient(&ptView);
  953. // If we are over a tree item, drop the item being dragged.
  954. hti = rtc.HitTest(ptView, &flags);
  955. if (hti != NULL)
  956. {
  957. CTreeItem * ptiDropTarget;
  958. // Get the item to drop on.
  959. ptiDropTarget = (CTreeItem *) rtc.GetItemData(hti);
  960. ASSERT_VALID(ptiDropTarget);
  961. ASSERT_KINDOF(CTreeItem, ptiDropTarget);
  962. ASSERT_VALID(ptiDropTarget->Pci());
  963. if (ptiDropTarget->Pci() != Pframe()->PciDrag())
  964. ptiDropTarget->Pci()->DropItem(Pframe()->PciDrag());
  965. } // if: over a tree item
  966. } // if: tree item is being dragged
  967. } //*** CClusterTreeView::OnButtonUpForDrag()
  968. /////////////////////////////////////////////////////////////////////////////
  969. //++
  970. //
  971. // CClusterTreeView::BeginDrag
  972. //
  973. // Routine Description:
  974. // Called by the frame to begin a drag operation.
  975. //
  976. // Arguments:
  977. // None.
  978. //
  979. // Return Value:
  980. // None.
  981. //
  982. //--
  983. /////////////////////////////////////////////////////////////////////////////
  984. void CClusterTreeView::BeginDrag(void)
  985. {
  986. Trace(g_tagTreeDrag, _T("BeginDrag()"));
  987. } //*** CClusterTreeView::BeginDrag()
  988. /////////////////////////////////////////////////////////////////////////////
  989. //++
  990. //
  991. // CClusterTreeView::EndDrag
  992. //
  993. // Routine Description:
  994. // Called by the frame to end a drag operation.
  995. //
  996. // Arguments:
  997. // None.
  998. //
  999. // Return Value:
  1000. // None.
  1001. //
  1002. //--
  1003. /////////////////////////////////////////////////////////////////////////////
  1004. void CClusterTreeView::EndDrag(void)
  1005. {
  1006. // Cleanup.
  1007. GetTreeCtrl().SelectDropTarget(NULL);
  1008. m_htiDrag = NULL;
  1009. m_ptiDrag = NULL;
  1010. m_htiDrop = NULL;
  1011. Trace(g_tagTreeDrag, _T("EndDrag()"));
  1012. } //*** CClusterTreeView::EndDrag()
  1013. /////////////////////////////////////////////////////////////////////////////
  1014. //++
  1015. //
  1016. // CClusterTreeView::PreTranslateMessage
  1017. //
  1018. // Routine Description:
  1019. // Translate window messages before they are dispatched.
  1020. //
  1021. // Arguments:
  1022. // pMsg Points to a MSG structure that contains the message to process.
  1023. //
  1024. // Return Value:
  1025. // TRUE Message was handled.
  1026. // FALSE Message was not handled.
  1027. //
  1028. //--
  1029. /////////////////////////////////////////////////////////////////////////////
  1030. BOOL CClusterTreeView::PreTranslateMessage(MSG * pMsg)
  1031. {
  1032. BOOL bForward = FALSE;
  1033. if (m_ptiBeingEdited != NULL)
  1034. {
  1035. CEdit * pedit = GetTreeCtrl().GetEditControl();
  1036. ASSERT(pedit != NULL);
  1037. if (pMsg->message == WM_KEYDOWN)
  1038. {
  1039. if (pMsg->wParam == VK_SHIFT)
  1040. m_bShiftPressed = TRUE;
  1041. else if (pMsg->wParam == VK_CONTROL)
  1042. {
  1043. ::CopyMemory(&m_msgControl, pMsg, sizeof(m_msgControl));
  1044. m_bControlPressed = TRUE;
  1045. } // else if: control key pressed
  1046. else if ((pMsg->wParam == VK_RETURN)
  1047. || (pMsg->wParam == VK_ESCAPE)
  1048. || (pMsg->wParam == VK_INSERT)
  1049. || (pMsg->wParam == VK_DELETE)
  1050. || (pMsg->wParam == VK_F1)
  1051. || (pMsg->wParam == VK_F5)
  1052. || (pMsg->wParam == VK_F6)
  1053. )
  1054. {
  1055. Trace(g_tagTreeView, _T("PreTranslateMessage() - Forwarding WM_KEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1056. bForward = TRUE;
  1057. if (m_bControlPressed)
  1058. {
  1059. if (pMsg->wParam == VK_RETURN)
  1060. pedit->SendMessage(WM_KEYUP, m_msgControl.wParam, m_msgControl.lParam);
  1061. } // if: control key pressed
  1062. } // else if: editing key pressed
  1063. else if ((pMsg->wParam == VK_TAB)
  1064. || (m_bControlPressed
  1065. && (_T('A') <= pMsg->wParam) && (pMsg->wParam <= _T('Y'))
  1066. && (pMsg->wParam != _T('C'))
  1067. && (pMsg->wParam != _T('H'))
  1068. && (pMsg->wParam != _T('M'))
  1069. && (pMsg->wParam != _T('V'))
  1070. && (pMsg->wParam != _T('X'))
  1071. )
  1072. )
  1073. {
  1074. Trace(g_tagTreeView, _T("PreTranslateMessage() - Ignoring WM_KEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1075. MessageBeep(MB_ICONEXCLAMATION);
  1076. return TRUE;
  1077. } // else if: key pressed that should be ignored
  1078. #ifdef NEVER
  1079. else
  1080. {
  1081. Trace(g_tagTreeView, _T("PreTranslateMessage() - Not forwarding WM_KEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1082. } // else: not processing key
  1083. #endif
  1084. } // if: key pressed while editing label
  1085. else if (pMsg->message == WM_SYSKEYDOWN)
  1086. {
  1087. if (pMsg->wParam == VK_MENU)
  1088. m_bAltPressed = TRUE;
  1089. else if ((pMsg->wParam == VK_RETURN)
  1090. )
  1091. {
  1092. Trace(g_tagTreeView, _T("PreTranslateMessage() - Forwarding WM_SYSKEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1093. bForward = TRUE;
  1094. } // else if: editing key pressed
  1095. #ifdef NEVER
  1096. else
  1097. {
  1098. Trace(g_tagTreeView, _T("PreTranslateMessage() - Not forwarding WM_SYSKEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1099. } // else: not processing key
  1100. #endif
  1101. } // else if: system key pressed while editing label
  1102. if (bForward)
  1103. {
  1104. pedit->SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
  1105. return TRUE;
  1106. } // if: forwarding the message
  1107. else if (pMsg->message == WM_KEYUP)
  1108. {
  1109. if (pMsg->wParam == VK_SHIFT)
  1110. m_bShiftPressed = FALSE;
  1111. else if (pMsg->wParam == VK_CONTROL)
  1112. m_bControlPressed = FALSE;
  1113. } // else if: key up
  1114. else if (pMsg->message == WM_SYSKEYUP)
  1115. {
  1116. if (pMsg->wParam == VK_MENU)
  1117. m_bAltPressed = FALSE;
  1118. } // else if: system key up
  1119. } // if: editing a label
  1120. return CTreeView::PreTranslateMessage(pMsg);
  1121. } //*** CClusterTreeView::PreTranslateMessage()
  1122. /////////////////////////////////////////////////////////////////////////////
  1123. //++
  1124. //
  1125. // CClusterTreeView::OnCmdRename
  1126. //
  1127. // Routine Description:
  1128. // Processes the ID_FILE_RENAME menu command.
  1129. //
  1130. // Arguments:
  1131. // None.
  1132. //
  1133. // Return Value:
  1134. // None.
  1135. //
  1136. //--
  1137. /////////////////////////////////////////////////////////////////////////////
  1138. void CClusterTreeView::OnCmdRename(void)
  1139. {
  1140. CTreeItem * ptiSelected = PtiSelected();
  1141. // If an item has benn selected, begin label editing
  1142. if (ptiSelected != NULL)
  1143. {
  1144. ASSERT_VALID(ptiSelected);
  1145. ptiSelected->EditLabel(this);
  1146. } // if: an item has the focus
  1147. } //*** CClusterTreeView::OnCmdRename()
  1148. /////////////////////////////////////////////////////////////////////////////
  1149. //++
  1150. //
  1151. // CClusterTreeView::OnKeyDown
  1152. //
  1153. // Routine Description:
  1154. // Handler method for the TVN_KEYDOWN message.
  1155. //
  1156. // Arguments:
  1157. // pNMHDR Notification message structure.
  1158. // pResult Place in which to return the result.
  1159. //
  1160. // Return Value:
  1161. // None.
  1162. //
  1163. //--
  1164. /////////////////////////////////////////////////////////////////////////////
  1165. void CClusterTreeView::OnKeyDown(NMHDR * pNMHDR, LRESULT * pResult)
  1166. {
  1167. TV_KEYDOWN * pTVKeyDown = (TV_KEYDOWN *) pNMHDR;
  1168. if (BDragging() && (pTVKeyDown->wVKey == VK_ESCAPE))
  1169. Pframe()->AbortDrag();
  1170. *pResult = 0;
  1171. } //*** CClusterTreeView::OnKeyDown()