MFC ListCtrl 虚拟列表闪烁的问题 && 改变ListCtrl颜色

    当使用ListCtrl显示大量数据或频繁进行显示时,传统的显示方法不仅显示速度慢,而且会出现闪烁的问题,为了提高数据的时效性,选择使用了虚拟列表。

    首先,设置Listctrl控件属性,将OwnerData属性修改为TRUE;然后为控件关联一个变量m_List。

    初始化

CRect rect; 
	int Total_num=4;
	m_List.ModifyStyle(WS_VSCROLL,0,0);
	m_List.GetClientRect(&rect);   // 获取编程语言列表视图控件的位置和大小 
	// 为列表视图控件添加全行选中和栅格风格    
	m_List.InsertColumn(0, _T("信号"),    LVCFMT_CENTER, 2*rect.Width()/Total_num, 0);   
	m_List.InsertColumn(1, _T("数值"),     LVCFMT_CENTER, 1*rect.Width()/Total_num, 1);   
	m_List.SetExtendedStyle(LVS_EX_FULLROWSELECT |LVS_EX_DOUBLEBUFFER| LVS_EX_GRIDLINES | LVS_EX_LABELTIP|LVIS_SELECTED|LVIS_FOCUSED);

    添加LVN_GETDISPINFO消息,编辑OnLvnGetdispinfoList消息,将要显示的信息(行信息)放置于数组coloum1Text、coloum2Text中。

void CXXXDlg::OnLvnGetdispinfoList(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	LV_ITEM* pItem= &(pDispInfo)->item;
	int iItemIndx= pItem->iItem;//获取行号,会自动根据当前显示区的行数,更新所有的行
	if (pItem->mask & LVIF_TEXT) //字符串缓冲区有效
	{
		// then display the appropriate column
		switch(pItem->iSubItem)
		{
		case 0:
			lstrcpy(pItem->pszText, coloum1Text[iItemIndx]);//将要显示的行信息放置于数组中
			break;
		case 1:
			lstrcpy(pItem->pszText, coloum2Text[iItemIndx]);
			break;
		
		default:
			ASSERT(0);
			break;
		}
	}
}

开一个定时器,周期根据自己情况定,100ms以上就可以,太短了人眼反应过不来。在定时器中调用下面的代码

m_List.SetItemCountEx(1000);//需要显示多少行就填多少,如果不是固定值,那需要一个变量进行控制
m_List.Invalidate();
m_List.UpdateWindow();

要显示的信息填充到上面的数组中,就可以正常显示了,而且效率比较高。

当你按照这些做下来,可能会发现一个问题,Listctrl控件刷新时会闪烁,不用尝试网上说的那些设置RedrawItems或其他的,基本都试过,不好用。

解决方法是:在初始化ListCtrl属性时,增加LVS_EX_DOUBLEBUFFER属性。加上之后,数据更新特别平滑,不会跳动。

如果想改变ListCtrl中单元格的颜色,需要增加NM_CUSTOMDRAW消息,如下图所示。

void CXXXDlg::OnNMCustomdrawDbcListShow(NMHDR *pNMHDR, LRESULT *pResult)
{
	NMLVCUSTOMDRAW* pLVCD = reinterpret_cast(pNMHDR);
	*pResult = 0;

	if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
	{
		*pResult = CDRF_NOTIFYITEMDRAW;
	}
	else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
	{
		*pResult = CDRF_NOTIFYSUBITEMDRAW;
	}
	else if ( (CDDS_ITEMPREPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage )
	{
		COLORREF m_clrTextBk;
		COLORREF m_clrText;
		int nItem = static_cast (pLVCD->nmcd.dwItemSpec);
 
		m_clrTextBk = WHITE;
		m_clrText = BLACK;
         //这里改变颜色,可增加限制条件
		pLVCD->clrTextBk = m_clrTextBk;
		pLVCD->clrText = m_clrText;
		*pResult = CDRF_DODEFAULT;
	}
}

   别急,还有内容,今天才注意到ListCtrl的第一列是左对齐的,无论如何修改初始化时的属性,都是左对齐,解决方法是在初始化之后增加下面的代码:

LVCOLUMN   lvc;
lvc.mask   =   LVCF_FMT;
m_List.GetColumn(0, &lvc);
lvc.fmt   &=   ~LVCFMT_JUSTIFYMASK;
lvc.fmt   |=   LVCFMT_CENTER;
m_List.SetColumn(0, &lvc);

   最后,ListCtrl向下滚动有下面几种方法

    1.
    m_list_Infor.PostMessage(WM_VSCROLL, SB_BOTTOM, NULL);
    2.
    m_list_Infor.SendMessage(WM_VSCROLL, SB_BOTTOM, NULL);
    3.
    m_list_Infor.EnsureVisible(m_list_Infor.GetItemCount()-1,FALSE);

 

你可能感兴趣的:(MFC)