防止CListCtrl闪烁的几种方法

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 paintingCRect 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/BGdiplus::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/BGdiplus::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);}}}

看自家总在期待,不知将来好歹,新乐吧总在不断等待,

防止CListCtrl闪烁的几种方法

相关文章:

你感兴趣的文章:

标签云: