/************************************************************************ * 程序名: 精仿QQ主界面 * 制作人: 李克平, 2011年04月11日 * 版本号: 1.0 ************************************************************************/ // MyListCtrl.cpp : implementation file // #include "stdafx.h" #include "MyListCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMyListCtrl CMyListCtrl::CMyListCtrl() { m_crHighlight = RGB(254,242,205); m_crHighlightBorder = RGB(233,175,0); m_crHover = RGB(7,162,254); nHoverItem = -1; nLastHoverItem = -1; m_bmpItemSelected.LoadImage(_T("Skin\\ItemSelected.bmp")); m_bmpFaceBG.LoadImage(_T("Skin\\FaceBG.bmp")); m_hTailIconCamera =(HICON)::LoadImage(AfxGetApp()->m_hInstance, _T("Skin\\icon\\CameraProp.ico"), IMAGE_ICON,14,14,LR_LOADFROMFILE); m_hTailIconEmail=(HICON)::LoadImage(AfxGetApp()->m_hInstance, _T("Skin\\icon\\EmailProp.ico"), IMAGE_ICON,14,14,LR_LOADFROMFILE); m_hTailIconMobile=(HICON)::LoadImage(AfxGetApp()->m_hInstance, _T("Skin\\icon\\MobileProp.ico"), IMAGE_ICON,14,14,LR_LOADFROMFILE); } CMyListCtrl::~CMyListCtrl() { if(m_hTailIconCamera) ::DestroyIcon(m_hTailIconCamera); if(m_hTailIconEmail) ::DestroyIcon(m_hTailIconEmail); if(m_hTailIconMobile) ::DestroyIcon(m_hTailIconMobile); } BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl) //{{AFX_MSG_MAP(CMyListCtrl) ON_WM_NCCALCSIZE() ON_WM_MOUSEMOVE() ON_WM_MEASUREITEM_REFLECT() ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnNMCustomdraw) ON_WM_LBUTTONDOWN() //}}AFX_MSG_MAP ON_WM_SIZE() ON_WM_ERASEBKGND() ON_WM_PAINT() ON_WM_TIMER() END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMyListCtrl message handlers void CMyListCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) { // TODO: Add your message handler code here and/or call default ShowScrollBar(SB_HORZ,FALSE); CListCtrl::OnNcCalcSize(bCalcValidRects, lpncsp); } void CMyListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult) { LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast(pNMHDR); lpLVCustomDraw->clrText = RGB(58,25,255); // white text //lpLVCustomDraw->clrTextBk = RGB(222,0,0); /* if(lpLVCustomDraw->nmcd.dwDrawStage==CDDS_PREPAINT) *pResult=CDRF_NOTIFYITEMDRAW; if(lpLVCustomDraw->nmcd.dwDrawStage==CDDS_ITEMPREPAINT) { for(int i=0;i<10;i++) { if(lpLVCustomDraw->nmcd.dwItemSpec==(unsigned)i) { lpLVCustomDraw->clrText=RGB(255,0,0); lpLVCustomDraw->clrTextBk=RGB(255,255,0); } } } */ // TODO: 在此添加控件通知处理程序代码 *pResult = 0; *pResult |= CDRF_NOTIFYPOSTPAINT; *pResult |= CDRF_NOTIFYITEMDRAW; *pResult |= CDRF_NOTIFYSUBITEMDRAW; } int CMyListCtrl::InsertItem(int nItem, LPCTSTR szItemText, int nImageIndex, LUSERITEM* UserInfo) { DEQUELVITEM* pDeqListItem = &m_DequeList; if(UserInfo) pDeqListItem ->push_back(*UserInfo); nItem = CListCtrl::InsertItem(nItem,szItemText,nImageIndex); return nItem; } void CMyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //CRect rcItem(lpDrawItemStruct->rcItem); int nItem = lpDrawItemStruct->itemID; CImageList* pImageList; // Save dc state int nSavedDC = pDC->SaveDC(); // Get item image and state info LV_ITEM lvi; lvi.mask = LVIF_IMAGE | LVIF_STATE; lvi.iItem = nItem; lvi.iSubItem = 0; lvi.stateMask = 0xFFFF; // get all state flags GetItem(&lvi); // Should the item be highlighted BOOL bHighlight = ((lvi.state & LVIS_DROPHILITED) || ( (lvi.state & LVIS_SELECTED) && ((GetFocus() == this) || (GetStyle() & LVS_SHOWSELALWAYS)))); // Get rectangles for drawing CRect rcClient; GetClientRect(&rcClient); CRect rcBounds, rcLabel, rcIcon; GetItemRect(nItem, rcBounds, LVIR_BOUNDS); GetItemRect(nItem, rcLabel, LVIR_LABEL); GetItemRect(nItem, rcIcon, LVIR_ICON); CRect rcCol( rcBounds ); POINT pt; GetCursorPos(&pt); ScreenToClient(&pt); CString sLabel = GetItemText( nItem, 0 ); // Labels are offset by a certain amount // This offset is related to the width of a space character int offset = pDC->GetTextExtent(_T(" "), 1 ).cx*2; CRect rcHighlight; int nExt; switch( m_nHighlight ) { case 0: nExt = pDC->GetOutputTextExtent(sLabel).cx + offset; rcHighlight = rcLabel; if( rcLabel.left + nExt < rcLabel.right ) rcHighlight.right = rcLabel.left + nExt; break; case 1: rcHighlight = rcBounds; rcHighlight.left = rcLabel.left; break; default: rcHighlight = rcBounds; rcHighlight.left = rcBounds.left+1; rcHighlight.right = rcClient.right-2; break; } // 画背景 CRect rcIconBG(rcIcon); rcIconBG.right += 12; CEnBitmap bmpFaceBG; if( bHighlight ) { //nItem是当前高亮的项 if(m_bmpItemSelected.m_hObject != NULL) m_bmpItemSelected.ExtendDraw(pDC,rcLabel/*rcHighlight*/,20,10,TRUE); //画图标背景 if(m_bmpFaceBG.m_hObject != NULL) { m_bmpFaceBG.DrawImage(bmpFaceBG,1,1,2,1); bmpFaceBG.ExtendDraw(pDC,rcIconBG,20,10); } } else { //if(nHoverItem == nItem) // pDC->FillRect(rcHighlight, &CBrush(m_crHover)); //else pDC->FillRect(rcHighlight, &CBrush(RGB(255,255,255))); //画图标背景 if(m_bmpFaceBG.m_hObject != NULL) { m_bmpFaceBG.DrawImage(bmpFaceBG,2,1,2,1); bmpFaceBG.ExtendDraw(pDC,rcIconBG,20,10); } } // Draw normal and overlay icon pImageList = GetImageList(LVSIL_SMALL); if (pImageList) { UINT nOvlImageMask=lvi.state & LVIS_OVERLAYMASK; pImageList->Draw(pDC, lvi.iImage, CPoint(rcIcon.left+6, rcIcon.top+6),ILD_TRANSPARENT | nOvlImageMask ); } // Draw item label - Column 0 rcLabel.top += 5; rcLabel.left += offset/2 + 7; rcLabel.right -= offset; pDC->DrawText(sLabel,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_END_ELLIPSIS); LUSERITEM userInfo; GetUserItemInfo(sLabel,&userInfo); CSize size = pDC->GetTextExtent(sLabel); if(userInfo.szUserID !="") { sLabel = userInfo.szNoticeMsg; rcLabel.top = rcLabel.top + size.cy + 3; rcLabel.right = rcClient.right; //if(rcLabel.PtInRect(pt)) //{ // pDC->SetTextColor(RGB(10,255,10)); //} //else //{ pDC->SetTextColor(GetSysColor(COLOR_BTNSHADOW)); //} pDC->DrawText(sLabel,rcLabel,DT_SINGLELINE|DT_LEFT|DT_END_ELLIPSIS); } //Draw TailIcon DWORD nStyle = GetItemData(nItem); CRect rcCamera = GetTailIconRect(nItem,TVS_CAMERA); if ( (nStyle & TVS_CAMERA) && (m_hTailIconCamera !=NULL) ) { if( rcCamera.PtInRect(pt) ) { pDC->FillSolidRect(rcCamera,m_crHighlight); pDC->Draw3dRect(rcCamera,m_crHighlightBorder,m_crHighlightBorder); } ::DrawIconEx(*pDC,rcCamera.left+2,rcCamera.top+2,m_hTailIconCamera,14,14,0,NULL,DI_NORMAL); } CRect rcEmail = GetTailIconRect(nItem,TVS_EMAIL); if ( (nStyle & TVS_EMAIL) && (m_hTailIconEmail !=NULL) ) { if( rcEmail.PtInRect(pt) ) { pDC->FillSolidRect(rcEmail,m_crHighlight); pDC->Draw3dRect(rcEmail,m_crHighlightBorder,m_crHighlightBorder); } ::DrawIconEx(*pDC,rcEmail.left+2,rcEmail.top+2,m_hTailIconEmail,14,14,0,NULL,DI_NORMAL); } CRect rcMobile = GetTailIconRect(nItem,TVS_MOBILE); if ( (nStyle & TVS_MOBILE) && (m_hTailIconMobile !=NULL) ) { if( rcMobile.PtInRect(pt) ) { pDC->FillSolidRect(rcMobile,m_crHighlight); pDC->Draw3dRect(rcMobile,m_crHighlightBorder,m_crHighlightBorder); } ::DrawIconEx(*pDC,rcMobile.left+2,rcMobile.top+2,m_hTailIconMobile,14,14,0,NULL,DI_NORMAL); } // Draw labels for remaining columns LV_COLUMN lvc; lvc.mask = LVCF_FMT | LVCF_WIDTH; if( m_nHighlight == 0 ) // Highlight only first column { pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT)); pDC->SetBkColor(::GetSysColor(COLOR_WINDOW)); } rcBounds.right = rcHighlight.right > rcBounds.right ? rcHighlight.right+10 : rcBounds.right + 10; for(int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++) { rcCol.left = rcCol.right; rcCol.right += lvc.cx; //Draw the background if needed //if( m_nHighlight == HIGHLIGHT_NORMAL ) // pDC->FillRect(rcCol, &CBrush(::GetSysColor(COLOR_WINDOW))); sLabel = GetItemText(nItem, nColumn); if (sLabel.GetLength() == 0) continue; // Get the text justification UINT nJustify = DT_LEFT; switch(lvc.fmt & LVCFMT_JUSTIFYMASK) { case LVCFMT_RIGHT: nJustify = DT_RIGHT; break; case LVCFMT_CENTER: nJustify = DT_CENTER; break; default: break; } rcLabel = rcCol; rcLabel.left += offset; rcLabel.right -= offset; pDC->DrawText(sLabel, -1, rcLabel, nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_END_ELLIPSIS); } // Restore dc pDC->RestoreDC( nSavedDC ); } CRect CMyListCtrl::GetTailIconRect(int nItem,DWORD dwServeFlag) { CRect rcIcon,rcClient; GetItemRect(nItem,rcIcon,LVIR_ICON); GetClientRect(&rcClient); DWORD nStyle = GetItemData(nItem); switch(nStyle & dwServeFlag) { case TVS_CAMERA: { rcIcon.left = rcClient.right - 22; rcIcon.right = rcIcon.left +18; rcIcon.bottom = rcIcon.top +18; } break; case TVS_EMAIL: { rcIcon.left = rcIcon.right + 10; rcIcon.right = rcIcon.left +18; rcIcon.top = rcIcon.bottom - 20; rcIcon.bottom = rcIcon.top + 18; } break; case TVS_MOBILE: { rcIcon.left = rcIcon.right + 10; if (nStyle & TVS_EMAIL) rcIcon.left += 18; rcIcon.right = rcIcon.left +18; rcIcon.top = rcIcon.bottom - 20; rcIcon.bottom = rcIcon.top + 18; } break; default: rcIcon.SetRectEmpty(); break; } return rcIcon; } BOOL CMyListCtrl::GetUserItemInfo(LPCTSTR szItemText,LUSERITEM* userInfo) { ASSERT(userInfo !=NULL); BOOL bRet = FALSE; DEQUELVITEM* pDeqListItem = &m_DequeList; DEQUELVITEM::iterator it,itbegin = pDeqListItem->begin(),itend = pDeqListItem->end(); for ( it = itbegin; it != itend; it++ ) { if( it->szUserID == szItemText) { *userInfo = (LUSERITEM)*it; //复制结构数据到userInof; bRet = TRUE; break; } } return bRet; } void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point) { int nItem = HitTest(point); if(nItem != -1) { CString strTip; CRect rcServe; for(DWORD dwFlag = TVS_CAMERA;dwFlag < TVS_ONLINEUSER;dwFlag++) { rcServe = GetTailIconRect(nItem,dwFlag); if(rcServe.PtInRect(point)) { strTip.Format(_T("位置:nItem=%d,dwServeFlag=%#0.8x"),nItem,dwFlag); break; } } if(!strTip.IsEmpty()) MessageBox(strTip); } CListCtrl::OnLButtonDown(nFlags, point); } //调整行高 void CMyListCtrl::MeasureItem( LPMEASUREITEMSTRUCT lpMis ) { lpMis->itemHeight = 52; } void CMyListCtrl::OnSize(UINT nType, int cx, int cy) { CListCtrl::OnSize(nType, cx, cy); SetColumnWidth(0 ,cx); RedrawWindow(); // TODO: 在此处添加消息处理程序代码 } BOOL CMyListCtrl::OnEraseBkgnd(CDC* pDC) { // TODO: 在此添加消息处理程序代码和/或调用默认值 return TRUE; //return CListCtrl::OnEraseBkgnd(pDC); } void CMyListCtrl::OnPaint() { CPaintDC dc(this); // device context for painting CRect rcClient; GetClientRect(&rcClient); CDC memdc; memdc.CreateCompatibleDC(&dc); CBitmap bitmap; bitmap.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height()); memdc.SelectObject( &bitmap ); memdc.FillSolidRect(rcClient,RGB(255,255,255)); CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC , 0); dc.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memdc, 0, 0,SRCCOPY); } void CMyListCtrl::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default nHoverItem = HitTest(point); if(nLastHoverItem >= 0 ) { CRect rcItem; GetItemRect(nLastHoverItem,rcItem,LVIR_BOUNDS); InvalidateRect(rcItem); } nLastHoverItem = nHoverItem; if (nHoverItem >= 0) { CRect rcItem; GetItemRect(nHoverItem,rcItem,LVIR_BOUNDS); InvalidateRect(rcItem); //SetTimer(1,100,NULL); } CListCtrl::OnMouseMove(nFlags, point); } void CMyListCtrl::OnTimer(UINT_PTR nIDEvent) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (nIDEvent == 1) { CPoint pt(GetMessagePos()); ScreenToClient(&pt); CRect rc; GetClientRect(&rc); if (!rc.PtInRect(pt)) { nHoverItem = -1; CRect rcItem; GetItemRect(nLastHoverItem,rcItem,LVIR_BOUNDS); InvalidateRect(rcItem); KillTimer(1); } } CListCtrl::OnTimer(nIDEvent); }