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.

902 lines
26 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: statsdlg.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // StatsDlg.cpp : implementation file
  11. //
  12. #include "stdafx.h"
  13. #include "StatsDlg.h"
  14. #include "coldlg.h"
  15. #include "modeless.h" // ModelessThread
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. BEGIN_MESSAGE_MAP(CStatsListCtrl, CListCtrl)
  22. //{{AFX_MSG_MAP(CStatsListCtrl)
  23. ON_WM_KEYDOWN()
  24. //}}AFX_MSG_MAP
  25. END_MESSAGE_MAP()
  26. void CStatsListCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  27. {
  28. BOOL fControlDown;
  29. BOOL fShiftDown;
  30. fControlDown = (GetKeyState(VK_CONTROL) < 0);
  31. fShiftDown = (GetKeyState(VK_SHIFT) < 0);
  32. switch(nChar)
  33. {
  34. case 'c':
  35. case 'C':
  36. case VK_INSERT:
  37. if (fControlDown)
  38. CopyToClipboard();
  39. break;
  40. }
  41. CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
  42. }
  43. void CStatsListCtrl::CopyToClipboard()
  44. {
  45. CString strText, strLine, strData;
  46. int nCount = GetItemCount();
  47. int nColumns = 0;
  48. TCHAR szBuffer[256];
  49. LV_COLUMN ColumnInfo = {0};
  50. ColumnInfo.mask = LVCF_TEXT;
  51. ColumnInfo.pszText = szBuffer;
  52. ColumnInfo.cchTextMax = sizeof(szBuffer);
  53. // build up the column info
  54. while (GetColumn(nColumns, &ColumnInfo))
  55. {
  56. if (!strLine.IsEmpty())
  57. strLine += _T(",");
  58. strLine += ColumnInfo.pszText;
  59. nColumns++;
  60. }
  61. strLine += _T("\r\n");
  62. strData += strLine;
  63. strLine.Empty();
  64. // now get the other data
  65. for (int i = 0; i < nCount; i++)
  66. {
  67. for (int j = 0; j < nColumns; j++)
  68. {
  69. if (!strLine.IsEmpty())
  70. strLine += _T(",");
  71. strText = GetItemText(i, j);
  72. strLine += strText;
  73. }
  74. strLine += _T("\r\n");
  75. strData += strLine;
  76. strLine.Empty();
  77. }
  78. int nLength = strData.GetLength() + 1;
  79. nLength *= sizeof(TCHAR);
  80. HGLOBAL hMem = GlobalAlloc(GPTR, nLength);
  81. if (hMem)
  82. {
  83. memcpy (hMem, strData, nLength);
  84. if (!OpenClipboard())
  85. {
  86. GlobalFree(hMem);
  87. return;
  88. }
  89. EmptyClipboard();
  90. SetClipboardData(CF_UNICODETEXT, hMem);
  91. CloseClipboard();
  92. }
  93. }
  94. /*!--------------------------------------------------------------------------
  95. StatsDialog::StatsDialog
  96. -
  97. Author: KennT
  98. ---------------------------------------------------------------------------*/
  99. StatsDialog::StatsDialog(DWORD dwOptions) :
  100. m_dwOptions(dwOptions),
  101. m_ulId(0),
  102. m_pConfig(NULL),
  103. m_bAfterInitDialog(FALSE)
  104. {
  105. m_sizeMinimum.cx = m_sizeMinimum.cy = 0;
  106. m_hEventThreadKilled = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  107. Assert(m_hEventThreadKilled);
  108. // Initialize the array of buttons
  109. ::ZeroMemory(m_rgBtn, sizeof(m_rgBtn));
  110. m_rgBtn[INDEX_CLOSE].m_ulId = IDCANCEL;
  111. m_rgBtn[INDEX_REFRESH].m_ulId = IDC_STATSDLG_BTN_REFRESH;
  112. m_rgBtn[INDEX_SELECT].m_ulId = IDC_STATSDLG_BTN_SELECT_COLUMNS;
  113. m_rgBtn[INDEX_CLEAR].m_ulId = IDC_STATSDLG_BTN_CLEAR;
  114. // Bug 134785 - create the ability to default to an ascending
  115. // rather than a descending sort.
  116. m_fSortDirection = !((dwOptions & STATSDLG_DEFAULTSORT_ASCENDING) != 0);
  117. m_fDefaultSortDirection = m_fSortDirection;
  118. // Multiply text header width with 2 for width of columns
  119. m_ColWidthMultiple = 2;
  120. m_ColWidthAdder = 0;
  121. }
  122. /*!--------------------------------------------------------------------------
  123. StatsDialog::~StatsDialog
  124. -
  125. Author: KennT
  126. ---------------------------------------------------------------------------*/
  127. StatsDialog::~StatsDialog()
  128. {
  129. if (m_hEventThreadKilled)
  130. ::CloseHandle(m_hEventThreadKilled);
  131. m_hEventThreadKilled = 0;
  132. }
  133. /*!--------------------------------------------------------------------------
  134. StatsDialog::DoDataExchange
  135. -
  136. Author: KennT
  137. ---------------------------------------------------------------------------*/
  138. void StatsDialog::DoDataExchange(CDataExchange* pDX)
  139. {
  140. CBaseDialog::DoDataExchange(pDX);
  141. //{{AFX_DATA_MAP(StatsDialog)
  142. // NOTE: the ClassWizard will add DDX and DDV calls here
  143. DDX_Control(pDX, IDC_STATSDLG_LIST, m_listCtrl);
  144. //}}AFX_DATA_MAP
  145. }
  146. BEGIN_MESSAGE_MAP(StatsDialog, CBaseDialog)
  147. //{{AFX_MSG_MAP(StatsDialog)
  148. ON_COMMAND(IDC_STATSDLG_BTN_REFRESH, OnRefresh)
  149. ON_COMMAND(IDC_STATSDLG_BTN_SELECT_COLUMNS, OnSelectColumns)
  150. ON_WM_MOVE()
  151. ON_WM_SIZE()
  152. ON_WM_GETMINMAXINFO()
  153. ON_WM_CONTEXTMENU()
  154. ON_NOTIFY(LVN_COLUMNCLICK, IDC_STATSDLG_LIST, OnNotifyListControlClick)
  155. //}}AFX_MSG_MAP
  156. END_MESSAGE_MAP()
  157. /////////////////////////////////////////////////////////////////////////////
  158. // StatsDialog message handlers
  159. /*!--------------------------------------------------------------------------
  160. StatsDialog::SetColumnInfo
  161. -
  162. Author: KennT
  163. ---------------------------------------------------------------------------*/
  164. HRESULT StatsDialog::SetColumnInfo(const ContainerColumnInfo *pColumnInfo, UINT cColumnInfo)
  165. {
  166. if (m_pConfig)
  167. {
  168. m_pConfig->InitViewInfo(m_ulId, TRUE, cColumnInfo, m_fDefaultSortDirection, pColumnInfo);
  169. }
  170. else
  171. {
  172. m_viewInfo.InitViewInfo(cColumnInfo, TRUE, m_fDefaultSortDirection, pColumnInfo);
  173. }
  174. return hrOK;
  175. }
  176. /*!--------------------------------------------------------------------------
  177. StatsDialog::MapColumnToSubitem
  178. -
  179. Author: KennT
  180. ---------------------------------------------------------------------------*/
  181. int StatsDialog::MapColumnToSubitem(UINT nColumnId)
  182. {
  183. if (m_pConfig)
  184. return m_pConfig->MapColumnToSubitem(m_ulId, nColumnId);
  185. else
  186. return m_viewInfo.MapColumnToSubitem(nColumnId);
  187. }
  188. /*!--------------------------------------------------------------------------
  189. StatsDialog::MapSubitemToColumn
  190. -
  191. Author: KennT
  192. ---------------------------------------------------------------------------*/
  193. int StatsDialog::MapSubitemToColumn(UINT nSubitemId)
  194. {
  195. if (m_pConfig)
  196. return m_pConfig->MapSubitemToColumn(m_ulId, nSubitemId);
  197. else
  198. return m_viewInfo.MapSubitemToColumn(nSubitemId);
  199. }
  200. /*!--------------------------------------------------------------------------
  201. StatsDialog::IsSubitemVisible
  202. -
  203. Author: KennT
  204. ---------------------------------------------------------------------------*/
  205. BOOL StatsDialog::IsSubitemVisible(UINT nSubitemId)
  206. {
  207. if (m_pConfig)
  208. return m_pConfig->IsSubitemVisible(m_ulId, nSubitemId);
  209. else
  210. return m_viewInfo.IsSubitemVisible(nSubitemId);
  211. }
  212. /*!--------------------------------------------------------------------------
  213. StatsDialog::RefreshData
  214. -
  215. Author: KennT
  216. ---------------------------------------------------------------------------*/
  217. HRESULT StatsDialog::RefreshData(BOOL fGrabNewData)
  218. {
  219. return hrOK;
  220. }
  221. /*!--------------------------------------------------------------------------
  222. StatsDialog::OnInitDialog
  223. -
  224. Author: KennT
  225. ---------------------------------------------------------------------------*/
  226. BOOL StatsDialog::OnInitDialog()
  227. {
  228. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  229. RECT rcWnd, rcBtn;
  230. CBaseDialog::OnInitDialog();
  231. m_bAfterInitDialog = TRUE;
  232. // If this is the first time, get the location of the buttons and
  233. // list control relative to the edge of the screen
  234. if (m_sizeMinimum.cx == 0)
  235. {
  236. ::GetWindowRect(GetSafeHwnd(), &rcWnd);
  237. // m_sizeMinimum.cx = rcWnd.right - rcWnd.left;
  238. // m_sizeMinimum.cy = rcWnd.bottom - rcWnd.top;
  239. m_sizeMinimum.cx = 100;
  240. m_sizeMinimum.cy = 100;
  241. ::GetClientRect(GetSafeHwnd(), &rcWnd);
  242. // what are the button locations?
  243. for (int i=0; i<INDEX_COUNT; i++)
  244. {
  245. ::GetWindowRect(GetDlgItem(m_rgBtn[i].m_ulId)->GetSafeHwnd(),
  246. &rcBtn);
  247. ScreenToClient(&rcBtn);
  248. m_rgBtn[i].m_rc.left = rcWnd.right - rcBtn.left;
  249. m_rgBtn[i].m_rc.right = rcWnd.right - rcBtn.right;
  250. m_rgBtn[i].m_rc.top = rcWnd.bottom - rcBtn.top;
  251. m_rgBtn[i].m_rc.bottom = rcWnd.bottom - rcBtn.bottom;
  252. }
  253. // what is the list control location?
  254. // The list control top, left is locked in position
  255. ::GetWindowRect(GetDlgItem(IDC_STATSDLG_LIST)->GetSafeHwnd(), &rcBtn);
  256. ScreenToClient(&rcBtn);
  257. m_rcList.left = rcBtn.left;
  258. m_rcList.top = rcBtn.top;
  259. // The bottom, right corner follows the expansion
  260. m_rcList.right = rcWnd.right - rcBtn.right;
  261. m_rcList.bottom = rcWnd.bottom - rcBtn.bottom;
  262. }
  263. // If we have a preferred position and size do that
  264. if (m_pConfig)
  265. {
  266. m_pConfig->GetStatsWindowRect(m_ulId, &m_rcPosition);
  267. m_fSortDirection = m_pConfig->GetSortDirection(m_ulId);
  268. }
  269. if (m_pConfig && (m_rcPosition.top != m_rcPosition.bottom))
  270. {
  271. MoveWindow(m_rcPosition.left, m_rcPosition.top,
  272. m_rcPosition.right - m_rcPosition.left,
  273. m_rcPosition.bottom - m_rcPosition.top);
  274. }
  275. if (m_dwOptions & STATSDLG_FULLWINDOW)
  276. {
  277. RECT rcClient;
  278. // Resize the list control if needed
  279. GetClientRect(&rcClient);
  280. OnSize(SIZE_MAXIMIZED, rcClient.right - rcClient.left,
  281. rcClient.bottom - rcClient.top);
  282. // Disable the buttons also
  283. for (int i=0; i<INDEX_COUNT; i++)
  284. {
  285. GetDlgItem(m_rgBtn[i].m_ulId)->ShowWindow(SW_HIDE);
  286. if (i != INDEX_CLOSE)
  287. GetDlgItem(m_rgBtn[i].m_ulId)->EnableWindow(FALSE);
  288. }
  289. }
  290. // If we do not have the select columns then we hide and disable
  291. // the select columns button.
  292. if ((m_dwOptions & STATSDLG_SELECT_COLUMNS) == 0)
  293. {
  294. GetDlgItem(m_rgBtn[INDEX_SELECT].m_ulId)->ShowWindow(SW_HIDE);
  295. GetDlgItem(m_rgBtn[INDEX_SELECT].m_ulId)->EnableWindow(FALSE);
  296. }
  297. // If we do not have the clear button then we hide and disable
  298. // the clear button.
  299. if ((m_dwOptions & STATSDLG_CLEAR) == 0)
  300. {
  301. GetDlgItem(m_rgBtn[INDEX_CLEAR].m_ulId)->ShowWindow(SW_HIDE);
  302. GetDlgItem(m_rgBtn[INDEX_CLEAR].m_ulId)->EnableWindow(FALSE);
  303. }
  304. ListView_SetExtendedListViewStyle(GetDlgItem(IDC_STATSDLG_LIST)->GetSafeHwnd(), LVS_EX_FULLROWSELECT);
  305. // Now initialize the headers
  306. LoadHeaders();
  307. RefreshData(TRUE);
  308. if (m_pConfig)
  309. {
  310. Sort( m_pConfig->GetSortColumn(m_ulId) );
  311. }
  312. if ((m_dwOptions & STATSDLG_FULLWINDOW) == 0)
  313. {
  314. GetDlgItem(IDCANCEL)->SetFocus();
  315. return FALSE;
  316. }
  317. return TRUE;
  318. }
  319. /*!--------------------------------------------------------------------------
  320. StatsDialog::OnOK
  321. -
  322. Author: KennT
  323. ---------------------------------------------------------------------------*/
  324. void StatsDialog::OnOK()
  325. {
  326. }
  327. /*!--------------------------------------------------------------------------
  328. StatsDialog::OnCancel
  329. -
  330. Author: KennT
  331. ---------------------------------------------------------------------------*/
  332. void StatsDialog::OnCancel()
  333. {
  334. DeleteAllItems();
  335. DestroyWindow();
  336. // Explicitly kill this thread.
  337. AfxPostQuitMessage(0);
  338. }
  339. /*!--------------------------------------------------------------------------
  340. StatsDialog::PostNcDestroy
  341. -
  342. Author: KennT
  343. ---------------------------------------------------------------------------*/
  344. void StatsDialog::PostNcDestroy()
  345. {
  346. // Make sure that this is NULL since this is how we detect that
  347. // the dialog is showing
  348. m_hWnd = NULL;
  349. m_bAfterInitDialog = FALSE;
  350. }
  351. /*!--------------------------------------------------------------------------
  352. StatsDialog::PreCreateWindow
  353. -
  354. Author: KennT
  355. ---------------------------------------------------------------------------*/
  356. BOOL StatsDialog::PreCreateWindow(CREATESTRUCT& cs)
  357. {
  358. // Have to refresh the event
  359. Verify( ResetEvent(m_hEventThreadKilled) );
  360. return CBaseDialog::PreCreateWindow(cs);
  361. }
  362. /*!--------------------------------------------------------------------------
  363. StatsDialog::OnRefresh
  364. -
  365. Author: KennT
  366. ---------------------------------------------------------------------------*/
  367. void StatsDialog::OnRefresh()
  368. {
  369. if ((m_dwOptions & STATSDLG_VERTICAL) == 0)
  370. {
  371. DeleteAllItems();
  372. }
  373. RefreshData(TRUE);
  374. }
  375. /*!--------------------------------------------------------------------------
  376. StatsDialog::OnSelectColumns
  377. -
  378. Author: KennT
  379. ---------------------------------------------------------------------------*/
  380. void StatsDialog::OnSelectColumns()
  381. {
  382. // We should bring up the columns dialog
  383. ColumnDlg columnDlg(NULL);
  384. ColumnData *pColumnData;
  385. ULONG cColumns;
  386. ULONG cVisible;
  387. int i;
  388. DWORD dwWidth;
  389. if (m_pConfig)
  390. {
  391. cColumns = m_pConfig->GetColumnCount(m_ulId);
  392. cVisible = m_pConfig->GetVisibleColumns(m_ulId);
  393. }
  394. else
  395. {
  396. cColumns = m_viewInfo.GetColumnCount();
  397. cVisible = m_viewInfo.GetVisibleColumns();
  398. }
  399. pColumnData = (ColumnData *) alloca(sizeof(ColumnData) * cColumns);
  400. if (m_pConfig)
  401. m_pConfig->GetColumnData(m_ulId, cColumns, pColumnData);
  402. else
  403. m_viewInfo.GetColumnData(cColumns, pColumnData);
  404. // Save the column width information
  405. if ((m_dwOptions & STATSDLG_VERTICAL) == 0)
  406. {
  407. for (i=0; i<(int) cVisible; i++)
  408. {
  409. dwWidth = m_listCtrl.GetColumnWidth(i);
  410. if (m_pConfig)
  411. pColumnData[m_pConfig->MapColumnToSubitem(m_ulId, i)].m_dwWidth = dwWidth;
  412. else
  413. pColumnData[m_viewInfo.MapColumnToSubitem(i)].m_dwWidth = dwWidth;
  414. }
  415. }
  416. columnDlg.Init(m_pConfig ?
  417. m_pConfig->GetColumnInfo(m_ulId) :
  418. m_viewInfo.GetColumnInfo(),
  419. cColumns,
  420. pColumnData
  421. );
  422. if (columnDlg.DoModal() == IDOK)
  423. {
  424. if (m_dwOptions & STATSDLG_VERTICAL)
  425. {
  426. //$ HACK HACK
  427. // To save the column info for vertical columns we will save the
  428. // width data in the first two "columns"
  429. pColumnData[0].m_dwWidth = m_listCtrl.GetColumnWidth(0);
  430. pColumnData[1].m_dwWidth = m_listCtrl.GetColumnWidth(1);
  431. }
  432. // Set the information back in
  433. if (m_pConfig)
  434. m_pConfig->SetColumnData(m_ulId, cColumns, pColumnData);
  435. else
  436. m_viewInfo.SetColumnData(cColumns, pColumnData);
  437. // Clear out the data
  438. DeleteAllItems();
  439. // Remove all of the columns
  440. if (m_dwOptions & STATSDLG_VERTICAL)
  441. {
  442. m_listCtrl.DeleteColumn(1);
  443. m_listCtrl.DeleteColumn(0);
  444. }
  445. else
  446. {
  447. for (i=(int) cVisible; --i >= 0; )
  448. m_listCtrl.DeleteColumn(i);
  449. }
  450. // Readd all of the columns
  451. LoadHeaders();
  452. // Do a refresh
  453. RefreshData(FALSE);
  454. }
  455. }
  456. void StatsDialog::OnMove(int x, int y)
  457. {
  458. if (!m_bAfterInitDialog)
  459. return;
  460. GetWindowRect(&m_rcPosition);
  461. if (m_pConfig)
  462. m_pConfig->SetStatsWindowRect(m_ulId, m_rcPosition);
  463. }
  464. /*!--------------------------------------------------------------------------
  465. StatsDialog::OnSize
  466. -
  467. Author: KennT
  468. ---------------------------------------------------------------------------*/
  469. void StatsDialog::OnSize(UINT nType, int cx, int cy)
  470. {
  471. RECT rcWnd;
  472. RECT rcBtn;
  473. RECT rcDlg;
  474. if (nType == SIZE_MINIMIZED)
  475. return;
  476. if (m_dwOptions & STATSDLG_FULLWINDOW)
  477. {
  478. // If we're full window, resize the list control to fill
  479. // the entire client area
  480. ::SetWindowPos(::GetDlgItem(GetSafeHwnd(), IDC_STATSDLG_LIST), NULL,
  481. 0, 0, cx, cy, SWP_NOZORDER);
  482. }
  483. else if (m_sizeMinimum.cx)
  484. {
  485. ::GetClientRect(GetSafeHwnd(), &rcDlg);
  486. // reposition the buttons
  487. // The widths are caluclated opposite of the normal order
  488. // since the positions are relative to the right and bottom.
  489. for (int i=0; i<INDEX_COUNT; i++)
  490. {
  491. ::SetWindowPos(::GetDlgItem(GetSafeHwnd(), m_rgBtn[i].m_ulId),
  492. NULL,
  493. rcDlg.right - m_rgBtn[i].m_rc.left,
  494. rcDlg.bottom - m_rgBtn[i].m_rc.top,
  495. m_rgBtn[i].m_rc.left - m_rgBtn[i].m_rc.right,
  496. m_rgBtn[i].m_rc.top - m_rgBtn[i].m_rc.bottom,
  497. SWP_NOZORDER);
  498. }
  499. // resize the list control
  500. ::SetWindowPos(::GetDlgItem(GetSafeHwnd(), IDC_STATSDLG_LIST),
  501. NULL,
  502. m_rcList.left,
  503. m_rcList.top,
  504. rcDlg.right - m_rcList.right - m_rcList.left,
  505. rcDlg.bottom - m_rcList.bottom - m_rcList.top,
  506. SWP_NOZORDER);
  507. }
  508. if (m_bAfterInitDialog)
  509. {
  510. GetWindowRect(&m_rcPosition);
  511. if (m_pConfig)
  512. m_pConfig->SetStatsWindowRect(m_ulId, m_rcPosition);
  513. }
  514. }
  515. /*!--------------------------------------------------------------------------
  516. StatsDialog::OnGetMinMaxInfo
  517. -
  518. Author: KennT
  519. ---------------------------------------------------------------------------*/
  520. void StatsDialog::OnGetMinMaxInfo(MINMAXINFO *pMinMax)
  521. {
  522. pMinMax->ptMinTrackSize.x = m_sizeMinimum.cx;
  523. pMinMax->ptMinTrackSize.y = m_sizeMinimum.cy;
  524. }
  525. /*!--------------------------------------------------------------------------
  526. StatsDialog::LoadHeaders
  527. -
  528. Author: KennT
  529. ---------------------------------------------------------------------------*/
  530. void StatsDialog::LoadHeaders()
  531. {
  532. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  533. ULONG cVis;
  534. ULONG i, iPos;
  535. ULONG ulId;
  536. CString st;
  537. DWORD dwWidth;
  538. ColumnData rgColumnData[2]; // used for vertical format
  539. // Load those headers that we have data for
  540. // Go through the column data finding the headers that we have
  541. if (m_pConfig)
  542. cVis = m_pConfig->GetVisibleColumns(m_ulId);
  543. else
  544. cVis = m_viewInfo.GetVisibleColumns();
  545. if (m_dwOptions & STATSDLG_VERTICAL)
  546. {
  547. if (m_pConfig)
  548. m_pConfig->GetColumnData(m_ulId, 2, rgColumnData);
  549. else
  550. m_viewInfo.GetColumnData(2, rgColumnData);
  551. // For the vertical format, the data is on a column
  552. // Thus we add two columns and fill in the data for the
  553. // first column
  554. st.LoadString(IDS_STATSDLG_DESCRIPTION);
  555. dwWidth = rgColumnData[0].m_dwWidth;
  556. if (dwWidth == AUTO_WIDTH)
  557. {
  558. dwWidth = m_ColWidthAdder + static_cast<DWORD>(m_ColWidthMultiple*m_listCtrl.GetStringWidth((LPCTSTR) st));
  559. }
  560. m_listCtrl.InsertColumn(0, st, rgColumnData[0].fmt, dwWidth, 0);
  561. st.LoadString(IDS_STATSDLG_DETAILS);
  562. dwWidth = rgColumnData[1].m_dwWidth;
  563. if (dwWidth == AUTO_WIDTH)
  564. {
  565. dwWidth = m_ColWidthAdder + static_cast<DWORD>(m_ColWidthMultiple*m_listCtrl.GetStringWidth((LPCTSTR) st));
  566. }
  567. m_listCtrl.InsertColumn(1, st, rgColumnData[1].fmt, dwWidth, 1);
  568. // Now go through and add the rows for each of our "columns"
  569. for (i=0; i<cVis; i++)
  570. {
  571. // Now get the info for iPos
  572. if (m_pConfig)
  573. ulId = m_pConfig->GetStringId(m_ulId, i);
  574. else
  575. ulId = m_viewInfo.GetStringId(i);
  576. st.LoadString(ulId);
  577. Assert(st.GetLength());
  578. m_listCtrl.InsertItem(i, _T(""));
  579. m_listCtrl.SetItemText(i, 0, (LPCTSTR) st);
  580. }
  581. }
  582. else
  583. {
  584. // For the normal horizontal format, the data is on a row
  585. // so we need to add the various columnar data
  586. for (i=0; i<cVis; i++)
  587. {
  588. int fmt = LVCFMT_LEFT;
  589. iPos = MapColumnToSubitem(i);
  590. // Now get the info for iPos
  591. if (m_pConfig)
  592. ulId = m_pConfig->GetStringId(m_ulId, i);
  593. else
  594. ulId = m_viewInfo.GetStringId(i);
  595. st.LoadString(ulId);
  596. Assert(st.GetLength());
  597. if (m_pConfig)
  598. {
  599. dwWidth = m_pConfig->GetColumnWidth(m_ulId, i);
  600. m_pConfig->GetColumnData(m_ulId, i, 1, rgColumnData);
  601. fmt = rgColumnData[0].fmt;
  602. }
  603. else
  604. {
  605. dwWidth = m_viewInfo.GetColumnWidth(i);
  606. m_viewInfo.GetColumnData(i, 1, rgColumnData);
  607. fmt = rgColumnData[0].fmt;
  608. }
  609. if (dwWidth == AUTO_WIDTH)
  610. {
  611. dwWidth = m_ColWidthAdder + static_cast<DWORD>(m_ColWidthMultiple*m_listCtrl.GetStringWidth((LPCTSTR) st));
  612. }
  613. m_listCtrl.InsertColumn(i, st, fmt, dwWidth, iPos);
  614. }
  615. }
  616. }
  617. HRESULT StatsDialog::AddToContextMenu(CMenu* pMenu)
  618. {
  619. return S_OK;
  620. }
  621. /*!--------------------------------------------------------------------------
  622. StatsDialog::OnContextMenu
  623. -
  624. Author: KennT
  625. ---------------------------------------------------------------------------*/
  626. void StatsDialog::OnContextMenu(CWnd *pWnd, CPoint pos)
  627. {
  628. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  629. CMenu menu;
  630. CString st;
  631. if ((m_dwOptions & STATSDLG_CONTEXTMENU) == 0)
  632. return;
  633. if (pWnd->GetDlgCtrlID() != IDC_STATSDLG_LIST)
  634. return;
  635. // Bring up a context menu if we need to
  636. menu.CreatePopupMenu();
  637. st.LoadString(IDS_STATSDLG_MENU_REFRESH);
  638. menu.AppendMenu(MF_STRING, IDC_STATSDLG_BTN_REFRESH, st);
  639. if (m_dwOptions & STATSDLG_SELECT_COLUMNS)
  640. {
  641. st.LoadString(IDS_STATSDLG_MENU_SELECT);
  642. menu.AppendMenu(MF_STRING, IDC_STATSDLG_BTN_SELECT_COLUMNS, st);
  643. }
  644. //virtual override to add additional context menus
  645. AddToContextMenu(&menu);
  646. menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  647. pos.x,
  648. pos.y,
  649. this,
  650. NULL);
  651. }
  652. void StatsDialog::OnNotifyListControlClick(NMHDR *pNmHdr, LRESULT *pResult)
  653. {
  654. NM_LISTVIEW * pnmlv = reinterpret_cast<NM_LISTVIEW *>(pNmHdr);
  655. if (m_pConfig)
  656. m_pConfig->SetSortColumn(m_ulId, pnmlv->iSubItem);
  657. // Call through to the user to sort
  658. Sort(pnmlv->iSubItem);
  659. if (m_pConfig)
  660. m_pConfig->SetSortDirection(m_ulId, m_fSortDirection);
  661. }
  662. void StatsDialog::Sort(UINT nColumn)
  663. {
  664. // Default is to do nothing
  665. }
  666. void StatsDialog::PreDeleteAllItems()
  667. {
  668. }
  669. void StatsDialog::DeleteAllItems()
  670. {
  671. PreDeleteAllItems();
  672. m_listCtrl.DeleteAllItems();
  673. }
  674. void StatsDialog::PostRefresh()
  675. {
  676. if (GetSafeHwnd())
  677. PostMessage(WM_COMMAND, IDC_STATSDLG_BTN_REFRESH);
  678. }
  679. /*!--------------------------------------------------------------------------
  680. StatsDialog::SetColumnWidths
  681. Loops through all items and calculates the max width for columns
  682. in a listbox.
  683. Author: EricDav
  684. ---------------------------------------------------------------------------*/
  685. void StatsDialog::SetColumnWidths(UINT uNumColumns)
  686. {
  687. // Set the default column widths to the width of the widest column
  688. int * aColWidth = (int *) alloca(uNumColumns * sizeof(int));
  689. int nRow, nCol;
  690. CString strTemp;
  691. ZeroMemory(aColWidth, uNumColumns * sizeof(int));
  692. // for each item, loop through each column and calculate the max width
  693. for (nRow = 0; nRow < m_listCtrl.GetItemCount(); nRow++)
  694. {
  695. for (nCol = 0; nCol < (int) uNumColumns; nCol++)
  696. {
  697. strTemp = m_listCtrl.GetItemText(nRow, nCol);
  698. if (aColWidth[nCol] < m_listCtrl.GetStringWidth(strTemp))
  699. aColWidth[nCol] = m_listCtrl.GetStringWidth(strTemp);
  700. }
  701. }
  702. // now update the column widths based on what we calculated
  703. for (nCol = 0; nCol < (int) uNumColumns; nCol++)
  704. {
  705. // GetStringWidth doesn't seem to report the right thing,
  706. // so we have to add a fudge factor of 15.... oh well.
  707. m_listCtrl.SetColumnWidth(nCol, aColWidth[nCol] + 15);
  708. }
  709. }
  710. void StatsDialog::SetConfigInfo(ConfigStream *pConfig, ULONG ulId)
  711. {
  712. m_pConfig = pConfig;
  713. m_ulId = ulId;
  714. }
  715. void StatsDialog::SetPosition(RECT rc)
  716. {
  717. m_rcPosition = rc;
  718. }
  719. void StatsDialog::GetPosition(RECT *prc)
  720. {
  721. *prc = m_rcPosition;
  722. }
  723. void CreateNewStatisticsWindow(StatsDialog *pWndStats,
  724. HWND hWndParent,
  725. UINT nIDD)
  726. {
  727. ModelessThread * pMT;
  728. // If the dialog is still up, don't create a new one
  729. if (pWndStats->GetSafeHwnd())
  730. {
  731. ::SetActiveWindow(pWndStats->GetSafeHwnd());
  732. return;
  733. }
  734. pMT = new ModelessThread(hWndParent,
  735. nIDD,
  736. pWndStats->GetSignalEvent(),
  737. pWndStats);
  738. pMT->CreateThread();
  739. }
  740. void WaitForStatisticsWindow(StatsDialog *pWndStats)
  741. {
  742. if (pWndStats->GetSafeHwnd())
  743. {
  744. // Post a cancel to that window
  745. // Do an explicit post so that it executes on the other thread
  746. pWndStats->PostMessage(WM_COMMAND, IDCANCEL, 0);
  747. // Now we need to wait for the event to be signalled so that
  748. // its memory can be cleaned up
  749. WaitForSingleObject(pWndStats->GetSignalEvent(), INFINITE);
  750. }
  751. }