ListCtrlBaseEx.cpp
上传用户:lds876
上传日期:2013-05-25
资源大小:567k
文件大小:12k
源码类别:

P2P编程

开发平台:

Visual C++

  1. // ListCtrlBaseEx.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "testbt.h"
  5. #include "ListCtrlBaseEx.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. #define ID_MENUITEM_SHOW_COLUMN 52826
  12. const CString CListCtrlBaseEx::m_strColumnWidthKey = "width";
  13. const CString CListCtrlBaseEx::m_strColumnVisibleKey = "visible";
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CListCtrlBaseEx
  16. CListCtrlBaseEx::CListCtrlBaseEx(CString strSection, bool bSortEnabled)
  17. {
  18. m_bSortEnabled = bSortEnabled;
  19. m_nSortColumn = 1;
  20. m_strSection = strSection;
  21. }
  22. CListCtrlBaseEx::~CListCtrlBaseEx()
  23. {
  24. }
  25. BEGIN_MESSAGE_MAP(CListCtrlBaseEx, CListCtrl)
  26. //{{AFX_MSG_MAP(CListCtrlBaseEx)
  27. ON_WM_CREATE()
  28. ON_WM_DESTROY()
  29. //}}AFX_MSG_MAP
  30. ON_NOTIFY_REFLECT_EX(LVN_COLUMNCLICK, OnItemclickSort)
  31. ON_MESSAGE(LVM_SETIMAGELIST, OnSetImageList)
  32. ON_COMMAND_RANGE(ID_MENUITEM_SHOW_COLUMN, ID_MENUITEM_SHOW_COLUMN + 100, OnMenuitemShowColumn)
  33. END_MESSAGE_MAP()
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CListCtrlBaseEx message handlers
  36. void CListCtrlBaseEx::SetSortColumn(int nColumn)
  37. {
  38.     m_nSortColumn = nColumn;
  39.     SetSortIcon();
  40. }
  41. void CListCtrlBaseEx::AddColumn(CString strName, bool bNumeric, long lWidth, CString strToolTip)
  42. {
  43. m_vColumnInfo.push_back(CColumnInfo(strName, bNumeric, lWidth, true, strToolTip));
  44. }
  45. int CListCtrlBaseEx::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  46. {
  47. if (CListCtrl::OnCreate(lpCreateStruct) == -1)
  48. return -1;
  49. //
  50. // Create BitmapList
  51. //
  52. HBITMAP hbm = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
  53. MAKEINTRESOURCE(IDB_BITMAP_HEADER_ARROW),
  54. IMAGE_BITMAP,
  55. 0,0, // cx,cy
  56. LR_CREATEDIBSECTION); // | LR_LOADMAP3DCOLORS );
  57. CBitmap bm;
  58. bm.Attach(hbm);
  59. BOOL bRet = m_ctlImage.Create(16, 16, ILC_COLOR8|ILC_MASK, 2, 4);
  60. ASSERT(bRet);
  61. m_ctlImage.Add(&bm, (COLORREF)RGB(255,0,255));
  62. m_ctlImage.SetBkColor(CLR_NONE); //::GetSysColor(COLOR_BTNFACE)); 
  63. LoadState();
  64. CHeaderCtrl* pHeader = GetHeaderCtrl();
  65. if (pHeader)
  66. {
  67. m_Tooltip.Create(pHeader);
  68. m_Tooltip.SetMaxTipWidth(1000);
  69. pHeader->EnableToolTips(); 
  70. // EnableToolTips();
  71. }
  72. int iInx = 0;
  73. for (int i=0; i<m_vColumnInfo.size(); i++)
  74. {
  75. if (m_vColumnInfo[i].m_bVisible)
  76. {
  77. int res = InsertColumn(i, m_vColumnInfo[i].m_strName, 
  78. m_vColumnInfo[i].m_bNumeric ? LVCFMT_RIGHT : LVCFMT_LEFT, m_vColumnInfo[i].m_lWidth);
  79. if(res!=-1 && (GetStyle()&LVS_TYPEMASK)==LVS_REPORT)
  80. {
  81. if (pHeader)
  82. {
  83. CRect rcColumn;
  84. BOOL bRet = pHeader->GetItemRect(iInx, &rcColumn);
  85. ASSERT(bRet);
  86. // m_Tooltip.AddTool(pHeader, m_vColumnInfo[i].m_strToolTip, (LPCRECT)rcColumn,  i+1);
  87. if (!m_Tooltip.AddTool(pHeader, m_vColumnInfo[i].m_strToolTip, (LPCRECT)rcColumn,  i+1))
  88. {
  89. ASSERT(FALSE);
  90. }
  91. }
  92. }
  93. iInx ++;
  94. }
  95. }
  96. return 0;
  97. }
  98. void CListCtrlBaseEx::OnDestroy() 
  99. {
  100. SaveState();
  101. CListCtrl::OnDestroy();
  102. }
  103. void CListCtrlBaseEx::LoadState()
  104. {
  105. CString strKey;
  106. for (int i=0; i<m_vColumnInfo.size(); i++)
  107. {
  108. long lWidth = m_vColumnInfo[i].m_lWidth;
  109. if (lWidth <= 0) lWidth = 100;
  110. strKey.Format("%s%d", m_strColumnWidthKey, i);
  111. m_vColumnInfo[i].m_lWidth = AfxGetApp()->GetProfileInt(m_strSection, strKey, lWidth);
  112. strKey.Format("%s%d", m_strColumnVisibleKey, i);
  113. m_vColumnInfo[i].m_bVisible = AfxGetApp()->GetProfileInt(m_strSection, strKey, true) != 0;
  114. }
  115. }
  116. void CListCtrlBaseEx::SaveState()
  117. {
  118. int nColumnCount = GetHeaderCtrl()->GetItemCount();
  119. int iColIdx = 0;
  120. CString strKey;
  121. for (int i=0; i<m_vColumnInfo.size(); i++)
  122. {
  123. if (m_vColumnInfo[i].m_bVisible)
  124. {
  125. strKey.Format("%s%d", m_strColumnWidthKey, i);
  126. AfxGetApp()->WriteProfileInt(m_strSection, strKey, GetColumnWidth(iColIdx));
  127. iColIdx ++;
  128. }
  129. }
  130. for (i=0; i<m_vColumnInfo.size(); i++)
  131. {
  132. strKey.Format("%s%d", m_strColumnVisibleKey, i);
  133. AfxGetApp()->WriteProfileInt(m_strSection, strKey, m_vColumnInfo[i].m_bVisible);
  134. }
  135. }
  136. int CListCtrlBaseEx::GetPhysicalIndex(int nColumnIndex) const
  137. {
  138. assert(nColumnIndex >= 0 && nColumnIndex < m_vColumnInfo.size());
  139. int nIndex = 0;
  140. for (int i = 0; i < nColumnIndex; i++)
  141. {
  142. if (m_vColumnInfo[i].m_bVisible) 
  143. nIndex++;
  144. }
  145. return nIndex;
  146. }
  147. int CListCtrlBaseEx::GetLogicalIndex(int nPhysicalIndex) const
  148. {
  149.   for (int i = 0; i < m_vColumnInfo.size(); i++)
  150.   {
  151.   if (m_vColumnInfo[i].m_bVisible)
  152.   {
  153.   if (i == nPhysicalIndex) 
  154.   return nPhysicalIndex;
  155.   }
  156.   else
  157.   nPhysicalIndex++;   
  158.   }
  159.   return -1;
  160. }
  161. void CListCtrlBaseEx::ShowColumn(int nColumn, bool bShowIt)
  162. {
  163. assert(nColumn >= 0 && nColumn < m_vColumnInfo.size());
  164. if (bShowIt)
  165. {
  166. if (!m_vColumnInfo[nColumn].m_bVisible)
  167. {
  168. m_vColumnInfo[nColumn].m_bVisible = true;
  169. int nPhysicalColumn = GetPhysicalIndex(nColumn);
  170. BOOL bRet = InsertColumn(nPhysicalColumn, m_vColumnInfo[nColumn].m_strName, 
  171. m_vColumnInfo[nColumn].m_bNumeric ? LVCFMT_RIGHT : LVCFMT_LEFT, 100); // m_lArrColumnWidth[nColumn]);
  172. ASSERT(bRet);
  173. for (int i = GetItemCount(); --i >= 0;)
  174. {
  175. // ShowFileDBItemText(i);
  176. // ShowFileDBItemActive(i);
  177. OnShowColumn(i);
  178. }
  179. SetSortIcon();
  180. //
  181. // tooltip
  182. //
  183. CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
  184. if (pHeaderCtrl)
  185. {
  186. CRect rcColumn;
  187. BOOL bRet = pHeaderCtrl->GetItemRect(nPhysicalColumn, &rcColumn);
  188. ASSERT(bRet);
  189. if (!m_Tooltip.AddTool(pHeaderCtrl, m_vColumnInfo[nColumn].m_strToolTip, (LPCRECT)rcColumn,  nColumn+1))
  190. {
  191. ASSERT(FALSE);
  192. }
  193. RecalcToolRect();
  194. }
  195. }
  196. }
  197. else
  198. {
  199. if (m_vColumnInfo[nColumn].m_bVisible)
  200. {
  201. m_vColumnInfo[nColumn].m_bVisible = false;
  202. int nPhysicalColumn = GetPhysicalIndex(nColumn);
  203. BOOL bRet = DeleteColumn(nPhysicalColumn);
  204. ASSERT(bRet);
  205. //
  206. // tooltip
  207. //
  208. CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
  209. if (pHeaderCtrl)
  210. {
  211. m_Tooltip.DelTool(pHeaderCtrl, nColumn + 1);
  212. RecalcToolRect();
  213. }
  214. else
  215. {
  216. ASSERT(FALSE);
  217. }
  218. }
  219. }
  220. }
  221. void CListCtrlBaseEx::OnShowColumn(int iItem)
  222. {
  223. assert(false);
  224. }
  225. bool CListCtrlBaseEx::OnContextMenu(CWnd* pWnd, CPoint point) 
  226. {
  227. if (pWnd == GetHeaderCtrl())
  228. {
  229.       CMenu menu;
  230.       if (!menu.CreatePopupMenu())
  231.   return false;
  232.   for (int i=1; i<m_vColumnInfo.size(); i++)
  233.   {
  234.   menu.AppendMenu(MF_STRING |
  235.   (m_vColumnInfo[i].m_bVisible ? MF_CHECKED : MF_UNCHECKED),
  236.   ID_MENUITEM_SHOW_COLUMN + i, m_vColumnInfo[i].m_strName);
  237.   }
  238.   
  239.   menu.TrackPopupMenu(TPM_LEFTALIGN |TPM_RIGHTBUTTON, point.x, 
  240.   point.y, this);
  241.   return true;
  242. }
  243. CRect rc;
  244. GetClientRect(&rc);
  245. ClientToScreen(rc);
  246. if (!rc.PtInRect(point))
  247. {
  248. CListCtrl::OnContextMenu(pWnd, point);
  249. return true;
  250. }
  251. return false;
  252. }
  253. void CListCtrlBaseEx::OnMenuitemShowColumn(UINT uID)
  254. {
  255. int iColumn = uID - ID_MENUITEM_SHOW_COLUMN;
  256. ShowColumn(iColumn, !m_vColumnInfo[iColumn].m_bVisible);
  257. }
  258. void CListCtrlBaseEx::SetItemTextEx(int iItem, int iSubItem, CString strText)
  259. {
  260. assert(iSubItem>= 0 && iSubItem < m_vColumnInfo.size());
  261. if (m_vColumnInfo[iSubItem].m_bVisible)
  262. {
  263. SetItemText(iItem, GetPhysicalIndex(iSubItem), strText);
  264. }
  265. }
  266. void CListCtrlBaseEx::SelectAllItems() 
  267. {
  268. for (int i=0; i<GetItemCount(); i++)
  269. SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
  270. SetFocus();
  271. }
  272. void CListCtrlBaseEx::ClearSelectItems()
  273. {
  274. POSITION pos = GetFirstSelectedItemPosition();
  275. while (pos)
  276. {
  277. int index = GetNextSelectedItem(pos);
  278. SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, 0);
  279. }
  280. }
  281. LRESULT CListCtrlBaseEx::OnSetImageList(WPARAM wParam, LPARAM lParam)
  282. {
  283. LRESULT dwResult = Default();
  284. if (wParam == LVSIL_SMALL && lParam)
  285. {
  286. // restore image list with sort icons because default behavior is that the
  287. // header control shares its image list with the small icon list of the
  288. // list control
  289. GetHeaderCtrl()->SetImageList(&m_ctlImage);
  290. }
  291. return dwResult;
  292. }
  293. void CListCtrlBaseEx::SetSortIcon()
  294. {
  295. if (!m_bSortEnabled) return;
  296. CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
  297. ASSERT(pHeaderCtrl);
  298. for (int col = 0; col <m_vColumnInfo.size(); col++)
  299. {
  300. if (m_vColumnInfo[col].m_bVisible)
  301. {
  302. HDITEM hdrItem;
  303. int    nPhysicalCol = GetPhysicalIndex(col);
  304. hdrItem.mask = HDI_FORMAT | HDI_IMAGE | HDI_HEIGHT;
  305. hdrItem.cxy = 25;
  306. pHeaderCtrl->GetItem(nPhysicalCol, &hdrItem);
  307. if ( m_nSortColumn != 0 && m_nSortColumn - 1 == col)
  308. {
  309. hdrItem.iImage = eArrowDown;
  310. hdrItem.fmt    = hdrItem.fmt & HDF_JUSTIFYMASK |
  311. HDF_IMAGE | HDF_STRING | HDF_BITMAP_ON_RIGHT;
  312. }
  313. else if (m_nSortColumn != 0 && -m_nSortColumn - 1 == col)
  314. {
  315. hdrItem.iImage = eArrowUp;
  316. hdrItem.fmt    = hdrItem.fmt & HDF_JUSTIFYMASK |
  317. HDF_IMAGE | HDF_STRING | HDF_BITMAP_ON_RIGHT;
  318. }
  319. else
  320. hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_STRING;
  321. pHeaderCtrl->SetItem(nPhysicalCol, &hdrItem);
  322. }
  323. }
  324. }
  325. void CListCtrlBaseEx::OnItemclickSort(NMHDR* pNMHDR, LRESULT* pResult)
  326. {
  327. *pResult = 0;
  328. if (!m_bSortEnabled) return;
  329. NMLISTVIEW* pNMListView = reinterpret_cast<NMLISTVIEW*>(pNMHDR);
  330. int iSubItem = GetLogicalIndex(pNMListView->iSubItem);
  331. if (iSubItem == -1)
  332. {
  333. assert(false);
  334. return;
  335. }
  336. int nAbsSortColumn = abs(m_nSortColumn);
  337. if (nAbsSortColumn > 0)
  338. {
  339. if (iSubItem == nAbsSortColumn-1)
  340. m_nSortColumn = -m_nSortColumn;
  341. else
  342. m_nSortColumn = iSubItem + 1;
  343. }
  344. else
  345. m_nSortColumn = iSubItem + 1;
  346. SetSortIcon();
  347. OnColumnSort(m_nSortColumn);
  348. }
  349. void CListCtrlBaseEx::OnColumnSort(int iColumn)
  350. {
  351. if (!m_bSortEnabled) return;
  352. assert(false);
  353. }
  354. /************************************************************************
  355. Tool tip
  356. ************************************************************************/
  357. /*
  358. void CListCtrlBaseEx::PreSubclassWindow() 
  359. {
  360. CListCtrl::PreSubclassWindow();
  361. EnableToolTips(); // Enables list contrl ToolTip control
  362. int iRet = m_Header.SubclassDlgItem(0, this); // Replaces new header control with default list contrl header control.
  363. if (!iRet)
  364. {
  365. DWORD dwErr = GetLastError();
  366. ASSERT(FALSE);
  367. }
  368. }
  369. //*/
  370. //*
  371. // Detects CListCtrlBaseEx resizing.
  372. BOOL CListCtrlBaseEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
  373. {
  374. // TODO: Add your specialized code here and/or call the base class
  375. LPNMHEADER pNMHD = (LPNMHEADER)lParam;
  376. switch(pNMHD->hdr.code)
  377. {
  378. case HDN_ITEMCHANGEDA:
  379. case HDN_ITEMCHANGEDW:
  380. {
  381. BOOL bRes;
  382. bRes = CListCtrl::OnNotify(wParam, lParam, pResult);
  383. RecalcToolRect();
  384. return bRes;
  385. }
  386. }
  387. return CListCtrl::OnNotify(wParam, lParam, pResult);
  388. }
  389.   //*/
  390. BOOL CListCtrlBaseEx::PreTranslateMessage(MSG* pMsg) 
  391. {
  392. m_Tooltip.RelayEvent(pMsg);
  393. return CListCtrl::PreTranslateMessage(pMsg);
  394. }
  395. void CListCtrlBaseEx::RecalcToolRect()
  396. {
  397. // This prevent debug assertion fail on last WM_MOVE on app close.
  398. if(!::IsWindow(m_Tooltip.m_hWnd))
  399. return;
  400. CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
  401. if (!pHeaderCtrl)
  402. {
  403. ASSERT(FALSE);
  404. return;
  405. }
  406. if((GetStyle()&LVS_TYPEMASK)!=LVS_REPORT)
  407. {
  408. ASSERT(FALSE);
  409. return;
  410. }
  411. int iInx = 0;
  412. for (int i=0; i<m_vColumnInfo.size(); i++)
  413. {
  414. if (m_vColumnInfo[i].m_bVisible)
  415. {
  416. if (pHeaderCtrl)
  417. {
  418. CRect rcColumn;
  419. BOOL bRet = pHeaderCtrl->GetItemRect(iInx, &rcColumn);
  420. ASSERT(bRet);
  421. // m_Tooltip.AddTool(pHeader, m_vColumnInfo[i].m_strToolTip, (LPCRECT)rcColumn,  i+1);
  422. m_Tooltip.SetToolRect(pHeaderCtrl, i+1, (LPCRECT)rcColumn);
  423. }
  424. iInx ++;
  425. }
  426. }
  427. /*
  428. HDITEM hdCol;
  429. hdCol.mask = HDI_WIDTH | HDI_FORMAT;
  430. RECT rcColumn;
  431. GetClientRect(&rcColumn);
  432. // Get scroll position
  433. int nHScrollPos = GetScrollPos(SB_HORZ);
  434. rcColumn.left -= nHScrollPos;
  435. rcColumn.right -= nHScrollPos;
  436. CRect rectTool;
  437. int numcol = GetItemCount();
  438. for(int col=0; col<numcol; col++)
  439. {
  440. // Get column string extent
  441. pHeaderCtrl->GetItem(col, &hdCol);
  442. rcColumn.right = rcColumn.left + LOWORD(hdCol.cxy);
  443. // Calculate ToolTip hover rectangle
  444. rectTool = rcColumn;
  445. rectTool.OffsetRect(nHScrollPos, 0);
  446. m_Tooltip.SetToolRect(this, col+1, &rectTool);
  447. rcColumn.left = rcColumn.right;
  448. }
  449. //*/
  450. }