MyListCtrl.cpp 12 KB

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