寫這篇文章的人真的是佛心來的耶!超厲害的啦!希望我有一天也能夠寫出這樣的作品 ^___^
轉載內容
主 题: 讨论ListView里显示十万级以上记录时,象SQL Server里的返回所有行的方式显示记录,怎么实现?
作 者: cmsoft (韦小宝是我的老乡)
等 级:
信 誉 值: 100
所属论坛: C++ Builder 基础类
问题点数: 99
回复次数: 38
发表时间: 2002-12-31 9:57:02
回复人: bigwhiteshark(大白鲨) ( )
信誉:被封杀
哈哈正中本人下怀
如何用TListView来处理大量数据
采用常规方法处理ListView,在数据量大时无论是还是用了BeginUpdata和EndUpdata()
还是处理WM_EraseBkgnd信息都不会得到理想的效果,那答案是什么呢?嗯,
采用所谓Virtual ListView技术。说起来很神秘,其实点通了很简单。
通常ListView中的所有数据都是由ListView自己来管理的,它负责这些数据空间的分配和释放,
当你把ListView->OwnerData设为true时,ListView就把数据的管理权交给了你,而它只负责显示。
这时你需要自己来为数据分配和释放空间,至于你怎样来管理这些数据完全有你自己来定,
ListView完全不关心,当ListView需要显示某条数据时,它就调用OnData事件,
你只要在这个事件的处理函数里指定ListView即将显示的Item的内容就可以了。
这就是所谓的Virtual ListView技术。
由于ListView对数据管理的功能强大,随之而来的却是效率低下,
如果你采用更高效的数据管理方式就会极大的改变效率。
而且Virtual ListView只在数据需要显示时才调用OnData事件载入数据,所以速度很快。
下面的例子中,假设ListView中需要显示4列数据,所有的数据被保存在vector里。
/*Unit1.h*/
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <vector.h>
using namespace std;
//---------------------------------------------------------------------------
struct ListViewData //用於存儲一條資料的結構體
{
AnsiString Caption;
AnsiString SubItems1;
AnsiString SubItems2;
AnsiString SubItems3;
};
class TForm1: public TForm
{
__published: // IDE-managed Components
TListView * ListView1;
void __fastcall ListView1Data(TObject * Sender, TListItem * Item);
private: // User declarations
vector < ListViewData * > m_lvDataVector; //用於存儲所以資料的向量
public: // User declarations
__fastcall TForm1(TComponent * Owner);
__fastcall~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 * Form1;
//---------------------------------------------------------------------------
#endif
/*unit1.cpp*/
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 * Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent * Owner) : TForm(Owner)
{
ListView1 -> OwnerData = true;
const int iListViewCount = 5000;
ListView1 -> Items -> Count = iListViewCount; //必須指定,以使ListView知道其虛擬資料量
//保存資料
for (int i = 0; i < iListViewCount; ++i) {
ListViewData * plvData = new ListViewData;
plvData -> Caption = "Caption" + AnsiString(i);
plvData -> SubItems1 = "SubItems1" + AnsiString(i);
plvData -> SubItems2 = "SubItems2" + AnsiString(i);
plvData -> SubItems3 = "SubItems3" + AnsiString(i);
m_lvDataVector.push_back(plvData); //向vector中添加一項
}
}
__fastcall TForm1::~TForm1()
{
int iCount = ListView1 -> Items -> Count;
for (int i = 0; i < iCount; ++i) {
ListViewData * plvData = m_lvDataVector[i];
delete plvData; //釋放資料佔用的資源
}
m_lvDataVector.clear(); //清空vector中所有條目
}
//---------------------------------------------------------------------------
//ListView在要顯示某條資料時會調用這個函數
void __fastcall TForm1::ListView1Data(TObject * Sender, TListItem * Item)
{
if (Item -> Index > m_lvDataVector.size())
return;
ListViewData * plvData = m_lvDataVector[Item -> Index];
//指定要顯示的條目的資料
Item -> Caption = plvData -> Caption;
Item -> SubItems -> Add(plvData -> SubItems1);
Item -> SubItems -> Add(plvData -> SubItems2);
Item -> SubItems -> Add(plvData -> SubItems3);
}
//---------------------------------------------------------------------------
速度很快,5000条数据只要1秒左右. 在使用Virtual ListView方式时,如果要对数据排序,只需对你保存的内部数据(这里时vector对象)排序,然后ListView->Refresh()即可。
这时你在ListView中看到的数据就是排好序的数据了。
沒有留言:
張貼留言