首先说下虚拟列表出现的原因:

数据量比较小的时候,对于CListView控件可以直接使用InsertItem并配合SetItemText函数来插入并修改数据。这样操作很直接。

但是,如果数据量比较大了,比如1w个数据,那么,根据插入的数据种类,长度,以及计算机性能,估计时间在10s中到1分钟不等。如果你的用户在使用的这样的程序时肯定不会开心,初始化的时候插入则需要登上10s+后才能使用,如果外加一个线程来并行插入,倒也是一个方法(这个事情我做过),不过,很浪费CPU时间,以及内存。

如果是10w个,甚至100w个数据呢?那么至少会线性的增加时间了~

但是回头想一想,一个列表,在你的计算机显示器上,最多也就能看到50-80个。我的笔记本分辨率是1366*768的就按50个来算,768/50 约等于15吧,一行用15个像素宽度表示,已经有点小勉强了~~~

所以这个时候有个事情就非常明显了:在大数据量的时候,根本没必要在初始化时把全部的数据都插入到CListCtrl控件中。

要注意,这个问题是我在下自习回寝室的路上想明白的~~~

然后我就想了,既然这样的话,如果自己动手做虚拟列表,也不是不能做。基本上需要准备好以下的东西:

1 右面的浏览滑块,就是那个scroll,这个需要处理好,根据不同的位置,动态加载不同地方的数据。

2 鼠标的滚轮消息,上下移动,也要做好。

3 窗口的最大数据量,以及文字显示之类的东西,都要做。

基本上就是意味着需要自己做一个控件,虚拟列表控件。这个确实是可行的。然后呢~我在百度查资料的时候,意外的看到了虚拟列表这个东西~~~

那时我才知道,原来microsoft的大神们已经想到了这个问题,而且在CListCtrl中已经整合好了。

在CListCtrl中使用虚拟列表

我之前的那篇关于CListCtrl控件使用方法的文章中说过,对于和控件绑定了的CListCtrl对象,主要需要做的工作,就是设置风格,并且插入列。

不过对于虚拟列表,与常规的列表相比,并没有什么风格上的不同,所以风格还是依照自己的需求进行设置就可以了。

列的控制,按照前面那篇文章上来就好了~这里不是重点。

然后呢,很需要做的一点就是,设置最大条目的数量。这里要注意的是,所谓的最大条目的数量,就是和你的数据库的数据量。这两者一定是要匹配的。

展示一小段实例代码:

 else
{
CFileInfo cfi;
while(m_MyDataBase.ReadString(path))
{
cfi.csFileRoot = path;
cfi.csFileName = path.Right(path.GetLength() - path.ReverseFind('\\') - );
cfi.csFilePath = path.Left(path.ReverseFind('\\'));
m_arrayFileInfo.Add(cfi);
nFileNum++;
}
m_MyDataBase.Close();
} m_LCTable.SetItemCountEx(nFileNum, LVSICF_NOSCROLL|LVSICF_NOINVALIDATEALL);
nInitialFlag = ;

最上面的代码是数据初始化的部分,存储到CArray模板中。也算是个最简单的数据库吧。

初始化过后,我的数据就放到了容器中,上面的nFileNum变量就是跟踪容量的数据,不过,其实也不需要,毕竟CArray是提供数据总量查询的。

然后接下来调用我们的明星函数:SetItemCountEx

这个函数,第一个参数毫无疑问就是设置数量上限的,第二个参数又是一个什么风格设置,看看MSDN怎么说:

    • LVSICF_NOINVALIDATEALL The list view control will not repaint unless affected items are currently in view. This is the default value.
    • LVSICF_NOSCROLL The list view control will not change the scroll position when the item count changes.

大意我就不翻译了,现在有个人正在和我聊天,翻译了太费时间。这两个的特性可以自己试一试。

然后在这算是第一步完成,主要还是SetItemCountEx函数。

接下来,需要做的事进行消息响应。

