當使用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<NMLVCUSTOMDRAW*>(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<int> (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);