XTListBase.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:20k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTListCtrl.cpp : implementation of the CXTListCtrl class.
  2. //
  3. // This file is a part of the XTREME CONTROLS MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/XTPResourceManager.h"
  22. #include "Common/XTPColorManager.h"
  23. #include "Common/XTPWinThemeWrapper.h"
  24. #include "Common/XTPSystemHelpers.h"
  25. #include "Common/XTPDrawHelpers.h"
  26. #include "XTGlobal.h"
  27. #include "XTVC50Helpers.h"
  28. #include "XTHeaderCtrl.h"
  29. #include "XTListBase.h"
  30. #include "XTRegistryManager.h"
  31. #include "XTColorRef.h"
  32. #ifdef _DEBUG
  33. #define new DEBUG_NEW
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37. CXTListBase::CXTListBase()
  38. : m_bAutoFont(false)
  39. , m_bAutoSave(false)
  40. , m_bRowColor(false)
  41. , m_bListColor(false)
  42. , m_bSortColor(false)
  43. , m_bAscending(true)
  44. , m_bNoColSizing(false)
  45. , m_nMinColWidth(0)
  46. , m_nMaxColWidth(0)
  47. , m_nSortedCol(-1)
  48. , m_crListText((COLORREF)-1)
  49. , m_crListBack((COLORREF)-1)
  50. , m_crSortText((COLORREF)-1)
  51. , m_crSortBack((COLORREF)-1)
  52. {
  53. RefreshMetrics();
  54. }
  55. CXTListBase::~CXTListBase()
  56. {
  57. }
  58. void CXTListBase::RefreshMetrics()
  59. {
  60. // update column metrics.
  61. m_nMaxColWidth = ::GetSystemMetrics(SM_CXFULLSCREEN);
  62. CXTColorRef crSortBack(GetListBackColor());
  63. crSortBack.subtract(RGB(8, 8, 8));
  64. // set sort background and text colors
  65. m_crSortText = GetListTextColor();
  66. m_crSortBack = crSortBack;
  67. }
  68. CXTListBase::ROWCOLOR* CXTListBase::Lookup(int iRow)
  69. {
  70. if (m_arRowColor.GetCount() == 0)
  71. return NULL;
  72. for (POSITION pos = m_arRowColor.GetHeadPosition(); pos;)
  73. {
  74. ROWCOLOR& rowColor = m_arRowColor.GetNext(pos);
  75. if (rowColor.iRow == iRow)
  76. return &rowColor;
  77. }
  78. return NULL;
  79. }
  80. void CXTListBase::SetRowColor(int iRow, COLORREF crText, COLORREF crBack, BOOL bRedraw /*= TRUE*/)
  81. {
  82. ROWCOLOR* lpRowClr = Lookup(iRow);
  83. if (lpRowClr)
  84. {
  85. lpRowClr->crText = crText;
  86. lpRowClr->crBack = crBack;
  87. }
  88. else
  89. {
  90. // initialize row color struct.
  91. ROWCOLOR rowclr;
  92. rowclr.iRow = iRow;
  93. rowclr.crText = crText;
  94. rowclr.crBack = crBack;
  95. m_arRowColor.AddHead(rowclr);
  96. }
  97. if (!m_pListCtrl || !m_pListCtrl->GetSafeHwnd() || !bRedraw)
  98. return;
  99. // Redraw window if row is visible
  100. const int nTopIndex = m_pListCtrl->GetTopIndex();
  101. const int nBotIndex = nTopIndex + m_pListCtrl->GetCountPerPage();
  102. if (iRow >= nTopIndex && iRow <= nBotIndex)
  103. {
  104. m_pListCtrl->RedrawWindow();
  105. }
  106. }
  107. void CXTListBase::SetRowColor(ROWCOLOR* lpRowColor, BOOL bRedraw)
  108. {
  109. SetRowColor(lpRowColor->iRow, lpRowColor->crText, lpRowColor->crBack, bRedraw);
  110. }
  111. void CXTListBase::RemoveRowColors()
  112. {
  113. m_arRowColor.RemoveAll();
  114. }
  115. void CXTListBase::ImplAttach(CListCtrl* pListCtrl)
  116. {
  117. m_pListCtrl = (CListCtrl_Friendly *)pListCtrl;
  118. }
  119. bool CXTListBase::MoveRow(int nFrom, int nTo)
  120. {
  121. // Can't move to the same place, or from or to a negative index
  122. if ((nFrom == nTo) || (nFrom < 0) || (nTo < 0))
  123. {
  124. return false;
  125. }
  126. // First Copy the row to the new location
  127. int iRemove = CopyRow(nFrom, nTo);
  128. if (iRemove != -1)
  129. {
  130. return (m_pListCtrl->DeleteItem(iRemove) == TRUE);
  131. }
  132. return false;
  133. }
  134. int CXTListBase::CopyRow(int nFrom, int nTo)
  135. {
  136. // Can't move to the same place, or from or to a negative index
  137. if ((nFrom == nTo) || (nFrom < 0) || (nTo < 0))
  138. {
  139. return -1;
  140. }
  141. //Copy the row to the new index
  142. TCHAR szLabel[ 256 ];
  143. LV_ITEM lvi;
  144. ::ZeroMemory(&lvi, sizeof(LV_ITEM));
  145. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  146. lvi.pszText = szLabel;
  147. lvi.iItem = nFrom;
  148. lvi.cchTextMax = _countof(szLabel);
  149. m_pListCtrl->GetItem(&lvi);
  150. lvi.iItem = nTo;
  151. m_pListCtrl->InsertItem(&lvi);
  152. // If row has been inserted before original
  153. // increment the original
  154. if (nFrom > nTo)
  155. {
  156. nFrom++;
  157. }
  158. //Loop through subitems
  159. int i;
  160. for (i = 1; i < GetColumnCount(); i++)
  161. {
  162. CString strLabel = m_pListCtrl->GetItemText(nFrom, i);
  163. if (!strLabel.IsEmpty())
  164. {
  165. m_pListCtrl->SetItemText(
  166. nTo, i, strLabel);
  167. }
  168. }
  169. return nFrom;
  170. }
  171. int CXTListBase::GetColumnCount()
  172. {
  173. // if we are not in report mode return error.
  174. if ((GetWindowLong(m_pListCtrl->m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
  175. return -1;
  176. // get a pointer to the header control, if NULL return error.
  177. CHeaderCtrl* pHeaderCtrl = _xtGetHeaderCtrl();
  178. if (pHeaderCtrl == NULL)
  179. return -1;
  180. return pHeaderCtrl->GetItemCount();
  181. }
  182. BOOL CXTListBase::ModifyExtendedStyle(DWORD dwRemove, DWORD dwAdd)
  183. {
  184. ASSERT(m_pListCtrl != NULL && m_pListCtrl->m_hWnd != NULL);
  185. if (!m_pListCtrl)
  186. return FALSE;
  187. DWORD dwStyle = (DWORD)::SendMessage(m_pListCtrl->m_hWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
  188. DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  189. if (dwStyle == dwNewStyle)
  190. return FALSE;
  191. ::SendMessage(m_pListCtrl->m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwNewStyle);
  192. return TRUE;
  193. }
  194. void CXTListBase::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
  195. {
  196. NMLVCUSTOMDRAW* lpLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
  197. *pResult = CDRF_DODEFAULT;
  198. switch (lpLVCD->nmcd.dwDrawStage)
  199. {
  200. case CDDS_PREPAINT:
  201. *pResult = CDRF_NOTIFYITEMDRAW;
  202. break;
  203. case CDDS_PREPAINT | CDDS_ITEM:
  204. *pResult = CDRF_NOTIFYSUBITEMDRAW;
  205. break;
  206. case CDDS_PREPAINT | CDDS_ITEM | CDDS_SUBITEM:
  207. {
  208. ROWCOLOR* lpRowColor = Lookup((int)lpLVCD->nmcd.dwItemSpec);
  209. BOOL bUseSortColor = (m_bSortColor && (lpLVCD->iSubItem == m_nSortedCol));
  210. BOOL bUseRowColor = (m_bRowColor && lpRowColor);
  211. // if the item is selected use system default.
  212. if (bUseRowColor && m_pListCtrl->GetItemState(
  213. (int)lpLVCD->nmcd.dwItemSpec, LVIS_SELECTED) == LVIS_SELECTED)
  214. {
  215. bUseRowColor = FALSE;
  216. }
  217. // if the window is disabled use system default.
  218. if (!m_pListCtrl->IsWindowEnabled())
  219. {
  220. lpLVCD->clrText = ::GetSysColor(COLOR_WINDOWTEXT);
  221. lpLVCD->clrTextBk = ::GetSysColor(COLOR_3DFACE);
  222. }
  223. // user defined sort color.
  224. else if (bUseSortColor && !bUseRowColor)
  225. {
  226. lpLVCD->clrText = GetSortTextColor();
  227. lpLVCD->clrTextBk = GetSortBackColor();
  228. }
  229. // use user defined row color.
  230. else if (bUseRowColor)
  231. {
  232. lpLVCD->clrText = lpRowColor->crText;
  233. lpLVCD->clrTextBk = lpRowColor->crBack;
  234. if (bUseSortColor)
  235. {
  236. CXTColorRef crTextBack(lpLVCD->clrTextBk);
  237. crTextBack.blend(GetSortBackColor(), 50);
  238. lpLVCD->clrTextBk = crTextBack;
  239. }
  240. }
  241. // user defined list color.
  242. else if (m_bListColor)
  243. {
  244. lpLVCD->clrText = GetListTextColor();
  245. lpLVCD->clrTextBk = GetListBackColor();
  246. }
  247. // default color.
  248. else
  249. {
  250. lpLVCD->clrText = ::GetSysColor(COLOR_WINDOWTEXT);
  251. lpLVCD->clrTextBk = ::GetSysColor(COLOR_WINDOW);
  252. }
  253. break;
  254. }
  255. }
  256. }
  257. int CXTListBase::SetSortImage(int nCol, BOOL bAsc)
  258. {
  259. int iPrev = m_nSortedCol;
  260. m_nSortedCol = nCol;
  261. m_bAscending = (bAsc == TRUE);
  262. CXTHeaderCtrl* pHeaderCtrl = DYNAMIC_DOWNCAST(CXTHeaderCtrl, m_pListCtrl->GetDlgItem(0));
  263. if (pHeaderCtrl && ::IsWindow(pHeaderCtrl->m_hWnd))
  264. {
  265. return pHeaderCtrl->SetSortImage(nCol, bAsc);
  266. }
  267. return iPrev;
  268. }
  269. BOOL CXTListBase::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  270. {
  271. HD_NOTIFY *pHDNotify = (HD_NOTIFY*)lParam;
  272. switch (pHDNotify->hdr.code)
  273. {
  274. case HDN_ITEMCLICKA:
  275. case HDN_ITEMCLICKW:
  276. {
  277. CXTFlatHeaderCtrl* pHeaderCtrl = GetFlatHeaderCtrl();
  278. if (pHeaderCtrl)
  279. {
  280. // left mouse button.
  281. if (pHDNotify->iButton == 0)
  282. {
  283. if (pHDNotify->iItem == m_nSortedCol)
  284. {
  285. m_bAscending = !m_bAscending;
  286. }
  287. else
  288. {
  289. m_bAscending = true;
  290. }
  291. }
  292. // right mouse button.
  293. else if (pHDNotify->iButton == 1)
  294. {
  295. m_bAscending = pHeaderCtrl->GetAscending() ? true : false;
  296. }
  297. else
  298. {
  299. break;
  300. }
  301. // set sort image for header.
  302. m_nSortedCol = pHDNotify->iItem;
  303. pHeaderCtrl->SetSortImage (m_nSortedCol, m_bAscending);
  304. // sort list.
  305. SortList (m_nSortedCol, m_bAscending);
  306. }
  307. }
  308. break;
  309. case HDN_ITEMCHANGINGA:
  310. case HDN_ITEMCHANGINGW:
  311. case HDN_ENDTRACK:
  312. {
  313. if (pHDNotify->pitem->mask & HDI_WIDTH)
  314. {
  315. if (pHDNotify->pitem->cxy < m_nMinColWidth)
  316. pHDNotify->pitem->cxy = m_nMinColWidth;
  317. }
  318. }
  319. break;
  320. case HDN_DIVIDERDBLCLICKA:
  321. case HDN_DIVIDERDBLCLICKW:
  322. case HDN_BEGINTRACKW:
  323. case HDN_BEGINTRACKA:
  324. {
  325. if (!m_bNoColSizing)
  326. break;
  327. *pResult = TRUE;
  328. return TRUE;
  329. }
  330. }
  331. return m_pListCtrl->CListCtrl::OnNotify(wParam, lParam, pResult);
  332. }
  333. bool CXTListBase::SortList(int nCol, bool bAscending)
  334. {
  335. #ifdef _DEBUG
  336. TRACE2("Column sort on column index %d, ascending=%dn", nCol, bAscending);
  337. #else
  338. UNREFERENCED_PARAMETER(nCol);
  339. UNREFERENCED_PARAMETER(bAscending);
  340. #endif
  341. return true;
  342. }
  343. int CXTListBase::AddColumn(LPCTSTR lpszColHeading, int nWidth/*= -1*/, int nFormat/*= LVCFMT_LEFT*/)
  344. {
  345. // if we are not in report mode return error.
  346. if ((GetWindowLong(m_pListCtrl->m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
  347. return -1;
  348. // get a pointer to the header control, if NULL return error.
  349. CHeaderCtrl* pHeaderCtrl = _xtGetHeaderCtrl();
  350. if (pHeaderCtrl == NULL)
  351. return -1;
  352. int iIndex = pHeaderCtrl->GetItemCount();
  353. if (nWidth == -1)
  354. {
  355. // Get the column width of the previous column from header control
  356. HD_ITEM hd_item;
  357. hd_item.mask = HDI_WIDTH;               //indicate that we want the width
  358. pHeaderCtrl->GetItem(iIndex - 1, &hd_item);
  359. nWidth = hd_item.cxy;
  360. }
  361. return m_pListCtrl->InsertColumn(iIndex, lpszColHeading, nFormat, nWidth, iIndex);
  362. }
  363. bool CXTListBase::BuildColumns(int nCols, int* nWidth, int* nColString)
  364. {
  365. int i;
  366. for (i = 0; i < nCols; ++i)
  367. {
  368. CString strColumn;
  369. if (!strColumn.LoadString(nColString[i]))
  370. {
  371. }
  372. if (m_pListCtrl->InsertColumn(i, strColumn, LVCFMT_LEFT, nWidth[i], i) == -1)
  373. {
  374. return false;
  375. }
  376. }
  377. return true;
  378. }
  379. bool CXTListBase::BuildColumns(int nCols, int* nWidth, CString* strColString)
  380. {
  381. int i;
  382. for (i = 0; i < nCols; ++i)
  383. {
  384. if (m_pListCtrl->InsertColumn(i, strColString[i], LVCFMT_LEFT, nWidth[i], i) == -1)
  385. {
  386. return false;
  387. }
  388. }
  389. return true;
  390. }
  391. int CXTListBase::HitTestEx(CPoint& point, int* nCol) const
  392. {
  393. int colnum = 0;
  394. int row = m_pListCtrl->HitTest(point, NULL);
  395. if (nCol) *nCol = 0;
  396. // Make sure that the ListView is in LVS_REPORT
  397. if ((GetWindowLong(m_pListCtrl->m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
  398. return row;
  399. // Get the top and bottom row visible
  400. row = m_pListCtrl->GetTopIndex();
  401. int bottom = row + m_pListCtrl->GetCountPerPage();
  402. if (bottom > m_pListCtrl->GetItemCount())
  403. bottom = m_pListCtrl->GetItemCount();
  404. // get a pointer to the header control, if NULL return error.
  405. CHeaderCtrl* pHeaderCtrl = _xtGetHeaderCtrl();
  406. if (pHeaderCtrl == NULL)
  407. return -1;
  408. // Get the number of columns
  409. int nColumnCount = pHeaderCtrl->GetItemCount();
  410. // Loop through the visible rows
  411. for (; row <= bottom; row++)
  412. {
  413. // Get bounding rect of item and check whether point falls in it.
  414. CRect rect;
  415. m_pListCtrl->GetItemRect(row, &rect, LVIR_BOUNDS);
  416. if (rect.PtInRect(point))
  417. {
  418. // Now find the column
  419. for (colnum = 0; colnum < nColumnCount; colnum++)
  420. {
  421. int colwidth = m_pListCtrl->GetColumnWidth(Header_OrderToIndex(pHeaderCtrl->m_hWnd, colnum));
  422. if (point.x >= rect.left
  423. && point.x <= (rect.left + colwidth))
  424. {
  425. if (nCol) *nCol = colnum;
  426. return row;
  427. }
  428. rect.left += colwidth;
  429. }
  430. }
  431. }
  432. return -1;
  433. }
  434. bool CXTListBase::SubclassHeader(bool bBoldFont/*= false*/)
  435. {
  436. // if we are not in report mode return false.
  437. if ((GetWindowLong(m_pListCtrl->m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
  438. return false;
  439. // header was already subclassed!
  440. if (::IsWindow(m_flatHeader.GetSafeHwnd()))
  441. return false;
  442. // Get the windows handle to the header control for the
  443. // list control then subclass the control.
  444. HWND hWndHeader = _xtGetHeaderCtrl()->GetSafeHwnd();
  445. if (!m_flatHeader.SubclassWindow (hWndHeader))
  446. return false;
  447. // finish header initialization.
  448. m_flatHeader.InitializeHeader(bBoldFont);
  449. return true;
  450. }
  451. void CXTListBase::AutoSaveColumns(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault)
  452. {
  453. m_bAutoSave = true;
  454. // initialize registry strings.
  455. if (lpszSection == NULL)
  456. m_strSection = _T("Settings");
  457. else
  458. m_strSection = lpszSection;
  459. if (lpszEntry == NULL)
  460. m_strEntry = _T("Column Info");
  461. else
  462. m_strEntry = lpszEntry;
  463. if (lpszDefault != NULL)
  464. m_strDefault = lpszDefault;
  465. LoadColumnWidths();
  466. }
  467. void CXTListBase::SaveColumnWidths()
  468. {
  469. // if we are not in report mode return.
  470. if ((GetWindowLong(m_pListCtrl->m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
  471. return;
  472. // get a pointer to the header control.
  473. CHeaderCtrl* pHeaderCtrl = _xtGetHeaderCtrl();
  474. if (pHeaderCtrl == NULL)
  475. return;
  476. CString strValue;
  477. int i;
  478. for (i = 0; i < pHeaderCtrl->GetItemCount(); ++i)
  479. {
  480. CString strTemp;
  481. strTemp.Format(_T("%d,"), m_pListCtrl->GetColumnWidth(Header_OrderToIndex(pHeaderCtrl->m_hWnd, i)));
  482. strValue += strTemp;
  483. }
  484. CXTRegistryManager regManager;
  485. regManager.WriteProfileString(m_strSection, m_strEntry, strValue);
  486. }
  487. void CXTListBase::LoadColumnWidths()
  488. {
  489. // if we are not in report mode return.
  490. if ((GetWindowLong(m_pListCtrl->m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
  491. return;
  492. // get a pointer to the header control.
  493. CHeaderCtrl* pHeaderCtrl = _xtGetHeaderCtrl();
  494. if (pHeaderCtrl == NULL)
  495. return;
  496. int i;
  497. for (i = 0; i < pHeaderCtrl->GetItemCount(); ++i)
  498. SetStoredWidth(Header_OrderToIndex(pHeaderCtrl->m_hWnd, i));
  499. }
  500. void CXTListBase::SetStoredWidth(int nCol)
  501. {
  502. int nWidth = GetStoredWidth(nCol);
  503. m_pListCtrl->SetColumnWidth(nCol, nWidth);
  504. }
  505. int CXTListBase::GetStoredWidth(int nCol)
  506. {
  507. // get the value from the registry.
  508. CXTRegistryManager regManager;
  509. CString strValue = regManager.GetProfileString(
  510. m_strSection, m_strEntry, m_strDefault);
  511. // extract the sub string to get the column width.
  512. CString strSubString;
  513. AfxExtractSubString(strSubString, strValue, nCol, _T(','));
  514. // return the width from the registry.
  515. return _ttoi(strSubString);
  516. }
  517. void CXTListBase::OnDestroy()
  518. {
  519. if (m_bAutoSave) SaveColumnWidths();
  520. }
  521. void CXTListBase::AutoSizeColumn(int nCol/*= -1*/)
  522. {
  523. // Call this after your list control is filled
  524. m_pListCtrl->SetRedraw (FALSE);
  525. int nMinCol = nCol < 0 ? 0 : nCol;
  526. int nMaxCol = nCol < 0 ? GetColumnCount()-1 : nCol;
  527. // get a pointer to the header control.
  528. CHeaderCtrl* pHeaderCtrl = _xtGetHeaderCtrl();
  529. if (!::IsWindow(pHeaderCtrl->GetSafeHwnd()))
  530. return;
  531. for (nCol = nMinCol; nCol <= nMaxCol; nCol++)
  532. {
  533. m_pListCtrl->SetColumnWidth(Header_OrderToIndex(pHeaderCtrl->m_hWnd, nCol), LVSCW_AUTOSIZE);
  534. int wc1 = m_pListCtrl->GetColumnWidth(Header_OrderToIndex(pHeaderCtrl->m_hWnd, nCol));
  535. int wc2 = 0;
  536. CWindowDC dc(NULL);
  537. CFont* pOF = dc.SelectObject(pHeaderCtrl->GetFont());
  538. TCHAR szColText[256];
  539. szColText[0] = _T('');
  540. LVCOLUMN lvc;
  541. lvc.mask = LVCF_TEXT;
  542. lvc.pszText = szColText;
  543. lvc.cchTextMax = _countof(szColText);
  544. ListView_GetColumn(m_pListCtrl->m_hWnd, nCol, &lvc);
  545. CSize size = dc.GetTextExtent(szColText);
  546. wc2 = size.cx;
  547. dc.SelectObject(pOF);
  548. wc2 += 12; // add padding.
  549. CXTFlatHeaderCtrl* pFlatHeaderCtrl = GetFlatHeaderCtrl();
  550. if (pFlatHeaderCtrl && pFlatHeaderCtrl->HasSortArrow())
  551. {
  552. if (m_nSortedCol == Header_OrderToIndex(pHeaderCtrl->m_hWnd, nCol))
  553. wc2 += 24; // add padding.
  554. }
  555. int wc = __max(m_nMinColWidth, __max(wc1, wc2));
  556. if (wc > m_nMaxColWidth)
  557. wc = m_nMaxColWidth;
  558. // set the column width.
  559. m_pListCtrl->SetColumnWidth(nCol, wc);
  560. }
  561. m_pListCtrl->SetRedraw();
  562. m_pListCtrl->Invalidate();
  563. }
  564. BOOL CXTListBase::OnEraseBkgnd(CDC* /*pDC*/)
  565. {
  566. return TRUE;
  567. }
  568. LRESULT CXTListBase::OnPrintClient(WPARAM wParam, LPARAM lParam)
  569. {
  570. m_pListCtrl->CWnd::DefWindowProc(WM_ERASEBKGND, wParam, 0);
  571. return m_pListCtrl->CWnd::DefWindowProc(WM_PRINTCLIENT, wParam, lParam);
  572. }
  573. void CXTListBase::OnPaint()
  574. {
  575. // background is already filled in gray
  576. CPaintDC dc(m_pListCtrl);
  577. bool bReportView = ((::GetWindowLong(m_pListCtrl->m_hWnd,
  578. GWL_STYLE) & LVS_TYPEMASK) == LVS_REPORT);
  579. // Get the client rect.
  580. CRect rectClient;
  581. m_pListCtrl->GetClientRect(&rectClient);
  582. // Exclude the header control from being re-painted.
  583. CHeaderCtrl* pHeaderCtrl = NULL;
  584. if (bReportView)
  585. {
  586. // Get a pointer to the header control.
  587. pHeaderCtrl = _xtGetHeaderCtrl();
  588. if (pHeaderCtrl && ::IsWindow(pHeaderCtrl->m_hWnd))
  589. {
  590. CRect rcHeader;
  591. pHeaderCtrl->GetWindowRect(&rcHeader);
  592. m_pListCtrl->ScreenToClient(&rcHeader);
  593. dc.ExcludeClipRect(&rcHeader);
  594. }
  595. }
  596. // define the background fill color.
  597. COLORREF crBackColor = GetListBackColor();
  598. if (!m_pListCtrl->IsWindowEnabled())
  599. crBackColor = ::GetSysColor(COLOR_3DFACE);
  600. // Paint to a memory device context to help
  601. // eliminate screen flicker.
  602. CXTPBufferDC memDC(dc);
  603. memDC.FillSolidRect(rectClient, crBackColor);
  604. if (pHeaderCtrl && ::IsWindow(pHeaderCtrl->m_hWnd))
  605. {
  606. CRect rcCol;
  607. m_pListCtrl->GetClientRect(&rcCol);
  608. SCROLLINFO si;
  609. ::ZeroMemory(&si, sizeof(SCROLLINFO));
  610. si.cbSize = sizeof(SCROLLINFO);
  611. si.fMask = SIF_POS;
  612. m_pListCtrl->GetScrollInfo(SB_HORZ, &si);
  613. rcCol.left -= si.nPos;
  614. for (int iCol = 0; iCol <= pHeaderCtrl->GetItemCount(); iCol++)
  615. {
  616. int iColWidth = m_pListCtrl->GetColumnWidth(Header_OrderToIndex(pHeaderCtrl->m_hWnd, iCol));
  617. rcCol.right = rcCol.left + iColWidth;
  618. if (m_bSortColor && (Header_OrderToIndex(pHeaderCtrl->m_hWnd, iCol) == m_nSortedCol))
  619. {
  620. memDC.FillSolidRect(&rcCol, GetSortBackColor());
  621. break;
  622. }
  623. rcCol.left += iColWidth;
  624. }
  625. }
  626. // Now let the window do its default painting...
  627. m_pListCtrl->CWnd::DefWindowProc(WM_PAINT, (WPARAM)memDC.m_hDC, 0);
  628. // Refresh the header control.
  629. if (pHeaderCtrl && ::IsWindow(pHeaderCtrl->m_hWnd))
  630. {
  631. pHeaderCtrl->Invalidate();
  632. pHeaderCtrl->UpdateWindow();
  633. }
  634. }
  635. bool CXTListBase::Init()
  636. {
  637. if (!::IsWindow(m_pListCtrl->GetSafeHwnd()))
  638. return false;
  639. // NOTE: using auto font will also reset the font
  640. // for the header control.
  641. if (m_bAutoFont)
  642. {
  643. m_pListCtrl->SetFont(&XTAuxData().font);
  644. }
  645. return true;
  646. }
  647. void CXTListBase::OnSettingChange(UINT /*uFlags*/, LPCTSTR /*lpszSection*/)
  648. {
  649. RefreshMetrics();
  650. }
  651. CHeaderCtrl* CXTListBase::_xtGetHeaderCtrl() const
  652. {
  653. if (m_pListCtrl == NULL)
  654. return NULL;
  655. CHeaderCtrl * const pHeaderCtrl =
  656. (CHeaderCtrl*)m_pListCtrl->GetDlgItem(0);
  657. // The follow code will ASSERT if you are trying to access the header
  658. // control prior to adding columns to the list control.  If you are
  659. // calling SubclassHeader(), you need to make sure that the call to
  660. // SubClassHeader() is placed after your columns have been inserted.
  661. ASSERT(pHeaderCtrl != NULL);
  662. return pHeaderCtrl;
  663. }
  664. CXTFlatHeaderCtrl* CXTListBase::GetFlatHeaderCtrl() const
  665. {
  666. CHeaderCtrl* pHeaderCtrl = _xtGetHeaderCtrl();
  667. if (!pHeaderCtrl->IsKindOf(RUNTIME_CLASS(CXTFlatHeaderCtrl)))
  668. return NULL;
  669. return (CXTFlatHeaderCtrl*)pHeaderCtrl;
  670. }