要知道,windows程序的运行是需要消息来推动的。当滑块对拖动或者鼠标滚动的时候,都会有消息产生。

所以,CListCtrl也是采用了这种机制,消息响应的方式去填充虚拟列表。

我在这里只介绍我使用过的一个消息,就是LVN_GETDISPINFO

最上面的那个消息响应就是了。

然后我们看响应函数的代码:

 void CMyRisingDlg::OnLvnGetdispinfoList2(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
// TODO: Add your control notification handler code here
LV_DISPINFO * pLPD = (LV_DISPINFO *)pDispInfo;
LV_ITEM* pItem= &(pDispInfo)->item;
HICON hIconTmp;
int nItem = pItem->iItem;
if (pItem->mask & LVIF_TEXT) //valid text buffer?
{
switch(pItem->iSubItem)
{
case : //fill in main text首列添加图像的工作肯定也要在这里完成
_tcscpy(pItem->pszText, m_arrayFileInfo[nItem].csFileName);
//ExtractIconEx(m_arrayFileInfo[nItem].csFileRoot, 0, NULL, &hIconTmp, 1);
//m_imagelist.Add(hIconTmp);
//Add Icon into the list
pItem->iImage = ;
//m_imagelist.Remove(0);
break;
case : //fill in sub item 1 text
_tcscpy(pItem->pszText, m_arrayFileInfo[nItem].csFilePath);
break;
case : //fill in sub item 2 text
_tcscpy(pItem->pszText, m_arrayFileInfo[nItem].FileTime);
break;
}
} *pResult = ;
}

首先能看参数,其中一个是NMHDR的指针,这个类型,我还真的不是很清楚。

不过清楚的可以看到,经过两次类型转换,我们会得到一个LV_ITEM的指针。在这简单的说一下,前面的那段类型转换的代码,是函数自动生成的时候就已经改出来的。

接着,在这里我们只要根据LV_ITEM中的消息进行相应来添加相应的数据就可以了。

所以接下来主要需要看的就是switch中的case选择。

在上面代码中的switchcase结构中,传给switch的参数就是一个条目中的子序号。根据这个子序号,去添加对应位置的信息。

然后这里还有非常重要的一点,就是在上面的这段代码:

 8     int nItem = pItem->iItem;

这段代码就是用来获取当前位置对应数据的目录号。只有根据这个目录号,你才能找到在你的数据中应该添加的数据的位置。这个在我的代码中你应该也能注意到的。

最主要的两个数据在这里基本就介绍完了,具体的代码也贴在上面。这样就能进行最简单的虚拟列表操作啦。

CListView虚拟列表的更多相关文章

  1. clistctrl 虚拟列表

    一.什么是虚拟列表控件 虚拟列表控件是指带有LVS_OWNERDATA风格的列表控件.. 二.为什么使用虚拟列表控件 我们知道,通常使用列表控件CListCtrl,需要调用InsertItem把要显示 ...

  2. 基于duilib的虚拟列表实现

    本文由作者邹启文授权网易云社区发布. 在邮箱大师选择duilib作为UI开发库后,我们面临这样一个问题.随着时间的积累,用户数据会越来越多,如何保证我们的软件在展示这些数据时依然保持非常好的体验? 原 ...

  3. 性能优化:虚拟列表,如何渲染10万条数据的dom,页面同时不卡顿

    列表大概有2万条数据,又不让做成分页,如果页面直接渲染2万条数据,在一些低配电脑上可能会照成页面卡死,基于这个需求,我们来手写一个虚拟列表 思路 列表中固定只显示少量的数据,比如60条 在列表滚动的时 ...

  4. vc mfc listctrl使用虚拟列表 虚拟列表用法

    note 虚拟列表可有效加载大量数据 需要处理listctrl的 LVN_GETDISPINFO 消息 使用虚拟列表 不能 使用 insert的方法插入数据,而是告诉listctrl 当前要显示多少行 ...

  5. 【react表格组件】react-virtualized虚拟列表

    https://css-tricks.com/rendering-lists-using-react-virtualized/

  6. react antd上拉加载与下拉刷新与虚拟列表使用

    创建项目 create-react-app antdReact 安装:antd-mobile.react-virtualized npm i antd-mobile -S npm i react-vi ...

  7. ClistCtrl用法及总结(由怎样隐藏ListCtrl列表头的排序小三角形这个bug学习到的知识)

    1 怎样隐藏ListCtrl列表头的排序小三角形 在创建控件是加入|LVS_NOSORTHEADER风格即可. 一下是用法总结: 本文根据本人在项目中的应用,来谈谈CListCtrl的部分用法及技巧. ...

  8. C#实现虚拟控件列表显示100w个控件方法

    方法一: C#的FlowlayoutPanel添加一定数据量的控件后就会空白,通过虚拟列表方式可以解决这个问题. 1.创建一个包含ScrollPanel和滚动条的用户控件,定义一个List,添加控件时 ...

  9. 【VS开发】MFC CListCtrl列表控件的消息响应

    MFC里的CListCtrl选中一行,消息是哪个.实在想不起来了.找了一篇文章,比较有用: http://www.cnblogs.com/hongfei/archive/2012/12/25/2832 ...

