虚拟列表 android,MFC ListCtrl 虚拟列表闪烁的问题 && 改变ListCtrl颜色
当使用ListCtrl显示大量数据或频繁进行显示时,传统的显示方法不仅显示速度慢,而且会出现闪烁的问题,为了提高数据的时效性,选择使用了虚拟列表。首先,设置Listctrl控件属性,将OwnerData属性修改为TRUE;然后为控件关联一个变量m_List。初始化CRect rect;int Total_num=4;m_List.ModifyStyle(WS_VSCROLL,0,0);m_List
当使用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);
更多推荐
所有评论(0)