NavListCtrl.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. #include "pch.h"
  2. #include "NavListCtrl.h"
  3. #ifdef _DEBUG
  4. #define new DEBUG_NEW
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #endif
  8. CNavListCtrl::CNavListCtrl()
  9. {
  10. m_crHighlight = RGB(254, 242, 205);
  11. m_crHighlightBorder = RGB(233, 175, 0);
  12. m_crHover = RGB(7, 162, 254);
  13. nHoverItem = -1;
  14. nLastHoverItem = -1;
  15. m_bmpItemSelected.LoadImage("Skin\\DefaultTheme\\ItemSelected.bmp");
  16. m_bmpFaceBG.LoadImage("Skin\\DefaultTheme\\FaceBG.bmp");
  17. m_hTailIconCamera = (HICON)::LoadImage(AfxGetApp()->m_hInstance, "Skin\\DefaultTheme\\icon\\CameraProp.ico", IMAGE_ICON, 14, 14, LR_LOADFROMFILE);
  18. m_hTailIconEmail = (HICON)::LoadImage(AfxGetApp()->m_hInstance, "Skin\\DefaultTheme\\icon\\EmailProp.ico", IMAGE_ICON, 14, 14, LR_LOADFROMFILE);
  19. m_hTailIconMobile = (HICON)::LoadImage(AfxGetApp()->m_hInstance, "Skin\\DefaultTheme\\icon\\MobileProp.ico", IMAGE_ICON, 14, 14, LR_LOADFROMFILE);
  20. }
  21. CNavListCtrl::~CNavListCtrl()
  22. {
  23. if (m_hTailIconCamera)
  24. ::DestroyIcon(m_hTailIconCamera);
  25. if (m_hTailIconEmail)
  26. ::DestroyIcon(m_hTailIconEmail);
  27. if (m_hTailIconMobile)
  28. ::DestroyIcon(m_hTailIconMobile);
  29. }
  30. BEGIN_MESSAGE_MAP(CNavListCtrl, CListCtrl)
  31. //{{AFX_MSG_MAP(CNavListCtrl)
  32. ON_WM_NCCALCSIZE()
  33. ON_WM_MOUSEMOVE()
  34. ON_WM_MEASUREITEM_REFLECT()
  35. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnNMCustomdraw)
  36. ON_WM_LBUTTONDOWN()
  37. //}}AFX_MSG_MAP
  38. ON_WM_SIZE()
  39. ON_WM_ERASEBKGND()
  40. ON_WM_PAINT()
  41. ON_WM_TIMER()
  42. END_MESSAGE_MAP()
  43. void CNavListCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
  44. {
  45. // TODO: Add your message handler code here and/or call default
  46. ShowScrollBar(SB_HORZ, FALSE);
  47. CListCtrl::OnNcCalcSize(bCalcValidRects, lpncsp);
  48. }
  49. void CNavListCtrl::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult)
  50. {
  51. LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
  52. LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
  53. lpLVCustomDraw->clrText = RGB(58, 25, 255); // white text
  54. //lpLVCustomDraw->clrTextBk = RGB(222,0,0);
  55. /*
  56. if(lpLVCustomDraw->nmcd.dwDrawStage==CDDS_PREPAINT)
  57. *pResult=CDRF_NOTIFYITEMDRAW;
  58. if(lpLVCustomDraw->nmcd.dwDrawStage==CDDS_ITEMPREPAINT)
  59. {
  60. for(int i=0;i<10;i++)
  61. {
  62. if(lpLVCustomDraw->nmcd.dwItemSpec==(unsigned)i)
  63. {
  64. lpLVCustomDraw->clrText=RGB(255,0,0);
  65. lpLVCustomDraw->clrTextBk=RGB(255,255,0);
  66. }
  67. }
  68. }
  69. */
  70. // TODO: 在此添加控件通知处理程序代码
  71. * pResult = 0;
  72. *pResult |= CDRF_NOTIFYPOSTPAINT;
  73. *pResult |= CDRF_NOTIFYITEMDRAW;
  74. *pResult |= CDRF_NOTIFYSUBITEMDRAW;
  75. }
  76. int CNavListCtrl::InsertItem(int nItem, LPCTSTR szItemText, int nImageIndex, LUSERITEM* UserInfo)
  77. {
  78. DEQUELVITEM* pDeqListItem = &m_DequeList;
  79. if (UserInfo)
  80. pDeqListItem->push_back(*UserInfo);
  81. nItem = CListCtrl::InsertItem(nItem, szItemText, nImageIndex);
  82. return nItem;
  83. }
  84. void CNavListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  85. {
  86. CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  87. //CRect rcItem(lpDrawItemStruct->rcItem);
  88. int nItem = lpDrawItemStruct->itemID;
  89. CImageList* pImageList;
  90. // Save dc state
  91. int nSavedDC = pDC->SaveDC();
  92. // Get item image and state info
  93. LV_ITEM lvi;
  94. lvi.mask = LVIF_IMAGE | LVIF_STATE;
  95. lvi.iItem = nItem;
  96. lvi.iSubItem = 0;
  97. lvi.stateMask = 0xFFFF; // get all state flags
  98. GetItem(&lvi);
  99. // Should the item be highlighted
  100. BOOL bHighlight = ((lvi.state & LVIS_DROPHILITED) || ((lvi.state & LVIS_SELECTED) && ((GetFocus() == this) || (GetStyle() & LVS_SHOWSELALWAYS))));
  101. // Get rectangles for drawing
  102. CRect rcClient;
  103. GetClientRect(&rcClient);
  104. CRect rcBounds, rcLabel, rcIcon;
  105. GetItemRect(nItem, rcBounds, LVIR_BOUNDS);
  106. GetItemRect(nItem, rcLabel, LVIR_LABEL);
  107. GetItemRect(nItem, rcIcon, LVIR_ICON);
  108. CRect rcCol(rcBounds);
  109. POINT pt;
  110. GetCursorPos(&pt);
  111. ScreenToClient(&pt);
  112. CString sLabel = GetItemText(nItem, 0);
  113. // Labels are offset by a certain amount
  114. // This offset is related to the width of a space character
  115. int offset = pDC->GetTextExtent(_T(" "), 1).cx * 2;
  116. CRect rcHighlight;
  117. int nExt;
  118. switch (m_nHighlight)
  119. {
  120. case 0:
  121. nExt = pDC->GetOutputTextExtent(sLabel).cx + offset;
  122. rcHighlight = rcLabel;
  123. if (rcLabel.left + nExt < rcLabel.right)
  124. rcHighlight.right = rcLabel.left + nExt;
  125. break;
  126. case 1:
  127. rcHighlight = rcBounds;
  128. rcHighlight.left = rcLabel.left;
  129. break;
  130. default:
  131. rcHighlight = rcBounds;
  132. rcHighlight.left = rcBounds.left + 1;
  133. rcHighlight.right = rcClient.right - 2;
  134. break;
  135. }
  136. // 黄色选中背景要跟控件长度一样;
  137. rcHighlight.right = rcClient.right - 2;
  138. // 画背景
  139. CRect rcIconBG(rcIcon);
  140. rcIconBG.right += 12;
  141. CEnBitmap bmpFaceBG;
  142. if (bHighlight)
  143. {
  144. //nItem是当前高亮的项
  145. if (m_bmpItemSelected.m_hObject != NULL)
  146. m_bmpItemSelected.ExtendDraw(pDC, rcHighlight, 20, 10, TRUE);
  147. //画图标背景
  148. if (m_bmpFaceBG.m_hObject != NULL)
  149. {
  150. m_bmpFaceBG.DrawImage(bmpFaceBG, 1, 1, 2, 1);
  151. bmpFaceBG.ExtendDraw(pDC, rcIconBG, 20, 10);
  152. }
  153. }
  154. else
  155. {
  156. //if(nHoverItem == nItem)
  157. // pDC->FillRect(rcHighlight, &CBrush(m_crHover));
  158. //else
  159. pDC->FillRect(rcHighlight, &CBrush(RGB(255, 255, 255)));
  160. //画图标背景
  161. if (m_bmpFaceBG.m_hObject != NULL)
  162. {
  163. m_bmpFaceBG.DrawImage(bmpFaceBG, 2, 1, 2, 1);
  164. bmpFaceBG.ExtendDraw(pDC, rcIconBG, 20, 10);
  165. }
  166. }
  167. // Draw normal and overlay icon
  168. pImageList = GetImageList(LVSIL_SMALL);
  169. if (pImageList)
  170. {
  171. UINT nOvlImageMask = lvi.state & LVIS_OVERLAYMASK;
  172. pImageList->Draw(pDC, lvi.iImage,
  173. CPoint(rcIcon.left + 6, rcIcon.top + 6), ILD_TRANSPARENT | nOvlImageMask);
  174. }
  175. // Draw item label - Column 0
  176. rcLabel.top += 5;
  177. rcLabel.left += offset / 2 + 7;
  178. rcLabel.right -= offset;
  179. pDC->DrawText(sLabel, -1, rcLabel, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_END_ELLIPSIS);
  180. LUSERITEM userInfo;
  181. GetUserItemInfo(sLabel, &userInfo);
  182. CSize size = pDC->GetTextExtent(sLabel);
  183. if (userInfo.szUserID != "")
  184. {
  185. sLabel = userInfo.szNoticeMsg;
  186. rcLabel.top = rcLabel.top + size.cy + 3;
  187. rcLabel.right = rcClient.right;
  188. //if(rcLabel.PtInRect(pt))
  189. //{
  190. // pDC->SetTextColor(RGB(10,255,10));
  191. //}
  192. //else
  193. //{
  194. pDC->SetTextColor(GetSysColor(COLOR_BTNSHADOW));
  195. //}
  196. pDC->DrawText(sLabel, rcLabel, DT_SINGLELINE | DT_LEFT | DT_END_ELLIPSIS);
  197. }
  198. //Draw TailIcon
  199. DWORD nStyle = GetItemData(nItem);
  200. CRect rcCamera = GetTailIconRect(nItem, TVS_CAMERA);
  201. if ((nStyle & TVS_CAMERA) && (m_hTailIconCamera != NULL))
  202. {
  203. if (rcCamera.PtInRect(pt))
  204. {
  205. pDC->FillSolidRect(rcCamera, m_crHighlight);
  206. pDC->Draw3dRect(rcCamera, m_crHighlightBorder, m_crHighlightBorder);
  207. }
  208. ::DrawIconEx(*pDC, rcCamera.left + 2, rcCamera.top + 2, m_hTailIconCamera, 14, 14, 0, NULL, DI_NORMAL);
  209. }
  210. CRect rcEmail = GetTailIconRect(nItem, TVS_EMAIL);
  211. if ((nStyle & TVS_EMAIL) && (m_hTailIconEmail != NULL))
  212. {
  213. if (rcEmail.PtInRect(pt))
  214. {
  215. pDC->FillSolidRect(rcEmail, m_crHighlight);
  216. pDC->Draw3dRect(rcEmail, m_crHighlightBorder, m_crHighlightBorder);
  217. }
  218. ::DrawIconEx(*pDC, rcEmail.left + 2, rcEmail.top + 2, m_hTailIconEmail, 14, 14, 0, NULL, DI_NORMAL);
  219. }
  220. CRect rcMobile = GetTailIconRect(nItem, TVS_MOBILE);
  221. if ((nStyle & TVS_MOBILE) && (m_hTailIconMobile != NULL))
  222. {
  223. if (rcMobile.PtInRect(pt))
  224. {
  225. pDC->FillSolidRect(rcMobile, m_crHighlight);
  226. pDC->Draw3dRect(rcMobile, m_crHighlightBorder, m_crHighlightBorder);
  227. }
  228. ::DrawIconEx(*pDC, rcMobile.left + 2, rcMobile.top + 2, m_hTailIconMobile, 14, 14, 0, NULL, DI_NORMAL);
  229. }
  230. // Draw labels for remaining columns
  231. LV_COLUMN lvc;
  232. lvc.mask = LVCF_FMT | LVCF_WIDTH;
  233. if (m_nHighlight == 0) // Highlight only first column
  234. {
  235. pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
  236. pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
  237. }
  238. rcBounds.right = rcHighlight.right > rcBounds.right ? rcHighlight.right + 10 :
  239. rcBounds.right + 10;
  240. for (int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++)
  241. {
  242. rcCol.left = rcCol.right;
  243. rcCol.right += lvc.cx;
  244. //Draw the background if needed
  245. //if( m_nHighlight == HIGHLIGHT_NORMAL )
  246. // pDC->FillRect(rcCol, &CBrush(::GetSysColor(COLOR_WINDOW)));
  247. sLabel = GetItemText(nItem, nColumn);
  248. if (sLabel.GetLength() == 0)
  249. continue;
  250. // Get the text justification
  251. UINT nJustify = DT_LEFT;
  252. switch (lvc.fmt & LVCFMT_JUSTIFYMASK)
  253. {
  254. case LVCFMT_RIGHT:
  255. nJustify = DT_RIGHT;
  256. break;
  257. case LVCFMT_CENTER:
  258. nJustify = DT_CENTER;
  259. break;
  260. default:
  261. break;
  262. }
  263. rcLabel = rcCol;
  264. rcLabel.left += offset;
  265. rcLabel.right -= offset;
  266. pDC->DrawText(sLabel, -1, rcLabel, nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_END_ELLIPSIS);
  267. }
  268. // Restore dc
  269. pDC->RestoreDC(nSavedDC);
  270. }
  271. CRect CNavListCtrl::GetTailIconRect(int nItem, DWORD dwServeFlag)
  272. {
  273. CRect rcIcon, rcClient;
  274. GetItemRect(nItem, rcIcon, LVIR_ICON);
  275. GetClientRect(&rcClient);
  276. DWORD nStyle = GetItemData(nItem);
  277. switch (nStyle & dwServeFlag)
  278. {
  279. case TVS_CAMERA:
  280. {
  281. rcIcon.left = rcClient.right - 22;
  282. rcIcon.right = rcIcon.left + 18;
  283. rcIcon.bottom = rcIcon.top + 18;
  284. }
  285. break;
  286. case TVS_EMAIL:
  287. {
  288. rcIcon.left = rcIcon.right + 10;
  289. rcIcon.right = rcIcon.left + 18;
  290. rcIcon.top = rcIcon.bottom - 20;
  291. rcIcon.bottom = rcIcon.top + 18;
  292. }
  293. break;
  294. case TVS_MOBILE:
  295. {
  296. rcIcon.left = rcIcon.right + 10;
  297. if (nStyle & TVS_EMAIL)
  298. rcIcon.left += 18;
  299. rcIcon.right = rcIcon.left + 18;
  300. rcIcon.top = rcIcon.bottom - 20;
  301. rcIcon.bottom = rcIcon.top + 18;
  302. }
  303. break;
  304. default:
  305. rcIcon.SetRectEmpty();
  306. break;
  307. }
  308. return rcIcon;
  309. }
  310. BOOL CNavListCtrl::GetUserItemInfo(LPCTSTR szItemText, LUSERITEM* userInfo)
  311. {
  312. ASSERT(userInfo != NULL);
  313. BOOL bRet = FALSE;
  314. DEQUELVITEM* pDeqListItem = &m_DequeList;
  315. DEQUELVITEM::iterator it, itbegin = pDeqListItem->begin(), itend = pDeqListItem->end();
  316. for (it = itbegin; it != itend; it++)
  317. {
  318. if (it->szUserID == szItemText)
  319. {
  320. *userInfo = (LUSERITEM)*it; //复制结构数据到userInof;
  321. bRet = TRUE;
  322. break;
  323. }
  324. }
  325. return bRet;
  326. }
  327. void CNavListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
  328. {
  329. int nItem = HitTest(point);
  330. if (nItem != -1)
  331. {
  332. CString strTip;
  333. CRect rcServe;
  334. for (DWORD dwFlag = TVS_CAMERA;dwFlag < TVS_ONLINEUSER;dwFlag++)
  335. {
  336. rcServe = GetTailIconRect(nItem, dwFlag);
  337. if (rcServe.PtInRect(point))
  338. {
  339. strTip.Format("位置:nItem=%d,dwServeFlag=%#0.8x", nItem, dwFlag);
  340. break;
  341. }
  342. }
  343. if (!strTip.IsEmpty())
  344. MessageBox(strTip);
  345. }
  346. CListCtrl::OnLButtonDown(nFlags, point);
  347. }
  348. //调整行高
  349. void CNavListCtrl::MeasureItem(LPMEASUREITEMSTRUCT lpMis)
  350. {
  351. lpMis->itemHeight = 52;
  352. }
  353. void CNavListCtrl::OnSize(UINT nType, int cx, int cy)
  354. {
  355. CListCtrl::OnSize(nType, cx, cy);
  356. SetColumnWidth(0, cx);
  357. RedrawWindow();
  358. }
  359. BOOL CNavListCtrl::OnEraseBkgnd(CDC* pDC)
  360. {
  361. // TODO: 在此添加消息处理程序代码和/或调用默认值
  362. return TRUE;
  363. //return CListCtrl::OnEraseBkgnd(pDC);
  364. }
  365. void CNavListCtrl::OnPaint()
  366. {
  367. CPaintDC dc(this); // device context for painting
  368. CRect rcClient;
  369. GetClientRect(&rcClient);
  370. CDC memdc;
  371. memdc.CreateCompatibleDC(&dc);
  372. CBitmap bitmap;
  373. bitmap.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
  374. memdc.SelectObject(&bitmap);
  375. memdc.FillSolidRect(rcClient, RGB(255, 255, 255));
  376. CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC, 0);
  377. dc.BitBlt(
  378. rcClient.left,
  379. rcClient.top,
  380. rcClient.Width(),
  381. rcClient.Height(),
  382. &memdc,
  383. 0, 0, SRCCOPY);
  384. }
  385. void CNavListCtrl::OnMouseMove(UINT nFlags, CPoint point)
  386. {
  387. // TODO: Add your message handler code here and/or call default
  388. nHoverItem = HitTest(point);
  389. if (nLastHoverItem >= 0)
  390. {
  391. CRect rcItem;
  392. GetItemRect(nLastHoverItem, rcItem, LVIR_BOUNDS);
  393. InvalidateRect(rcItem);
  394. }
  395. nLastHoverItem = nHoverItem;
  396. if (nHoverItem >= 0)
  397. {
  398. CRect rcItem;
  399. GetItemRect(nHoverItem, rcItem, LVIR_BOUNDS);
  400. InvalidateRect(rcItem);
  401. //SetTimer(1,100,NULL);
  402. }
  403. CListCtrl::OnMouseMove(nFlags, point);
  404. }
  405. void CNavListCtrl::OnTimer(UINT_PTR nIDEvent)
  406. {
  407. // TODO: 在此添加消息处理程序代码和/或调用默认值
  408. if (nIDEvent == 1)
  409. {
  410. CPoint pt(GetMessagePos());
  411. ScreenToClient(&pt);
  412. CRect rc; GetClientRect(&rc);
  413. if (!rc.PtInRect(pt))
  414. {
  415. nHoverItem = -1;
  416. CRect rcItem;
  417. GetItemRect(nLastHoverItem, rcItem, LVIR_BOUNDS);
  418. InvalidateRect(rcItem);
  419. KillTimer(1);
  420. }
  421. }
  422. CListCtrl::OnTimer(nIDEvent);
  423. }