首页 > 代码库 > WTL - Virtual List Controls(WTL下使用虚拟列表)

WTL - Virtual List Controls(WTL下使用虚拟列表)

普通的 CListCtrl 在其数据达到10000以上时,拖动滚动条已卡,很不好。。

Virtual List Controls,虚拟列表,我认为是一种列表的显示方式。。

普通列表:所有的列表数据加载完成再显示。

虚拟列表:只加载当前指定的要显示的数据(当收到 LVN_GETDISPINFO 消息时,会刷新列表,只刷新要显示的部分 )。

很明显,当数据量大的时候,谁优谁劣。。

比起 MFC,我更喜欢轻量级 WTL,就用 WTL 做个例子吧。。

1、新建 WTL 工程:

技术分享

2、拖出列表控件 List Control:

我设其 ID 为 IDC_LIST_LOVE,View ReportOwner Data True

技术分享

3、用 WTL 的 CListViewCtrl 去关联这个列表 IDC_LIST_LOVE,并插入列:

我设了个 CListViewCtrl 的成员变量 m_lvcLove

	//set virtual list
	m_lvcLove.Attach(GetDlgItem(IDC_LIST_LOVE));
	m_lvcLove.AddColumn(_T("海誓山盟"), 0);
	m_lvcLove.AddColumn(_T("往事如烟"), 1);

4、消息宏中关联 LVN_GETDISPINFO 消息、列表 ID 和响应函数:

NOTIFY_HANDLER(IDC_LIST_LOVE, LVN_GETDISPINFO, OnGetDispInfo)

5、完成响应函数:

pItem 在这里就是列表控件的单元格,要想列表的这个单元格显示什么,就对 pItem 进行什么样的操作,至于 pItem 是如何显示在列表上的,并不用我们写在代码中

pItem->mask 是显示内容的标志,指定要显示图标、文字或是其他

pItem->iItem 是列表控件的行号(从0开始)

pItem->iSubItem 是列表控件的列号(从0开始)

LRESULT CMainDlg::OnGetDispInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
{
	NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pnmh);
	LV_ITEM* pItem = &(pDispInfo)->item;
	int nItem = pItem->iItem;

	if (pItem->mask & LVIF_TEXT) //valid text buffer?
	{
		switch (pItem->iSubItem)
		{
		case 0: //fill in main text
			lstrcpy(pItem->pszText, m_vtLove[nItem].strSaying);
			break;
		case 1: //fill in sub item 1 text
			lstrcpy(pItem->pszText, m_vtLove[nItem].strHistory);
			break;
		}
	}

	return 0;
}

6、主动触发列表更新(SetItemCount 非常关键,这会触发 LVN_GETDISPINFO 消息):

我用了一个Add Data 的按钮,每按一次加入1000条数据

LRESULT CMainDlg::OnAddData(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	int nBase = m_vtLove.size();

	for (int i = 0; i < ADD_COUNT_ONE_TIME; ++i)
	{
		CString strHistory;
		strHistory.Format(_T("%d days"), nBase + i);
		m_vtLove.push_back(LOVEITEM(_T("I love you"), strHistory));
	}
	m_lvcLove.SetItemCount(m_vtLove.size());

	return 0;
}

7、看看效果吧:

我点了10次,加了10000条数据,随便拉滚动条,一点都不卡。。技术分享

技术分享

WTL - Virtual List Controls(WTL下使用虚拟列表)