随机推荐

  1. 【Sort List】cpp

    题目: Sort a linked list in O(n log n) time using constant space complexity. 代码: /** * Definition for ...

  2. mailx 乱码,sendmail发html邮件,脚本开机启动

    echo "yes"|mailx -s "我" -S ttycharset=utf-8 -S sendcharsets=utf-8 -S encoding=ut ...

  3. ASP.NET MVC学习之视图篇(1)

    一.前言 不知道还有多少读者从第一篇开始一直学习到如今,笔者也会一直坚持将ASP.NET MVC的学习完美的结束掉,然后开始写如何配合其他框架使用ASP.NET MVC的随笔.当然笔者后面的随笔如果没 ...

  4. 【BZOJ】【1034】【ZJOI2008】泡泡堂BNB

    贪心 类似田忌赛马策略的一个贪心= = 随便YY了一个做法居然A了…… 简单来说就是先强对强,弱对弱,能赢就赢,不能赢就让弱的那个去对强的那个,剩下的人继续依次捉对比赛(继续刚刚的策略),现在人数还是 ...

  5. Leetcode#76 Minimum Window Substring

    原题地址 用两个指针分别记录窗口的左右边界,移动指针时忽略那些出现在S种但是没有出现在T中的字符 1. 扩展窗口.向右移动右指针,当窗口内的字符即将多于T内的字符时,停止右移 2. 收缩窗口.向右调整 ...

  6. c++new和new()区别(了解)

    我们在C++程序中经常看到两种new的使用方式:new A以及new A().那么这两种究竟有什么区别呢? 调用new分配的内存有时候会被初始化,而有时候不会,这依赖于A的类型是否是POD(Plain ...

  7. Spring boot教程

    1.首先是新建Maven工程 2.引入Pom依赖 3.新建一个Controller 4.运行Main方法 5.浏览器访问 pom.xml <project xmlns="http:// ...

  8. Ogre1.8.1源码编译

    本文的编译环境为Windows7_SP1 + VS2010_SP1 + CMake2.8.11   :) 资源下载 1. 下载Ogre1.8.1的源代码,下载链接地址:http://www.ogre3 ...

  9. Activity学习(四)——简单切换

    理论学习Activity之后,我们就来具体的实战,Activity之间相互切换依靠的是“ 意图 ”(Intent),这个 Intent 包含了要跳转到的Activity的一些信息,因为Activity ...

  10. Linux下Sublime Text 2的安装

    安装方法1: 通过apt-get install来安装,可以如下来做: sudo add-apt-repository ppa:webupd8team/sublime-text-2 sudo apt- ...