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.

1684 lines
50 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ListView.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CListView class.
  10. //
  11. // Author:
  12. // David Potter (davidp) May 6, 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 "ClusItem.h"
  24. #include "ListView.h"
  25. #include "ListItem.h"
  26. #include "ListItem.inl"
  27. #include "SplitFrm.h"
  28. #include "TreeItem.h"
  29. #include "TreeView.h"
  30. #include "ClusDoc.h"
  31. #include "TraceTag.h"
  32. #include "ExcOper.h"
  33. #ifdef _DEBUG
  34. #define new DEBUG_NEW
  35. #undef THIS_FILE
  36. static char THIS_FILE[] = __FILE__;
  37. #endif
  38. /////////////////////////////////////////////////////////////////////////////
  39. // Global Variables
  40. /////////////////////////////////////////////////////////////////////////////
  41. #ifdef _DEBUG
  42. CTraceTag g_tagListView(_T("UI"), _T("LIST VIEW"), 0);
  43. CTraceTag g_tagListDrag(_T("Drag&Drop"), _T("LIST VIEW DRAG"), 0);
  44. CTraceTag g_tagListDragMouse(_T("Drag&Drop"), _T("LIST VIEW DRAG MOUSE"), 0);
  45. #endif
  46. /////////////////////////////////////////////////////////////////////////////
  47. // CClusterListView
  48. /////////////////////////////////////////////////////////////////////////////
  49. IMPLEMENT_DYNCREATE(CClusterListView, CListView)
  50. /////////////////////////////////////////////////////////////////////////////
  51. // Message Maps
  52. BEGIN_MESSAGE_MAP(CClusterListView, CListView)
  53. //{{AFX_MSG_MAP(CClusterListView)
  54. ON_WM_DESTROY()
  55. ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemChanged)
  56. ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)
  57. ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblClk)
  58. ON_COMMAND(ID_OPEN_ITEM, OpenItem)
  59. ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnBeginLabelEdit)
  60. ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndLabelEdit)
  61. ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateProperties)
  62. ON_COMMAND(ID_FILE_PROPERTIES, OnCmdProperties)
  63. ON_COMMAND(ID_FILE_RENAME, OnCmdRename)
  64. ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBeginDrag)
  65. ON_NOTIFY_REFLECT(LVN_BEGINRDRAG, OnBeginDrag)
  66. ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeyDown)
  67. //}}AFX_MSG_MAP
  68. END_MESSAGE_MAP()
  69. /////////////////////////////////////////////////////////////////////////////
  70. //++
  71. //
  72. // CClusterListView::CClusterListView
  73. //
  74. // Routine Description:
  75. // Default constructor.
  76. //
  77. // Arguments:
  78. // None.
  79. //
  80. // Return Value:
  81. // None.
  82. //
  83. //--
  84. /////////////////////////////////////////////////////////////////////////////
  85. CClusterListView::CClusterListView(void)
  86. {
  87. m_ptiParent = NULL;
  88. m_nColumns = 0;
  89. m_nSortDirection = -1;
  90. m_pcoliSort = NULL;
  91. m_pframe = NULL;
  92. // Initialize label editing.
  93. m_pliBeingEdited = NULL;
  94. m_bShiftPressed = FALSE;
  95. m_bControlPressed = FALSE;
  96. m_bAltPressed = FALSE;
  97. // Initialize drag & drop.
  98. m_iliDrag = -1;
  99. m_pliDrag = NULL;
  100. m_iliDrop = -1;
  101. } //*** CClusterListView::CClusterListView()
  102. /////////////////////////////////////////////////////////////////////////////
  103. //++
  104. //
  105. // CClusterListView::~CClusterListView
  106. //
  107. // Routine Description:
  108. // Destructor.
  109. //
  110. // Arguments:
  111. // None.
  112. //
  113. // Return Value:
  114. // None.
  115. //
  116. //--
  117. /////////////////////////////////////////////////////////////////////////////
  118. CClusterListView::~CClusterListView(void)
  119. {
  120. if (m_ptiParent != NULL)
  121. m_ptiParent->Release();
  122. } //*** CClusterListView::~CClusterListView()
  123. /////////////////////////////////////////////////////////////////////////////
  124. //++
  125. //
  126. // CClusterListView::Create
  127. //
  128. // Routine Description:
  129. // Create the window.
  130. //
  131. // Arguments:
  132. // lpszClassName [IN] Name of the window class to create.
  133. // lpszWindowName [IN] Name of the window (used as the caption).
  134. // dwStyle [IN] Window styles.
  135. // rect [IN] Size and position of the window
  136. // pParentWnd [IN OUT ] Parent window.
  137. // nID [IN] ID of the window.
  138. // pContext [IN OUT] Create context of the window.
  139. //
  140. // Return Value:
  141. // 0 Successful.
  142. // !0 Unsuccessful.
  143. //
  144. //--
  145. /////////////////////////////////////////////////////////////////////////////
  146. BOOL CClusterListView::Create(
  147. LPCTSTR lpszClassName,
  148. LPCTSTR lpszWindowName,
  149. DWORD dwStyle,
  150. const RECT & rect,
  151. CWnd * pParentWnd,
  152. UINT nID,
  153. CCreateContext * pContext
  154. )
  155. {
  156. BOOL bSuccess;
  157. // Set default style bits.
  158. dwStyle |=
  159. LVS_SHAREIMAGELISTS
  160. | LVS_EDITLABELS
  161. | LVS_SINGLESEL
  162. | LVS_SHOWSELALWAYS
  163. | LVS_ICON
  164. | LVS_REPORT
  165. ;
  166. bSuccess = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
  167. if (bSuccess)
  168. {
  169. GetListCtrl().SetImageList(GetClusterAdminApp()->PilLargeImages(), LVSIL_NORMAL);
  170. GetListCtrl().SetImageList(GetClusterAdminApp()->PilSmallImages(), LVSIL_SMALL);
  171. // GetListCtrl().SetImageList(GetClusterAdminApp()->PilSmallImages(), LVSIL_STATE);
  172. // Change list view control extended styles.
  173. {
  174. DWORD dwExtendedStyle;
  175. dwExtendedStyle = (DWORD)GetListCtrl().SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE);
  176. GetListCtrl().SendMessage(
  177. LVM_SETEXTENDEDLISTVIEWSTYLE,
  178. 0,
  179. dwExtendedStyle
  180. | LVS_EX_FULLROWSELECT
  181. | LVS_EX_HEADERDRAGDROP
  182. );
  183. } // Change list view control extended styles
  184. } // if: window created successfully
  185. return bSuccess;
  186. } //*** CClusterListView::Create()
  187. /////////////////////////////////////////////////////////////////////////////
  188. //++
  189. //
  190. // CClusterListView::OnInitialUpdate
  191. //
  192. // Routine Description:
  193. // Do one-time initialization.
  194. //
  195. // Arguments:
  196. // None.
  197. //
  198. // Return Value:
  199. // None.
  200. //
  201. //--
  202. /////////////////////////////////////////////////////////////////////////////
  203. void CClusterListView::OnInitialUpdate()
  204. {
  205. CListView::OnInitialUpdate();
  206. // Save the frame pointer.
  207. // ASSERT(m_pframe == NULL);
  208. m_pframe = (CSplitterFrame *) GetParentFrame();
  209. ASSERT_VALID(m_pframe);
  210. ASSERT_KINDOF(CSplitterFrame, m_pframe);
  211. } //*** CClusterListView::OnInitialUpdate()
  212. /////////////////////////////////////////////////////////////////////////////
  213. //++
  214. //
  215. // CClusterListView::Refresh
  216. //
  217. // Routine Description:
  218. // Refresh the view by reloading all the data.
  219. //
  220. // Arguments:
  221. // ptiSelected [IN OUT] Pointer to currently selected item in the tree control.
  222. //
  223. // Return Value:
  224. // None.
  225. //
  226. //--
  227. /////////////////////////////////////////////////////////////////////////////
  228. void CClusterListView::Refresh(IN OUT CTreeItem * ptiSelected)
  229. {
  230. // Save columns.
  231. if (PtiParent() != NULL)
  232. SaveColumns();
  233. // Clean up the control to start with.
  234. DeleteAllItems();
  235. // Cleanup the previous parent tree item.
  236. if (m_ptiParent != NULL)
  237. m_ptiParent->Release();
  238. m_ptiParent = ptiSelected;
  239. // Setup the new selection.
  240. if (m_ptiParent != NULL)
  241. {
  242. ASSERT_VALID(ptiSelected);
  243. CListCtrl & rListCtrl = GetListCtrl();
  244. const CListItemList & rlpli = ptiSelected->LpliChildren();
  245. m_ptiParent->AddRef();
  246. // Add columns to the list control.
  247. AddColumns();
  248. // Add items from the tree item's list to the list view.
  249. {
  250. POSITION pos;
  251. CListItem * pli;
  252. // Tell the list control how many items we will be adding.
  253. // This improves performance.
  254. rListCtrl.SetItemCount((int)rlpli.GetCount());
  255. // Add the items to the list control.
  256. pos = rlpli.GetHeadPosition();
  257. while (pos != NULL)
  258. {
  259. pli = rlpli.GetNext(pos);
  260. ASSERT_VALID(pli);
  261. pli->IliInsertInList(this);
  262. } // while: more items in the list
  263. } // Add items from the tree item's list to the list view
  264. // Give the focus to the first item in the list.
  265. if (rListCtrl.GetItemCount() != 0)
  266. rListCtrl.SetItem(0, 0, LVIF_STATE, NULL, 0, LVIS_FOCUSED, LVIS_FOCUSED, NULL);
  267. } // if: non-null selection
  268. // Set the sort column and direction.
  269. m_nSortDirection = -1;
  270. m_pcoliSort = NULL;
  271. } //*** CClusterListView::Refresh()
  272. /////////////////////////////////////////////////////////////////////////////
  273. //++
  274. //
  275. // CClusterListView::DeleteAllItems
  276. //
  277. // Routine Description:
  278. // Delete all the list and column items.
  279. //
  280. // Arguments:
  281. // None.
  282. //
  283. // Return Value:
  284. // TRUE All items deleted successfully.
  285. // FALSE Not all items were deleted successfully.
  286. //
  287. //--
  288. /////////////////////////////////////////////////////////////////////////////
  289. BOOL CClusterListView::DeleteAllItems(void)
  290. {
  291. BOOL bDeletedAllItems;
  292. BOOL bDeletedAllColumns = TRUE;
  293. int icol;
  294. // Remove all the items from our list.
  295. {
  296. CListItem * pli;
  297. int ili;
  298. int cli = GetListCtrl().GetItemCount();
  299. // Get the index of the first item.
  300. for (ili = 0 ; ili < cli; ili++)
  301. {
  302. pli = (CListItem *) GetListCtrl().GetItemData(ili);
  303. ASSERT_VALID(pli);
  304. pli->PreRemoveFromList(this);
  305. } // for: each item in the list
  306. } // Remove all the items from the cluster item back pointer list
  307. // Delete the columns.
  308. {
  309. for (icol = m_nColumns - 1 ; icol >= 0 ; icol--)
  310. {
  311. // Delete the column from the view.
  312. if (!GetListCtrl().DeleteColumn(icol))
  313. bDeletedAllColumns = FALSE;
  314. } // for: each column
  315. m_nColumns = 0;
  316. } // Delete the columns
  317. // Remove all the items from the list.
  318. bDeletedAllItems = GetListCtrl().DeleteAllItems();
  319. return (bDeletedAllItems && bDeletedAllColumns);
  320. } //*** CClusterListView::DeleteAllItems()
  321. /////////////////////////////////////////////////////////////////////////////
  322. //++
  323. //
  324. // CClusterListView::SaveColumns
  325. //
  326. // Routine Description:
  327. // Save the columns being displayed in the list view.
  328. //
  329. // Arguments:
  330. // None.
  331. //
  332. // Return Value:
  333. // None.
  334. //
  335. //--
  336. /////////////////////////////////////////////////////////////////////////////
  337. void CClusterListView::SaveColumns(void)
  338. {
  339. int icol;
  340. DWORD * prgnColumnInfo;
  341. CListCtrl & rplc = GetListCtrl();
  342. ASSERT_VALID(PtiParent());
  343. // We can only save column information if we are in report view.
  344. if (GetView() & LVS_REPORT)
  345. {
  346. try
  347. {
  348. // Get the column info array for this view.
  349. prgnColumnInfo = PtiParent()->PrgnColumnInfo(this);
  350. // Save the widths of the columns.
  351. for (icol = m_nColumns - 1 ; icol >= 0 ; icol--)
  352. prgnColumnInfo[icol + 1] = rplc.GetColumnWidth(icol);
  353. // Save the position information in the array.
  354. rplc.SendMessage(LVM_GETCOLUMNORDERARRAY, m_nColumns, (LPARAM) &prgnColumnInfo[m_nColumns + 1]);
  355. } // try
  356. catch (CException * pe)
  357. {
  358. pe->Delete();
  359. } // catch: CException
  360. } // if: we are in detail view
  361. } //*** CClusterListView::SaveColumns()
  362. /////////////////////////////////////////////////////////////////////////////
  363. //++
  364. //
  365. // CClusterListView::AddColumns
  366. //
  367. // Routine Description:
  368. // Add columns to the list view.
  369. //
  370. // Arguments:
  371. // None.
  372. //
  373. // Return Value:
  374. // None.
  375. //
  376. //--
  377. /////////////////////////////////////////////////////////////////////////////
  378. void CClusterListView::AddColumns(void)
  379. {
  380. POSITION pos;
  381. int cColumns;
  382. int icoli = 0;
  383. CColumnItem * pcoli;
  384. DWORD * prgnColumnInfo;
  385. CListCtrl & rplc = GetListCtrl();
  386. ASSERT_VALID(PtiParent());
  387. try
  388. {
  389. // Get the column info.
  390. cColumns = (int)PtiParent()->Lpcoli().GetCount();
  391. prgnColumnInfo = PtiParent()->PrgnColumnInfo(this);
  392. pos = PtiParent()->Lpcoli().GetHeadPosition();
  393. for (icoli = 0 ; pos != NULL ; icoli++)
  394. {
  395. // Get the next column item.
  396. pcoli = PtiParent()->Lpcoli().GetNext(pos);
  397. ASSERT(pcoli != NULL);
  398. // Insert the column item in the list.
  399. rplc.InsertColumn(
  400. icoli, // nCol
  401. pcoli->StrText(), // lpszColumnHeading
  402. LVCFMT_LEFT, // nFormat
  403. prgnColumnInfo[icoli + 1], // nWidth
  404. icoli // nSubItem
  405. );
  406. } // while: more items in the list
  407. // Set column positions.
  408. rplc.SendMessage(LVM_SETCOLUMNORDERARRAY, cColumns, (LPARAM) &prgnColumnInfo[cColumns + 1]);
  409. } // try
  410. catch (CException * pe)
  411. {
  412. pe->ReportError();
  413. pe->Delete();
  414. } // catch: CException
  415. m_nColumns = icoli;
  416. } //*** CClusterListView::AddColumns()
  417. /////////////////////////////////////////////////////////////////////////////
  418. // CClusterListView diagnostics
  419. /////////////////////////////////////////////////////////////////////////////
  420. #ifdef _DEBUG
  421. void CClusterListView::AssertValid(void) const
  422. {
  423. CListView::AssertValid();
  424. } //*** CClusterListView::AssertValid()
  425. void CClusterListView::Dump(CDumpContext& dc) const
  426. {
  427. CListView::Dump(dc);
  428. } //*** CClusterListView::Dump()
  429. CClusterDoc * CClusterListView::GetDocument(void) // non-debug version is inline
  430. {
  431. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CClusterDoc)));
  432. return (CClusterDoc *) m_pDocument;
  433. } //*** CClusterListView::GetDocument()
  434. #endif //_DEBUG
  435. /////////////////////////////////////////////////////////////////////////////
  436. //++
  437. //
  438. // CClusterListView::PliFocused
  439. //
  440. // Routine Description:
  441. // Get the list item that has the focus.
  442. //
  443. // Arguments:
  444. // None.
  445. //
  446. // Return Value:
  447. // pliSelected The item with the focus or NULL if no item has focus.
  448. //
  449. //--
  450. /////////////////////////////////////////////////////////////////////////////
  451. CListItem * CClusterListView::PliFocused(void) const
  452. {
  453. int iliFocused;
  454. CListItem * pliFocused;
  455. iliFocused = IliFocused();
  456. if (iliFocused != -1)
  457. {
  458. pliFocused = (CListItem *) GetListCtrl().GetItemData(iliFocused);
  459. ASSERT_VALID(pliFocused);
  460. } // if: found an item with the focus
  461. else
  462. pliFocused = NULL;
  463. return pliFocused;
  464. } //*** CClusterListView::PliFocused()
  465. /////////////////////////////////////////////////////////////////////////////
  466. //++
  467. //
  468. // CClusterListView::OnCmdMsg
  469. //
  470. // Routine Description:
  471. // Processes command messages. Attempts to pass them on to a selected
  472. // item first.
  473. //
  474. // Arguments:
  475. // nID [IN] Command ID.
  476. // nCode [IN] Notification code.
  477. // pExtra [IN OUT] Used according to the value of nCode.
  478. // pHandlerInfo [OUT] ???
  479. //
  480. // Return Value:
  481. // TRUE Message has been handled.
  482. // FALSE Message has NOT been handled.
  483. //
  484. //--
  485. /////////////////////////////////////////////////////////////////////////////
  486. BOOL CClusterListView::OnCmdMsg(
  487. UINT nID,
  488. int nCode,
  489. void * pExtra,
  490. AFX_CMDHANDLERINFO * pHandlerInfo
  491. )
  492. {
  493. int ili;
  494. CListItem * pli;
  495. BOOL bHandled = FALSE;
  496. // If there is a current item selected, give it a chance
  497. // to handle the message.
  498. ili = GetListCtrl().GetNextItem(-1, LVNI_FOCUSED);
  499. if (ili != -1)
  500. {
  501. pli = (CListItem *) GetListCtrl().GetItemData(ili);
  502. ASSERT_VALID(pli);
  503. bHandled = pli->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  504. } // if: an item is selected
  505. if (!bHandled)
  506. bHandled = CListView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  507. return bHandled;
  508. } //*** CClusterListView::OnCmdMsg()
  509. /////////////////////////////////////////////////////////////////////////////
  510. //++
  511. //
  512. // CClusterListView::PmenuPopup
  513. //
  514. // Routine Description:
  515. // Returns a popup menu.
  516. //
  517. // Arguments:
  518. // rpointScreen [IN OUT] Position of the cursor, in screen coordinates.
  519. // rpci [OUT] Pointer in which to return associated cluster item.
  520. //
  521. // Return Value:
  522. // pmenu A popup menu for the item.
  523. //
  524. //--
  525. /////////////////////////////////////////////////////////////////////////////
  526. CMenu * CClusterListView::PmenuPopup(
  527. IN OUT CPoint & rpointScreen,
  528. OUT CClusterItem *& rpci
  529. )
  530. {
  531. CListItem * pli = NULL;
  532. CMenu * pmenu = NULL;
  533. rpci = NULL;
  534. // If there are no coordinates (-1,-1), display a menu for the selected item.
  535. if ((rpointScreen.x == -1) && (rpointScreen.y == -1))
  536. {
  537. CListItem * pliFocused = PliFocused();
  538. CRect rect;
  539. if ((pliFocused != NULL)
  540. && GetListCtrl().GetItemRect(IliFocused(), &rect, LVIR_BOUNDS))
  541. {
  542. pli = pliFocused;
  543. } // if: item with focus and it is visible
  544. else
  545. GetWindowRect(&rect);
  546. rpointScreen.x = (rect.right - rect.left) / 2;
  547. rpointScreen.y = (rect.bottom - rect.top) / 2;
  548. ClientToScreen(&rpointScreen);
  549. } // if: no coordinates
  550. else
  551. {
  552. CPoint pointClient;
  553. int ili;
  554. UINT uiFlags;
  555. // Get the coordinates of the point where the user clicked the right mouse
  556. // button. We need in both screen and client coordinates.
  557. pointClient = rpointScreen;
  558. ScreenToClient(&pointClient);
  559. // Get the item under the cursor and get its popup menu.
  560. ili = GetListCtrl().HitTest(pointClient, &uiFlags);
  561. if ((ili != -1) && ((uiFlags | LVHT_ONITEM) != 0))
  562. {
  563. // Get the list item for the item under the cursor.
  564. pli = (CListItem *) GetListCtrl().GetItemData(ili);
  565. ASSERT_VALID(pli);
  566. } // if: on an item
  567. } // else: coordinates specified
  568. if (pli != NULL)
  569. {
  570. // Get a menu from the item.
  571. pmenu = pli->PmenuPopup();
  572. rpci = pli->Pci();
  573. } // if: item found
  574. return pmenu;
  575. } //*** CClusterListView::PmenuPopup()
  576. /////////////////////////////////////////////////////////////////////////////
  577. //++
  578. //
  579. // CClusterListView::OnUpdateProperties
  580. //
  581. // Routine Description:
  582. // Determines whether menu items corresponding to ID_FILE_PROPERTIES
  583. // should be enabled or not.
  584. //
  585. // Arguments:
  586. // pCmdUI [IN OUT] Command routing object.
  587. //
  588. // Return Value:
  589. // None.
  590. //
  591. //--
  592. /////////////////////////////////////////////////////////////////////////////
  593. void CClusterListView::OnUpdateProperties(CCmdUI * pCmdUI)
  594. {
  595. CListItem * pliFocused = PliFocused();
  596. // If there is an item with the focus, pass this message on to it.
  597. if (pliFocused != NULL)
  598. {
  599. ASSERT_VALID(pliFocused->Pci());
  600. pliFocused->Pci()->OnUpdateProperties(pCmdUI);
  601. } // if: there is an item with the focus
  602. } //*** CClusterListView::OnUpdateProperties()
  603. /////////////////////////////////////////////////////////////////////////////
  604. //++
  605. //
  606. // CClusterListView::OnCmdProperties
  607. //
  608. // Routine Description:
  609. // Processes the ID_FILE_PROPERTIES menu command.
  610. //
  611. // Arguments:
  612. // None.
  613. //
  614. // Return Value:
  615. // None.
  616. //
  617. //--
  618. /////////////////////////////////////////////////////////////////////////////
  619. void CClusterListView::OnCmdProperties(void)
  620. {
  621. CListItem * pliFocused = PliFocused();
  622. // If there is an item with the focus, pass this message on to it.
  623. if (pliFocused != NULL)
  624. {
  625. ASSERT_VALID(pliFocused->Pci());
  626. pliFocused->Pci()->OnCmdProperties();
  627. } // if: there is an item with the focus
  628. } //*** CClusterListView::OnCmdProperties()
  629. /////////////////////////////////////////////////////////////////////////////
  630. //++
  631. //
  632. // CClusterListView::OnItemChanged
  633. //
  634. // Routine Description:
  635. // Handler method for the LVN_ITEMCHANGED message.
  636. //
  637. // Arguments:
  638. // pNMHDR [IN OUT] WM_NOTIFY structure.
  639. // pResult [OUT] LRESULT in which to return the result of this operation.
  640. //
  641. // Return Value:
  642. // None.
  643. //
  644. //--
  645. /////////////////////////////////////////////////////////////////////////////
  646. void CClusterListView::OnItemChanged(NMHDR * pNMHDR, LRESULT * pResult)
  647. {
  648. NM_LISTVIEW * pNMListView = (NM_LISTVIEW *) pNMHDR;
  649. CWnd * pwndFocus = GetFocus();
  650. CListItem * pli;
  651. if (m_pDocument != NULL) // this happens on system shutdown
  652. {
  653. // If the item has just lost or received the focus, save it and set the menu.
  654. if ((pNMListView->uChanged & LVIF_STATE)
  655. && (pwndFocus == &GetListCtrl()))
  656. {
  657. ASSERT(pNMListView->iItem != -1);
  658. // Get the item whose state is changing.
  659. pli = (CListItem *) pNMListView->lParam;
  660. ASSERT_VALID(pli);
  661. if ((pNMListView->uOldState & LVIS_FOCUSED)
  662. && !(pNMListView->uNewState & LVIS_FOCUSED))
  663. {
  664. Trace(g_tagListView, _T("OnItemChanged() - '%s' lost focus"), pli->Pci()->StrName());
  665. // Tell the document of the new selection.
  666. GetDocument()->OnSelChanged(NULL);
  667. } // if: old item losing focus
  668. else if (!(pNMListView->uOldState & LVIS_FOCUSED)
  669. && (pNMListView->uNewState & LVIS_FOCUSED))
  670. {
  671. Trace(g_tagListView, _T("OnItemChanged() - '%s' received focus"), pli->Pci()->StrName());
  672. // Tell the document of the new selection.
  673. GetDocument()->OnSelChanged(pli->Pci());
  674. } // else: new item receiving focus
  675. } // if: item received the focus
  676. } // if: document is available
  677. *pResult = 0;
  678. } //*** CClusterListView::OnItemChanged()
  679. /////////////////////////////////////////////////////////////////////////////
  680. //++
  681. //
  682. // CClusterListView::OnActivateView
  683. //
  684. // Routine Description:
  685. // Called when the view is activated.
  686. //
  687. // Arguments:
  688. // bActivate [IN] Indicates whether the view being activated or deactivated.
  689. // pActivateView [IN OUT] Points to the view object that is being activated.
  690. // peactiveView [IN OUT] Points to the view object that is being deactivated.
  691. //
  692. // Return Value:
  693. // None.
  694. //
  695. //--
  696. /////////////////////////////////////////////////////////////////////////////
  697. void CClusterListView::OnActivateView(
  698. BOOL bActivate,
  699. CView * pActivateView,
  700. CView * pDeactiveView
  701. )
  702. {
  703. CListItem * pliFocused = PliFocused();
  704. if (m_pDocument != NULL) // this happens on system shutdown
  705. {
  706. if (bActivate && (pliFocused != NULL))
  707. {
  708. ASSERT_VALID(pliFocused->Pci());
  709. Trace(g_tagListView, _T("OnActivateView() - '%s' received focus"), pliFocused->Pci()->StrName());
  710. // Tell the document of the new selection.
  711. GetDocument()->OnSelChanged(pliFocused->Pci());
  712. } // if: we are being activated
  713. } // if: document is available
  714. CListView::OnActivateView(bActivate, pActivateView, pDeactiveView);
  715. } //*** CClusterListView::OnActivateView()
  716. /////////////////////////////////////////////////////////////////////////////
  717. //++
  718. //
  719. // CClusterListView::OnDestroy
  720. //
  721. // Routine Description:
  722. // Handler method for the WM_DESTROY message.
  723. //
  724. // Arguments:
  725. // None.
  726. //
  727. // Return Value:
  728. // None.
  729. //
  730. //--
  731. /////////////////////////////////////////////////////////////////////////////
  732. void CClusterListView::OnDestroy(void)
  733. {
  734. // Save the columns.
  735. if (PtiParent() != NULL)
  736. SaveColumns();
  737. // Clean up the control.
  738. DeleteAllItems();
  739. CListView::OnDestroy();
  740. } //*** CClusterListView::OnDestroy()
  741. /////////////////////////////////////////////////////////////////////////////
  742. //++
  743. //
  744. // CClusterListView::OnColumnClick
  745. //
  746. // Routine Description:
  747. // Handler method for the LVN_COLUMNCLICK message.
  748. //
  749. // Arguments:
  750. // None.
  751. //
  752. // Return Value:
  753. // None.
  754. //
  755. //--
  756. /////////////////////////////////////////////////////////////////////////////
  757. void CClusterListView::OnColumnClick(NMHDR * pNMHDR, LRESULT * pResult)
  758. {
  759. NM_LISTVIEW * pNMListView = (NM_LISTVIEW *) pNMHDR;
  760. int ili;
  761. CListItem * pli;
  762. POSITION pos;
  763. CColumnItem * pcoli;
  764. if (GetListCtrl().GetItemCount() != 0)
  765. {
  766. // Get the first item in the list.
  767. ili = GetListCtrl().GetNextItem(-1, LVNI_ALL);
  768. ASSERT(ili != -1);
  769. pli = (CListItem *) GetListCtrl().GetItemData(ili);
  770. ASSERT_VALID(pli);
  771. ASSERT_VALID(pli->PtiParent());
  772. // Get the column item to sort by.
  773. pos = pli->PtiParent()->Lpcoli().FindIndex(pNMListView->iSubItem);
  774. ASSERT(pos != NULL);
  775. pcoli = pli->PtiParent()->Lpcoli().GetAt(pos);
  776. ASSERT_VALID(pcoli);
  777. // Save the current sort column and direction.
  778. if (pcoli == PcoliSort())
  779. m_nSortDirection ^= -1;
  780. else
  781. {
  782. m_pcoliSort = pcoli;
  783. m_nSortDirection = 0;
  784. } // else: different column
  785. // Sort the list.
  786. GetListCtrl().SortItems(CompareItems, (LPARAM) this);
  787. } // if: there are items in the list
  788. *pResult = 0;
  789. } //*** CClusterListView::OnColumnClick()
  790. /////////////////////////////////////////////////////////////////////////////
  791. //++
  792. //
  793. // CClusterListView::CompareItems [static]
  794. //
  795. // Routine Description:
  796. // Callback function for the CListCtrl::SortItems method.
  797. //
  798. // Arguments:
  799. // lparam1 First item to compare.
  800. // lparam2 Second item to compare.
  801. // lparamSort Sort parameter.
  802. //
  803. // Return Value:
  804. // -1 First parameter comes before second.
  805. // 0 First and second parameters are the same.
  806. // 1 First parameter comes after second.
  807. //
  808. //--
  809. /////////////////////////////////////////////////////////////////////////////
  810. int CALLBACK CClusterListView::CompareItems(
  811. LPARAM lparam1,
  812. LPARAM lparam2,
  813. LPARAM lparamSort
  814. )
  815. {
  816. CListItem * pli1 = (CListItem *) lparam1;
  817. CListItem * pli2 = (CListItem *) lparam2;
  818. CClusterListView * pclv = (CClusterListView *) lparamSort;
  819. CString str1;
  820. CString str2;
  821. int nResult;
  822. ASSERT_VALID(pli1);
  823. ASSERT_VALID(pli2);
  824. ASSERT_VALID(pli1->Pci());
  825. ASSERT_VALID(pli2->Pci());
  826. ASSERT_VALID(pclv);
  827. ASSERT_VALID(pclv->PcoliSort());
  828. // Get the strings from the list items.
  829. pli1->Pci()->BGetColumnData(pclv->PcoliSort()->Colid(), str1);
  830. pli2->Pci()->BGetColumnData(pclv->PcoliSort()->Colid(), str2);
  831. // Compare the two strings.
  832. // Use CompareString() so that it will sort properly on localized builds.
  833. nResult = CompareString(
  834. LOCALE_USER_DEFAULT,
  835. 0,
  836. str1,
  837. str1.GetLength(),
  838. str2,
  839. str2.GetLength()
  840. );
  841. if ( nResult == CSTR_LESS_THAN )
  842. {
  843. nResult = -1;
  844. }
  845. else if ( nResult == CSTR_EQUAL )
  846. {
  847. nResult = 0;
  848. }
  849. else if ( nResult == CSTR_GREATER_THAN )
  850. {
  851. nResult = 1;
  852. }
  853. else
  854. {
  855. // An error occurred. Ignore it.
  856. nResult = 0;
  857. }
  858. // Return the result based on the direction we are sorting.
  859. if (pclv->NSortDirection() != 0)
  860. nResult = -nResult;
  861. return nResult;
  862. } //*** CClusterListView::CompareItems()
  863. /////////////////////////////////////////////////////////////////////////////
  864. //++
  865. //
  866. // CClusterListView::OnDblClk
  867. //
  868. // Routine Description:
  869. // Handler method for the NM_DBLCLK message.
  870. //
  871. // Arguments:
  872. // pNMHDR Notification message structure.
  873. // pResult Place in which to return the result.
  874. //
  875. // Return Value:
  876. // None.
  877. //
  878. //--
  879. /////////////////////////////////////////////////////////////////////////////
  880. void CClusterListView::OnDblClk(NMHDR * pNMHDR, LRESULT * pResult)
  881. {
  882. OpenItem();
  883. *pResult = 0;
  884. } //*** CClusterListView::OnDblClk()
  885. /////////////////////////////////////////////////////////////////////////////
  886. //++
  887. //
  888. // CClusterListView::OpenItem
  889. //
  890. // Routine Description:
  891. // Open the item with the focus.
  892. //
  893. // Arguments:
  894. // None.
  895. //
  896. // Return Value:
  897. // None.
  898. //
  899. //--
  900. /////////////////////////////////////////////////////////////////////////////
  901. void CClusterListView::OpenItem(void)
  902. {
  903. CListItem * pliFocused = PliFocused();
  904. if (m_pliBeingEdited == NULL)
  905. {
  906. // If an item has focus, open it or show its properties.
  907. if (pliFocused != NULL)
  908. {
  909. CTreeItem * pti;
  910. ASSERT_VALID(pliFocused->PtiParent());
  911. Trace(g_tagListView, _T("Opening item '%s'"), pliFocused->Pci()->StrName());
  912. // Find the item tree item for the list item.
  913. pti = pliFocused->PtiParent()->PtiChildFromPci(pliFocused->Pci());
  914. // If this item has a tree item, open it up. Otherwise show its
  915. // properties.
  916. if (pti != NULL)
  917. {
  918. CSplitterFrame * pframe;
  919. // Get the frame pointer so we can talk to the tree view.
  920. pframe = (CSplitterFrame *) GetParentFrame();
  921. ASSERT_KINDOF(CSplitterFrame, pframe);
  922. pliFocused->PtiParent()->OpenChild(pti, pframe);
  923. } // if: item is openable
  924. else
  925. OnCmdProperties();
  926. } // if: an item has focus
  927. } // if: label not being edited
  928. else
  929. {
  930. ASSERT_VALID(m_pliBeingEdited);
  931. Trace(g_tagListView, _T("Not opening item '%s'"), m_pliBeingEdited->Pci()->StrName());
  932. } // else if: label being edited
  933. } //*** CClusterListView::OpenItem()
  934. /////////////////////////////////////////////////////////////////////////////
  935. //++
  936. //
  937. // CClusterListView::OnBeginLabelEdit
  938. //
  939. // Routine Description:
  940. // Handler method for the LVN_BEGINLABELEDIT message.
  941. //
  942. // Arguments:
  943. // pNMHDR Notification message structure.
  944. // pResult Place in which to return the result.
  945. //
  946. // Return Value:
  947. // None.
  948. //
  949. //--
  950. /////////////////////////////////////////////////////////////////////////////
  951. void CClusterListView::OnBeginLabelEdit(NMHDR * pNMHDR, LRESULT * pResult)
  952. {
  953. ASSERT(pNMHDR != NULL);
  954. LV_DISPINFO * pDispInfo = (LV_DISPINFO *) pNMHDR;
  955. CListItem * pli = (CListItem *) pDispInfo->item.lParam;
  956. ASSERT(m_pliBeingEdited == NULL);
  957. ASSERT_VALID(pli->Pci());
  958. if (pli->Pci()->BCanBeEdited())
  959. {
  960. pli->Pci()->OnBeginLabelEdit(GetListCtrl().GetEditControl());
  961. m_pliBeingEdited = pli;
  962. *pResult = FALSE;
  963. } // if: object can be renamed
  964. else
  965. *pResult = TRUE;
  966. m_bShiftPressed = FALSE;
  967. m_bControlPressed = FALSE;
  968. m_bAltPressed = FALSE;
  969. } //*** CClusterListView::OnBeginLabelEdit()
  970. /////////////////////////////////////////////////////////////////////////////
  971. //++
  972. //
  973. // CClusterListView::OnEndLabelEdit
  974. //
  975. // Routine Description:
  976. // Handler method for the LVN_ENDLABELEDIT message.
  977. //
  978. // Arguments:
  979. // pNMHDR Notification message structure.
  980. // pResult Place in which to return the result.
  981. //
  982. // Return Value:
  983. // None.
  984. //
  985. //--
  986. /////////////////////////////////////////////////////////////////////////////
  987. void CClusterListView::OnEndLabelEdit(NMHDR * pNMHDR, LRESULT * pResult)
  988. {
  989. ASSERT(pNMHDR != NULL);
  990. LV_DISPINFO * pDispInfo = (LV_DISPINFO *) pNMHDR;
  991. CListItem * pli = (CListItem *) pDispInfo->item.lParam;
  992. ASSERT_VALID(pli);
  993. ASSERT(pli == m_pliBeingEdited);
  994. ASSERT_VALID(pli->Pci());
  995. // If the edit wasn't cancelled, rename it.
  996. if (pDispInfo->item.mask & LVIF_TEXT)
  997. {
  998. ASSERT(pli->Pci()->BCanBeEdited());
  999. ASSERT(pDispInfo->item.pszText != NULL);
  1000. Trace(g_tagListView, _T("Ending edit of item '%s' (Saving as '%s')"), pli->Pci()->StrName(), pDispInfo->item.pszText);
  1001. if ( pli->Pci()->BIsLabelEditValueValid( pDispInfo->item.pszText ) )
  1002. {
  1003. try
  1004. {
  1005. pli->Pci()->Rename(pDispInfo->item.pszText);
  1006. *pResult = TRUE;
  1007. } // try
  1008. catch (CException * pe)
  1009. {
  1010. pe->ReportError();
  1011. pe->Delete();
  1012. *pResult = FALSE;
  1013. } // catch: CException
  1014. } // if: name is valid
  1015. else
  1016. {
  1017. *pResult = FALSE;
  1018. }
  1019. } // if: the edit wasn't cancelled
  1020. else
  1021. {
  1022. Trace(g_tagListView, _T("Ending edit of item '%s' (Not Saving)"), pli->Pci()->StrName());
  1023. *pResult = TRUE;
  1024. } // else: edit was cancelled
  1025. m_pliBeingEdited = NULL;
  1026. m_bShiftPressed = FALSE;
  1027. m_bControlPressed = FALSE;
  1028. m_bAltPressed = FALSE;
  1029. } //*** CClusterListView::OnEndLabelEdit()
  1030. /////////////////////////////////////////////////////////////////////////////
  1031. //++
  1032. //
  1033. // CClusterListView::OnBeginDrag
  1034. //
  1035. // Routine Description:
  1036. // Handler method for the LVN_BEGINDRAG and LVN_BEGINRDRAG messages.
  1037. //
  1038. // Arguments:
  1039. // pNMHDR Notification message structure.
  1040. // pResult Place in which to return the result.
  1041. //
  1042. // Return Value:
  1043. // None.
  1044. //
  1045. //--
  1046. /////////////////////////////////////////////////////////////////////////////
  1047. void CClusterListView::OnBeginDrag(NMHDR * pNMHDR, LRESULT * pResult)
  1048. {
  1049. NM_LISTVIEW * pNMListView = (NM_LISTVIEW *) pNMHDR;
  1050. CListCtrl & rlc = GetListCtrl();
  1051. CPoint ptAction;
  1052. CClusterItem * pci = NULL;
  1053. CImageList * pimagelist;
  1054. ASSERT_VALID(Pframe());
  1055. // Get the item being dragged.
  1056. {
  1057. int ili;
  1058. CListItem * pli;
  1059. // Get the item being dragged.
  1060. ili = pNMListView->iItem;
  1061. pli = (CListItem *) rlc.GetItemData(ili);
  1062. ASSERT_VALID(pli);
  1063. ASSERT_KINDOF(CListItem, pli);
  1064. ASSERT_VALID(pli->Pci());
  1065. // If the item can not be dragged, abort the operation.
  1066. if (!pli->Pci()->BCanBeDragged())
  1067. return;
  1068. // Deselect the item being dragged.
  1069. rlc.SetItemState(ili, 0, LVIS_SELECTED);
  1070. // Save info for later.
  1071. m_iliDrag = ili;
  1072. m_pliDrag = pli;
  1073. m_iliDrop = -1;
  1074. pci = pli->Pci();
  1075. } // Get the item being dragged
  1076. // Create the image list and let the frame window initialize the drag operation.
  1077. {
  1078. CPoint ptImage;
  1079. CPoint ptFrameItem;
  1080. CPoint ptHotSpot;
  1081. pimagelist = rlc.CreateDragImage(m_iliDrag, &ptImage);
  1082. ASSERT(pimagelist != NULL);
  1083. ptFrameItem = pNMListView->ptAction;
  1084. Pframe()->ScreenToClient(&ptFrameItem);
  1085. // Calculate the hot spot point.
  1086. {
  1087. long lStyle = rlc.GetStyle() & LVS_TYPEMASK;
  1088. switch (lStyle)
  1089. {
  1090. case LVS_REPORT:
  1091. case LVS_LIST:
  1092. case LVS_SMALLICON:
  1093. ptHotSpot.x = 0;
  1094. ptHotSpot.y = -16;
  1095. break;
  1096. case LVS_ICON:
  1097. ptHotSpot.x = 8;
  1098. ptHotSpot.y = 8;
  1099. break;
  1100. } // switch: lStyle
  1101. } // Calculate the hot spot point
  1102. Trace(g_tagListDrag, _T("OnBeginDrag() - Dragging '%s' at (%d,%d)"), m_pliDrag->StrName(), ptFrameItem.x, ptFrameItem.y);
  1103. Pframe()->BeginDrag(pimagelist, pci, ptFrameItem, ptHotSpot);
  1104. pimagelist->SetDragCursorImage(0, CPoint(0, 0)); // define the hot spot for the new cursor image
  1105. } // Create the image list and let the frame window initialize the drag operation
  1106. *pResult = 0;
  1107. } //*** CClusterListView::OnBeginDrag(pNMHDR, pResult)
  1108. /////////////////////////////////////////////////////////////////////////////
  1109. //++
  1110. //
  1111. // CClusterListView::OnMouseMoveForDrag
  1112. //
  1113. // Routine Description:
  1114. // Handler method for the WM_MOUSEMOVE message during a drag operation.
  1115. // This function is only responsible for providing view-specific
  1116. // functionality, such as selecting the drop target if it is valid.
  1117. //
  1118. // Arguments:
  1119. // nFlags Indicates whether various virtual keys are down.
  1120. // point Specifies the x- and y-coordinate of the cursor in frame
  1121. // coordinates.
  1122. // pwndDrop Specifies the window under the cursor.
  1123. //
  1124. // Return Value:
  1125. // None.
  1126. //
  1127. //--
  1128. /////////////////////////////////////////////////////////////////////////////
  1129. void CClusterListView::OnMouseMoveForDrag(
  1130. IN UINT nFlags,
  1131. IN OUT CPoint point,
  1132. IN const CWnd * pwndDrop
  1133. )
  1134. {
  1135. ASSERT(BDragging());
  1136. ASSERT_VALID(Pframe());
  1137. // If we are dragging, select the drop target.
  1138. if (BDragging())
  1139. {
  1140. int ili;
  1141. UINT uFlags;
  1142. CPoint ptView;
  1143. CListCtrl & rlc = GetListCtrl();
  1144. // Convert the point to view coordinates.
  1145. ptView = point;
  1146. Pframe()->ClientToScreen(&ptView);
  1147. rlc.ScreenToClient(&ptView);
  1148. // If this window is the drop target, find the item under the cursor.
  1149. if (pwndDrop == &rlc)
  1150. {
  1151. // If we are over a list item, highlight it.
  1152. ili = rlc.HitTest(ptView, &uFlags);
  1153. if (ili != -1)
  1154. {
  1155. CListItem * pli;
  1156. // Get the item to be highlight.
  1157. pli = (CListItem *) rlc.GetItemData(ili);
  1158. ASSERT_VALID(pli);
  1159. ASSERT_KINDOF(CListItem, pli);
  1160. ASSERT_VALID(pli->Pci());
  1161. // If this is not a drop target, change the cursor.
  1162. if (pli->Pci()->BCanBeDropTarget(Pframe()->PciDrag()))
  1163. Pframe()->ChangeDragCursor(IDC_ARROW);
  1164. else
  1165. Pframe()->ChangeDragCursor(IDC_NO);
  1166. } // if: over a list item
  1167. } // if: this window is the drop target
  1168. else
  1169. ili = -1;
  1170. // If the drop target is or was in this view, update the view.
  1171. if ((ili != -1) || (m_iliDrop != -1))
  1172. {
  1173. // Unlock window updates.
  1174. VERIFY(Pimagelist()->DragShowNolock(FALSE /*bShow*/));
  1175. // Turn off highlight for the previous drop target.
  1176. if (m_iliDrop != -1)
  1177. {
  1178. VERIFY(rlc.SetItemState(m_iliDrop, 0, LVIS_DROPHILITED));
  1179. VERIFY(rlc.RedrawItems(m_iliDrop, m_iliDrop));
  1180. } // if: there was a previous drop target
  1181. // Highlight the new drop target.
  1182. if (ili != -1)
  1183. {
  1184. VERIFY(rlc.SetItemState(ili, LVIS_DROPHILITED, LVIS_DROPHILITED));
  1185. VERIFY(rlc.RedrawItems(ili, ili));
  1186. } // if: over an item
  1187. m_iliDrop = ili;
  1188. rlc.UpdateWindow();
  1189. VERIFY(Pimagelist()->DragShowNolock(TRUE /*bShow*/));
  1190. } // if: new or old drop target
  1191. } // if: list item is being dragged
  1192. } //*** CClusterListView::OnMouseMoveForDrag()
  1193. /////////////////////////////////////////////////////////////////////////////
  1194. //++
  1195. //
  1196. // CClusterListView::OnButtonUpForDrag
  1197. //
  1198. // Routine Description:
  1199. // Called to handle a button up event during drag and drop.
  1200. //
  1201. // Arguments:
  1202. // nFlags Indicates whether various virtual keys are down.
  1203. // point Specifies the x- and y-coordinate of the cursor.
  1204. //
  1205. // Return Value:
  1206. // None.
  1207. //
  1208. //--
  1209. /////////////////////////////////////////////////////////////////////////////
  1210. void CClusterListView::OnButtonUpForDrag(IN UINT nFlags, IN CPoint point)
  1211. {
  1212. ASSERT(BDragging());
  1213. ASSERT_VALID(Pframe());
  1214. ASSERT_VALID(Pframe()->PciDrag());
  1215. // If we are dragging, process the drop.
  1216. if (BDragging())
  1217. {
  1218. int ili;
  1219. UINT flags;
  1220. CPoint ptView;
  1221. CListCtrl & rlc = GetListCtrl();
  1222. Trace(g_tagListDrag, _T("OnButtonUpForDrag()"));
  1223. // Convert the point to view coordinates.
  1224. ptView = point;
  1225. Pframe()->ClientToScreen(&ptView);
  1226. rlc.ScreenToClient(&ptView);
  1227. // If we are over a tree item, drop the item being dragged.
  1228. ili = rlc.HitTest(ptView, &flags);
  1229. if (ili != -1)
  1230. {
  1231. CListItem * pliDropTarget;
  1232. // Get the item to drop on.
  1233. pliDropTarget = (CListItem *) rlc.GetItemData(ili);
  1234. ASSERT_VALID(pliDropTarget);
  1235. ASSERT_KINDOF(CListItem, pliDropTarget);
  1236. ASSERT_VALID(pliDropTarget->Pci());
  1237. if (pliDropTarget->Pci() != Pframe()->PciDrag())
  1238. pliDropTarget->Pci()->DropItem(Pframe()->PciDrag());
  1239. } // if: over a tree item
  1240. } // if: tree item is being dragged
  1241. } //*** CClusterListView::OnButtonUpForDrag()
  1242. /////////////////////////////////////////////////////////////////////////////
  1243. //++
  1244. //
  1245. // CClusterListView::BeginDrag
  1246. //
  1247. // Routine Description:
  1248. // Called by the frame to begin a drag operation.
  1249. //
  1250. // Arguments:
  1251. // None.
  1252. //
  1253. // Return Value:
  1254. // None.
  1255. //
  1256. //--
  1257. /////////////////////////////////////////////////////////////////////////////
  1258. void CClusterListView::BeginDrag(void)
  1259. {
  1260. Trace(g_tagListDrag, _T("BeginDrag()"));
  1261. } //*** CClusterListView::BeginDrag()
  1262. /////////////////////////////////////////////////////////////////////////////
  1263. //++
  1264. //
  1265. // CClusterListView::EndDrag
  1266. //
  1267. // Routine Description:
  1268. // Called by the frame to end a drag operation.
  1269. //
  1270. // Arguments:
  1271. // None.
  1272. //
  1273. // Return Value:
  1274. // None.
  1275. //
  1276. //--
  1277. /////////////////////////////////////////////////////////////////////////////
  1278. void CClusterListView::EndDrag(void)
  1279. {
  1280. // Clear and reset highlights. The second one can fail, since the item
  1281. // could be removed from the list by this time.
  1282. if (m_iliDrop != -1)
  1283. VERIFY(GetListCtrl().SetItemState(m_iliDrop, 0, LVIS_DROPHILITED));
  1284. if (m_iliDrag != -1)
  1285. GetListCtrl().SetItemState(m_iliDrag, LVIS_SELECTED, LVIS_SELECTED);
  1286. m_iliDrag = -1;
  1287. m_pliDrag = NULL;
  1288. m_iliDrop = -1;
  1289. Trace(g_tagListDrag, _T("EndDrag()"));
  1290. } //*** CClusterListView::EndDrag()
  1291. /////////////////////////////////////////////////////////////////////////////
  1292. //++
  1293. //
  1294. // CClusterListView::PreTranslateMessage
  1295. //
  1296. // Routine Description:
  1297. // Translate window messages before they are dispatched.
  1298. // This is necessary for handling keystrokes properly while editing
  1299. // the label on an item.
  1300. //
  1301. // Arguments:
  1302. // pMsg Points to a MSG structure that contains the message to process.
  1303. //
  1304. // Return Value:
  1305. // TRUE Message was handled.
  1306. // FALSE Message was not handled.
  1307. //
  1308. //--
  1309. /////////////////////////////////////////////////////////////////////////////
  1310. BOOL CClusterListView::PreTranslateMessage(MSG * pMsg)
  1311. {
  1312. BOOL bForward = FALSE;
  1313. if (m_pliBeingEdited != NULL)
  1314. {
  1315. CEdit * pedit = GetListCtrl().GetEditControl();
  1316. ASSERT(pedit != NULL);
  1317. if (pMsg->message == WM_KEYDOWN)
  1318. {
  1319. if (pMsg->wParam == VK_SHIFT)
  1320. m_bShiftPressed = TRUE;
  1321. else if (pMsg->wParam == VK_CONTROL)
  1322. {
  1323. ::CopyMemory(&m_msgControl, pMsg, sizeof(m_msgControl));
  1324. m_bControlPressed = TRUE;
  1325. } // else if: control key pressed
  1326. else if ((pMsg->wParam == VK_RETURN)
  1327. || (pMsg->wParam == VK_ESCAPE)
  1328. || (pMsg->wParam == VK_INSERT)
  1329. || (pMsg->wParam == VK_DELETE)
  1330. || (pMsg->wParam == VK_F1)
  1331. || (pMsg->wParam == VK_F5)
  1332. || (pMsg->wParam == VK_F6)
  1333. )
  1334. {
  1335. Trace(g_tagListView, _T("PreTranslateMessage() - Forwarding WM_KEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1336. bForward = TRUE;
  1337. if (m_bControlPressed)
  1338. {
  1339. if (pMsg->wParam == VK_RETURN)
  1340. pedit->SendMessage(WM_KEYUP, m_msgControl.wParam, m_msgControl.lParam);
  1341. } // if: control key pressed
  1342. } // else if: editing key pressed
  1343. else if ((pMsg->wParam == VK_TAB)
  1344. || (m_bControlPressed
  1345. && (_T('A') <= pMsg->wParam) && (pMsg->wParam <= _T('Y'))
  1346. && (pMsg->wParam != _T('C'))
  1347. && (pMsg->wParam != _T('H'))
  1348. && (pMsg->wParam != _T('M'))
  1349. && (pMsg->wParam != _T('V'))
  1350. && (pMsg->wParam != _T('X'))
  1351. )
  1352. )
  1353. {
  1354. Trace(g_tagListView, _T("PreTranslateMessage() - Ignoring WM_KEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1355. MessageBeep(MB_ICONEXCLAMATION);
  1356. return TRUE;
  1357. } // else if: key pressed that should be ignored
  1358. #ifdef NEVER
  1359. else
  1360. {
  1361. Trace(g_tagListView, _T("PreTranslateMessage() - Not forwarding WM_KEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1362. } // else: not processing key
  1363. #endif
  1364. } // if: key pressed while editing label
  1365. else if (pMsg->message == WM_SYSKEYDOWN)
  1366. {
  1367. if (pMsg->wParam == VK_MENU)
  1368. m_bAltPressed = TRUE;
  1369. else if ((pMsg->wParam == VK_RETURN)
  1370. )
  1371. {
  1372. Trace(g_tagListView, _T("PreTranslateMessage() - Forwarding WM_SYSKEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1373. bForward = TRUE;
  1374. } // else if: editing key pressed
  1375. #ifdef NEVER
  1376. else
  1377. {
  1378. Trace(g_tagListView, _T("PreTranslateMessage() - Not forwarding WM_SYSKEYDOWN - %d '%c', lparam = %08.8x"), pMsg->wParam, pMsg->wParam, pMsg->lParam);
  1379. } // else: not processing key
  1380. #endif
  1381. } // else if: system key pressed while editing label
  1382. if (bForward)
  1383. {
  1384. pedit->SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
  1385. return TRUE;
  1386. } // if: forwarding the message
  1387. else if (pMsg->message == WM_KEYUP)
  1388. {
  1389. if (pMsg->wParam == VK_SHIFT)
  1390. m_bShiftPressed = FALSE;
  1391. else if (pMsg->wParam == VK_CONTROL)
  1392. m_bControlPressed = FALSE;
  1393. } // else if: key up
  1394. else if (pMsg->message == WM_SYSKEYUP)
  1395. {
  1396. if (pMsg->wParam == VK_MENU)
  1397. m_bAltPressed = FALSE;
  1398. } // else if: system key up
  1399. } // if: editing a label
  1400. return CListView::PreTranslateMessage(pMsg);
  1401. } //*** CClusterListView::PreTranslateMessage()
  1402. /////////////////////////////////////////////////////////////////////////////
  1403. //++
  1404. //
  1405. // CClusterListView::OnCmdRename
  1406. //
  1407. // Routine Description:
  1408. // Processes the ID_FILE_RENAME menu command.
  1409. //
  1410. // Arguments:
  1411. // None.
  1412. //
  1413. // Return Value:
  1414. // None.
  1415. //
  1416. //--
  1417. /////////////////////////////////////////////////////////////////////////////
  1418. void CClusterListView::OnCmdRename(void)
  1419. {
  1420. CListItem * pliFocused = PliFocused();
  1421. // If an item has focus, begin label editing
  1422. if (pliFocused != NULL)
  1423. {
  1424. ASSERT_VALID(pliFocused);
  1425. pliFocused->EditLabel(this);
  1426. } // if: an item has the focus
  1427. } //*** CClusterListView::OnCmdRename()
  1428. /////////////////////////////////////////////////////////////////////////////
  1429. //++
  1430. //
  1431. // CClusterListView::SetView
  1432. //
  1433. // Routine Description:
  1434. // Set the current view of the list view control.
  1435. //
  1436. // Arguments:
  1437. // dwView [IN] List view to set.
  1438. //
  1439. // Return Value:
  1440. // None.
  1441. //
  1442. //--
  1443. /////////////////////////////////////////////////////////////////////////////
  1444. void CClusterListView::SetView(IN DWORD dwView)
  1445. {
  1446. // Get the current window style.
  1447. DWORD dwStyle = GetWindowLong(GetListCtrl().m_hWnd, GWL_STYLE);
  1448. // Only set the window style if the view bits have changed.
  1449. if ((dwStyle & LVS_TYPEMASK) != dwView)
  1450. {
  1451. // Save the column information before switching out of report view.
  1452. if ((dwStyle & LVS_REPORT) && (PtiParent() != NULL))
  1453. SaveColumns();
  1454. // Set the new view.
  1455. SetWindowLong(GetListCtrl().m_hWnd, GWL_STYLE, (dwStyle & ~LVS_TYPEMASK) | dwView);
  1456. } // if: view has changed
  1457. } //*** CClusterListView::SetView()
  1458. /////////////////////////////////////////////////////////////////////////////
  1459. //++
  1460. //
  1461. // CClusterListView::OnKeyDown
  1462. //
  1463. // Routine Description:
  1464. // Handler method for the LVN_KEYDOWN message.
  1465. //
  1466. // Arguments:
  1467. // pNMHDR Notification message structure.
  1468. // pResult Place in which to return the result.
  1469. //
  1470. // Return Value:
  1471. // None.
  1472. //
  1473. //--
  1474. /////////////////////////////////////////////////////////////////////////////
  1475. void CClusterListView::OnKeyDown(NMHDR * pNMHDR, LRESULT * pResult)
  1476. {
  1477. LV_KEYDOWN * pLVKeyDown = (LV_KEYDOWN *) pNMHDR;
  1478. if (BDragging() && (pLVKeyDown->wVKey == VK_ESCAPE))
  1479. Pframe()->AbortDrag();
  1480. *pResult = 0;
  1481. } //*** CClusterListView::OnKeyDown()