MyListCtrl.cpp 12 KB

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