从数据库读数据,然后利用Virtual ListCtrl将数据显示到控件中时,界面还是有停顿,是不是我的使用方法不对?

时间:2022-09-21 19:12:04
我从数据库中读取记录,大约几万条吧,为了加快插入,我使用了Virtual ListCtrl技术。我的步骤是:
1. 从CListCtrl派生一个类CVirtualListCtrl,在派生类的PreSubclassWindow()中设置类型:
   SetExtendedStyle(LVS_EX_GRIDLINES|LVS_OWNERDATA);

2. 新开一个工作线程,在线程函数里完成从库中读取数据的工作。并将每条数据保存在一个结构体变量中,结构体变量
   是CArray数组类的参数,然后调用Add方法插入进数组。

3. 当读完所有记录后,向主线程发送消息,在消息响应函数中调用CVirtualListCtrl类的函数,设置记录的总数。
   SetItemCount(nRecordCount);

4. 在派生类中响应反射消息LVN_GETDISPINFO,在OnGetdispinfo()函数中完成最后的显示工作。

我遇到的疑问是: 
1. 为什么在第一步中按如下操作结果发现控件什么都不显示,而在控件的properties属性设置中再将Owner data勾上就好用了?
     DWORD dStyle=this->GetStyle();
    dStyle|=LVS_EX_GRIDLINES|LVS_OWNERDATA;
    SetExtendedStyle(dStyle);

2. 运行后,发现当显示的数据大约超过10000条时,控件会空白几秒钟,然后一下数据全都显示出来了。我想这几秒钟是
   不是由于要从数据库读取记录耗费的时间,有没有什么办法可以避免等待?就是最好即便我读10万条记录,也可以一下子全都显
   示出来。用Virtual ListCtrl怎么实现,针对我这个例子,能给提供个解决方案吗?

11 个解决方案

#1


怎么没人啊,自己顶一下。

#2


用虚拟列表的话,第2步要改一下,只要读出数据的条目,然后SetItemCount就可以了。在响应LVN_GETDISPINFO消息的时候才需要真正读取数据来显示。

#3


即使不用线程,那我还是一样要连接将数据库中的记录读出来,并保存到一个结构体数组里。在响应LVN_GETDISPINFO消息的函数里再将结构体中的数据取走。就像下面这样:
void CVirtualListCtrl::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult) 
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here

LV_ITEM *pItem=&pDispInfo->item;

STRUCT_DATA data;
data=m_array.GetAt(pItem->iItem);

m_strID.Format("%d",data.nID);
m_strTime=data.chTime;
m_strValue.Format("%.2f",data.fValue);

if(pItem->mask & LVIF_TEXT)
{
switch(pItem->iSubItem)
{
case 0:
lstrcpy(pItem->pszText,m_strID);
break;
case 1:
lstrcpy(pItem->pszText,m_strTime);
break;
case 2:
lstrcpy(pItem->pszText,m_strValue);
    break;

}
}
*pResult = 0;
}
我这样操作有问题吗?

#4


你的listctl能一下子显示10万条数据吗?肯定显示不完吧,那样就不用一下子全加上去,用的时候再加就可以了。

#5


我现在的疑惑是:是不是当从数据库读取很多条记录时,即便是用线程和虚拟列表来做,也是要耗费几秒钟时间的,这是可以接受的?

#6


在响应LVN_GETDISPINFO消息的时候才需要真正 (从数据库)读取数据来显示。

#7


我想知道为什么datagrid以及其他可以绑定的表格控件,显示怎么这么快的
郁闷

#8


对于1,代码放在你的Create中
对于2,为什么要1W全部插入?屏幕显示是很费时间的,你插一条,ListCtrl会更新一下界面,频繁更新,就造成空白,直到数据插入完,更新动作结束。控制一下更新,不要插入一条就更新一次,插入自定义条更新一次,估计就好了

#9


如果这一万数据不是从数据库中读取,试过了吗? 也会白一段时间?

#10


如果这一万数据不是从数据库中读取,试过了吗?   也会白一段时间?
///
其他的方法倒是没试过,只是发现数据库是这样。

#1


怎么没人啊,自己顶一下。

#2


用虚拟列表的话,第2步要改一下,只要读出数据的条目,然后SetItemCount就可以了。在响应LVN_GETDISPINFO消息的时候才需要真正读取数据来显示。

#3


即使不用线程,那我还是一样要连接将数据库中的记录读出来,并保存到一个结构体数组里。在响应LVN_GETDISPINFO消息的函数里再将结构体中的数据取走。就像下面这样:
void CVirtualListCtrl::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult) 
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here

LV_ITEM *pItem=&pDispInfo->item;

STRUCT_DATA data;
data=m_array.GetAt(pItem->iItem);

m_strID.Format("%d",data.nID);
m_strTime=data.chTime;
m_strValue.Format("%.2f",data.fValue);

if(pItem->mask & LVIF_TEXT)
{
switch(pItem->iSubItem)
{
case 0:
lstrcpy(pItem->pszText,m_strID);
break;
case 1:
lstrcpy(pItem->pszText,m_strTime);
break;
case 2:
lstrcpy(pItem->pszText,m_strValue);
    break;

}
}
*pResult = 0;
}
我这样操作有问题吗?

#4


你的listctl能一下子显示10万条数据吗?肯定显示不完吧,那样就不用一下子全加上去,用的时候再加就可以了。

#5


我现在的疑惑是:是不是当从数据库读取很多条记录时,即便是用线程和虚拟列表来做,也是要耗费几秒钟时间的,这是可以接受的?

#6


在响应LVN_GETDISPINFO消息的时候才需要真正 (从数据库)读取数据来显示。

#7


我想知道为什么datagrid以及其他可以绑定的表格控件,显示怎么这么快的
郁闷

#8


对于1,代码放在你的Create中
对于2,为什么要1W全部插入?屏幕显示是很费时间的,你插一条,ListCtrl会更新一下界面,频繁更新,就造成空白,直到数据插入完,更新动作结束。控制一下更新,不要插入一条就更新一次,插入自定义条更新一次,估计就好了

#9


如果这一万数据不是从数据库中读取,试过了吗? 也会白一段时间?

#10


如果这一万数据不是从数据库中读取,试过了吗?   也会白一段时间?
///
其他的方法倒是没试过,只是发现数据库是这样。

#11