防止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 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

防止CListCtrl闪烁的几种方法的相关文章

控件绘制的四种方法

OWNER?DRAW实现自绘按钮 一准备工作 在您决定开发 Windows 提供的常规免费自定义控件范围之外的控件之后,您必需确定自己的控件将有多少独到之处 - 在功能和外观两方面.例如,我们假定您正在创建一个类似于计速表的控件.由于公共控件库 (ComCtrl32.dll) 中没有类似的控件,您完全需要自己进行以下操作:编写所有控件功能需要的代码,进行绘制,默认终端用户的交互,以及控件与其父窗口之间需要的任意消息处理. (#add 两方面,公共控件库中没有类似的 完全重写;? 只想调整公共控件

一、查看Linux内核版本命令(两种方法):

一.查看Linux内核版本命令(两种方法): 1.cat /proc/version [[email protected]CentOS home]# cat /proc/versionLinux version 2.6.32-431.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Nov 22 03:15:09 UTC 2013 2.uname -a [

利用颜色和形态学两种方法进行车牌区域提取的OpenCV代码

要想提取车牌号,首先你要定位车牌区域嘛,本文分别两种方法用,即颜色和形态学的方法,对车牌区域进行判定.说得是两种方法,其实两种方法并无多大的区别,只是有一步的判断标准不一样而已,你看了下面整理出的的思路就知道两者的区别真的很小了. 方法一:利用颜色提取车牌区域的思路: ①求得原图像的sobel边缘sobelMat ②在HSV空间内利用车牌颜色阈值对图像进行二值化处理,得到图像bw_blue→ ③由下面的判别标准得到图像bw_blue_edge for (int k = 1; k != heigh

ios图片拉伸两种方法

ios图片拉伸两种方法 UIImage *image = [UIImage imageNamed:@"qq"]; 第一种: // 左端盖宽度 NSInteger leftCapWidth = image.size.width * 0.5f; // 顶端盖高度 NSInteger topCapHeight = image.size.height * 0.5f; // 重新赋值 image = [image stretchableImageWithLeftCapWidth:leftCapW

XML解析的几种方法

第一种方法系统自带的解析方法(NSXMLParser) //1.指定XML文件 NSString *path=[[NSBundle mainBundle] pathForResource:@"person" ofType:@"xml"]; //转换成data类型对象 NSData *data=[NSData dataWithContentsOfFile:path]; //2.为parser指定初始值 NSXMLParser *parser=[[NSXMLParser

Spring官网下载dist.zip的几种方法

Spring官网下载dist.zip的几种方法 Spring官网改版后,很多项目的完整zip包下载链接已经隐掉了,虽然Spring旨在引导大家用更“高大上”的maven方式来管理所依赖的jar包,但是完全没想到中国的国情,在伟大的墙内,直接通过maven下载墙外的东西,要么龟速,要么直接被和谐. 下面是从网上搜集的一些方法,可用于一次性下载Spring各项目的完整dist.zip 第一种 直接 http://repo.springsource.org/libs-release-local/org

SSH 框架打开项目自动执行action的第二种方法

web.xml还是什么不配置 <welcome-file-list> <welcome-file></welcome-file> </welcome-file-list> struts.xml加上这个 <default-action-ref name="index" /> 同时原来的修改为这样 <action name="index" class="index"> <r

Java 计算中英文长度的若干种方法

在项目开发中经常碰到到输入字符的校验,特别是中英文混合在一起的校验.而为了满足校验的需求,有时需要计算出中英文的长度. 本文将通过几种常用的方法实现长度的计算: <span style="font-size:18px;">import java.io.UnsupportedEncodingException; /** * 中英文校验的处理 * @author a123demi * */ public class EnChValidate { public static vo

分区自动挂载的三种方法

一.修改/etc/rc.local配置文件追加类似命令:mount /dev/sda1  /sda1 到配置文件最后一行 二,修改/etc/fstab配置文件追加类似命令:/dev/sda1   /sda1  ext4   defaults   0  0 到配置文件中 三,安装autofs服务yum install autofs 追加类似命令:sda1   -fstype=ext4  :/dev/sda1 到配置/etc/autofs.misc文件中重启服务: service autofs re