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<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);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章