1. 使用SetRedraw禁止窗口重绘,操作完成后,再恢复窗口重绘
m_ctlList.SetRedraw(FALSE); //以下为更新数据操作 //…… //恢复窗口重绘 m_ctlList.SetRedraw(TRUE);
2. 使用LockWindowUpdate禁止窗口重绘,操作完成后,用UnlockWindowUpdate恢复窗口重绘
m_ctlList.LockWindowUpdate(); //以下为更新数据操作 //…… //恢复窗口重绘 m_ctlList.UnlockWindowUpdate();
3. 使用ListCtrl的内部双缓冲(经实测, 好像不起作用)
m_ctlLisit.SetExtendedStyle(m_ctlLisit.GetExtendedStyle()|LVS_EX_DOUBLEBUFFER); VC6未定义LVS_EX_DOUBLEBUFFER宏,使用者可以自定义,如下: #define LVS_EX_DOUBLEBUFFER 0×00010000
4. Virtual List
首先要设置ListCtrl风格为LVS_REPORT | LVS_OWNERDATA或在ListCtrl属里中的More Styles页面中选中Owner data复选框。 其次要向应LVN_GETDISPINFO消息; void OnGetdispinfoList(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; LV_ITEM *pItem = &(pDispInfo)->item; char szText[128] = {0}; if (pItem->mask & LVIF_TEXT) { //使缓冲区数据与表格子项对应 //m_ArrayBuff为二维数组 //定义如下 int m_ArrayBuff[2048][4]; _stprintf(szText,_T(“%d”),m_ArrayBuff[pItem->iItem][pItem->iSubItem]); pItem->pszText = szText; } *pResult = 0; } 最后便是生成缓冲区数据 void Insertdata() { //删除之前的数据 m_ctlList.SetItemCountEx(0); m_ctlList.Invalidate(); m_ctlList.UpdateWindow(); srand( (unsigned)time( NULL )); //生成新的数据缓冲区 int nItemCount = 2048; for (int i = 0;i < nItemCount; i ++) { for (int k = 0;k < 4;k ++) { m_ArrayBuff[i][k] = rand()%2048 + 1; } } if (nItemCount < 2) { m_ctlList.SetItemCountEx(1); } else { m_ctlList.SetItemCountEx(nItemCount); } m_ctlList.Invalidate(); } 若要修改数据,只要修改缓冲区m_ArrayBuff的数据即可以
5. 自绘(最常用,最简单)
首先当然是重载CListCtrl类,设置ListCtrl属性"Owner Draw Fixed"为true,"Owner data"为false
(1). 并接管WM_ERASEBKGND消息,去掉默认的处理,改为不处理
手动添加重载消息ON_WM_ERASEBKGND()
BOOL CListCtrlEx::OnEraseBkgnd(CDC* pDC) { //响应WM_ERASEBKGND消息 return false; //屏蔽默认处理 //return CListCtrl::OnEraseBkgnd(pDC); }
(2). 手动添加重载消息ON_WM_DRAWITEM()
void CListCtrlEx::OnPaint() { //响应WM_PAINT消息 CPaintDC dc(this); // device context for painting CRect rect; CRect headerRect; CDC MenDC;//内存ID表 CBitmap MemMap; GetClientRect(&rect); GetDlgItem(0)->GetWindowRect(&headerRect); MenDC.CreateCompatibleDC(&dc); MemMap.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height()); MenDC.SelectObject(&MemMap); MenDC.FillSolidRect(&rect,RGB(228,236,243)); //这一句是调用默认的OnPaint(),把图形画在内存DC表上 DefWindowProc(WM_PAINT,(WPARAM)MenDC.m_hDC,(LPARAM)0); //输出 dc.BitBlt(0,headerRect.Height(),rect.Width(), rect.Height(),&MenDC,0, headerRect.Height(),SRCCOPY); MenDC.DeleteDC(); MemMap.DeleteObject(); }
(3). 手动添加重载消息ON_WM_MEASUREITEM_REFLECT()
void DrawItem(_In_ LPDRAWITEMSTRUCT lpDrawItemStruct);
例如:这是我自己的的代码,可能你们有些符号找不到,这方面有疑问的话,可以咨询我QQ173708459,大家共同探讨
void CMyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); LVITEM lvi = { 0 }; lvi.mask = LVIF_STATE | LVIF_IMAGE; lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED; lvi.iItem = lpDrawItemStruct->itemID; //表示菜单项ID,也可以表示列表框或者组合框中某项的索引值 BOOL bGet = GetItem(&lvi); //获取某些或全部列表视图项的属性 //颜色变量 COLORREF cTextColor; COLORREF cBackColor; //绘制区域 CRect rcBack = lpDrawItemStruct->rcItem; int nWidth = rcBack.Width(); int nHeight = rcBack.Height(); //偏移图标位置(44*44),避免选中行时图标也被选中 rcBack.left += 48; pDC->SetBkMode(TRANSPARENT); //统一字体 CFont* OldFont = (CFont*)pDC->SelectObject(m_Font); //预先设置文本字体 //判断是否选中 BOOL bHighlight = ((lvi.state & LVIS_DROPHILITED) || ((lvi.state & LVIS_SELECTED) && ((GetFocus() == this) || (GetStyle() & LVS_SHOWSELALWAYS)))); //(1).先设置文本及背景色 if (bHighlight) //选中行 { cTextColor = m_SelectItemTextColor; cBackColor = m_SelectItemBackColor; } else if (lvi.iItem == m_nHoverIndex) //热点行 { cTextColor = m_HoverItemTextColor; cBackColor = m_HoverItemBackColor; } else { if (lpDrawItemStruct->itemID % 2) //奇数行 { cTextColor = m_OddItemTextColor; cBackColor = m_OddItemBackColor; } else //偶数行 { cTextColor = m_EvenItemTextColor; cBackColor = m_EvenItemBackColor; } } //(2).再统一绘制颜色 pDC->SetTextColor(cTextColor); pDC->FillRect(rcBack, &CBrush(cBackColor)); //(3).绘制文本内容 if (lpDrawItemStruct->itemAction & ODA_DRAWENTIRE) { //获取列数 CString szText; int nCollumn = GetHeaderCtrl()->GetItemCount(); //循环得到文本 for (int i = 0; i < nCollumn; i++) { //获取子项矩形边界 CRect rcItem; if (!GetSubItemRect(lvi.iItem, i, LVIR_LABEL, rcItem)) { continue; } //获取子项文本内容 szText = GetItemText(lvi.iItem, i); //绘制按钮 if (m_nListMark == LIST_INSTALL) { strTask_S *pTask = (strTask_S*)lpDrawItemStruct->itemData; if (NULL != pTask) { if (i == 3) //绘制进度条 { CRect rect(pTask->strProgress.rect); if (!rect.IsRectEmpty()) { //绘制边框 //CPoint point(5, 5); CPen hNewPen(PS_SOLID, 1, RGB(217, 0, 0)); //RGB(217, 217, 217) CPen* hOldPen = pDC->SelectObject(&hNewPen); //pDC->RoundRect(&rect, point); pDC->Rectangle(rect); pDC->SelectObject(hOldPen); hNewPen.DeleteObject(); //填充颜色 rect.top += 1; rect.left += 1; rect.right -= 1; rect.bottom -= 1; CString sInfo = ""; sInfo.Format("2.....%d\r\n", pTask->strProgress.uPercent); OutputDebugString(sInfo); int nLen = pTask->strProgress.uPercent * rect.Width() / 100; sInfo.Format("3.....%d\r\n", nLen); OutputDebugString(sInfo); rect.right = rect.left + nLen; CBrush brush(RGB(31, 210, 69)); pDC->FillRect(&rect, &brush); //brush.DeleteObject(); //绘制文本 CRect rcText(pTask->strProgress.rect); rcText.top = rcText.bottom + 8; rcText.bottom = rcText.top + 13; pDC->SetTextColor(RGB(153, 153, 153)); pDC->DrawText("已下载 0 B, 0 B/s", &rcText, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE); } } else if (i == 4) //绘制按钮 { if (!pTask->strButtons.rect.IsRectEmpty()) { //按钮边框 CPoint point(6, 6); CPen hNewPen(PS_SOLID, 1, RGB(153, 153, 153)); CPen* hOldPen = pDC->SelectObject(&hNewPen); CRect rect(pTask->strButtons.rect); pDC->RoundRect(rect, point); pDC->SelectObject(hOldPen); hNewPen.DeleteObject(); //向内缩进 rect.DeflateRect(CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE))); //改用GDI+绘制,目的填充按钮渐变色 //定义一个线性渐变画刷,沿直线方向渐变,从上往下渐变 Point point1(rect.left, rect.top); Point point2(rect.left, rect.bottom); LinearGradientBrush linGrBrush(point1, point2, Color(255, 248, 248, 248), Color(255, 210, 210, 210)); Color colors[] = { Color(255, 220, 220, 220), Color(255, 200, 200, 200) }; //按红两种颜色渐变 REAL positions[] = { 0.0f, 0.5f }; //两种颜色,各占二分之一 linGrBrush.SetInterpolationColors(colors, positions, 2); //设置插补颜色(插值法) Gdiplus::Graphics graphics(pDC->m_hDC); graphics.FillRectangle(&linGrBrush, rect.left, rect.top, rect.Width(), rect.Height()); //填充区域 //绘制文本 Gdiplus::Pen pen(Gdiplus::Color(255, 0, 0, 255)); Gdiplus::SolidBrush brush(Gdiplus::Color(255, 30, 30, 30)); //设置颜色和透明(0完全透明)/R/G/B Gdiplus::FontFamily family(L"微软雅黑"); //设置字体 FontFamily fontFamily(L"Arial"); Gdiplus::Font font(&family, (Gdiplus::REAL)12, Gdiplus::FontStyleRegular, Gdiplus::UnitPixel); //FontStyleBold:粗体;FontStyleItalic:斜体;FontStyleUnderline:下划线 Gdiplus::PointF pointF((Gdiplus::REAL)rect.left + 12, (Gdiplus::REAL)rect.top + 2); graphics.DrawString(CT2CW(pTask->strButtons.sTitle), -1, &font, pointF, &brush); } } else //绘制文本 { if (0 == i) { rcItem.left += 48 + 5; //跳过图标位置 } pDC->DrawText(szText, lstrlen(szText), &rcItem, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE); } } } else if (m_nListMark == LIST_UPGRADE) { strAppInfo_S *pAppInfo = (strAppInfo_S*)lpDrawItemStruct->itemData; if (NULL != pAppInfo) { if (i == 2) //设置按钮 { if (!pAppInfo->strButtons.rect.IsRectEmpty()) { //按钮边框 CPoint point(6, 6); CPen hNewPen(PS_SOLID, 1, RGB(153, 153, 153)); CPen* hOldPen = pDC->SelectObject(&hNewPen); CRect rect(pAppInfo->strButtons.rect); pDC->RoundRect(rect, point); pDC->SelectObject(hOldPen); hNewPen.DeleteObject(); //向内缩进 rect.DeflateRect(CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE))); //改用GDI+绘制,目的填充按钮渐变色 //定义一个线性渐变画刷,沿直线方向渐变,从上往下渐变 Point point1(rect.left, rect.top); Point point2(rect.left, rect.bottom); LinearGradientBrush linGrBrush(point1, point2, Color(255, 248, 248, 248), Color(255, 210, 210, 210)); Color colors[] = { Color(255, 220, 220, 220), Color(255, 200, 200, 200) }; //按红两种颜色渐变 REAL positions[] = { 0.0f, 0.5f }; //两种颜色,各占二分之一 linGrBrush.SetInterpolationColors(colors, positions, 2); //设置插补颜色(插值法) Gdiplus::Graphics graphics(pDC->m_hDC); graphics.FillRectangle(&linGrBrush, rect.left, rect.top, rect.Width(), rect.Height()); //填充区域 //绘制文本 Gdiplus::Pen pen(Gdiplus::Color(255, 0, 0, 255)); Gdiplus::SolidBrush brush(Gdiplus::Color(255, 30, 30, 30)); //设置颜色和透明(0完全透明)/R/G/B Gdiplus::FontFamily family(L"微软雅黑"); //设置字体 FontFamily fontFamily(L"Arial"); Gdiplus::Font font(&family, (Gdiplus::REAL)12, Gdiplus::FontStyleRegular, Gdiplus::UnitPixel); //FontStyleBold:粗体;FontStyleItalic:斜体;FontStyleUnderline:下划线 Gdiplus::PointF pointF((Gdiplus::REAL)rect.left + 12, (Gdiplus::REAL)rect.top + 2); graphics.DrawString(CT2CW(pAppInfo->strButtons.sTitle), -1, &font, pointF, &brush); } } else //绘制文本 { if (0 == i) { rcItem.left += 48 + 5; //跳过图标位置 } pDC->DrawText(szText, lstrlen(szText), &rcItem, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE); } } } } } //(4).重绘图标 Graphics graphics(pDC->m_hDC); if (m_nListMark == LIST_INSTALL) { strTask_S *pTask = (strTask_S*)this->GetItemData(lvi.iItem); if (pTask && pTask->pImageIcon) { Image *pImage = pTask->pImageIcon; if (pImage) { graphics.DrawImage(pImage, 6, rcBack.top + 5, 36, 36); } } else { graphics.DrawImage(g_pDefaultIcon, 6, rcBack.top + 5, 36, 36); } } else if (m_nListMark == LIST_UPGRADE) { strAppInfo_S *pTask = (strAppInfo_S*)this->GetItemData(lvi.iItem); if (pTask && pTask->pImageIcon) { Image *pImage = pTask->pImageIcon; if (pImage) { graphics.DrawImage(pImage, 6, rcBack.top + 5, 36, 36); } } else { graphics.DrawImage(g_pDefaultIcon, 6, rcBack.top + 5, 36, 36); } } }
时间: 2024-09-30 11:42:18