listview显示起来美观,可就是速度不行比如下面的方式
For i = 0 To 10000
ListView1.ListItems.Add ListView1.ListItems.Count + 1, , ListView1.ListItems.Count + 1
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(1) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(2) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(3) = ("你好啊")
Next i用逐个添加速度很慢,看到一个avafind软件,几万行的数据显示出来只要零点几秒请问各位高手如何在VB中实现listview的快速显示呢?只要没有停顿感就好。如果能解决,可再加100分
For i = 0 To 10000
ListView1.ListItems.Add ListView1.ListItems.Count + 1, , ListView1.ListItems.Count + 1
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(1) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(2) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(3) = ("你好啊")
Next i用逐个添加速度很慢,看到一个avafind软件,几万行的数据显示出来只要零点几秒请问各位高手如何在VB中实现listview的快速显示呢?只要没有停顿感就好。如果能解决,可再加100分
搜了搜没找到阿
自己添加 LockWindowUpdate api,然后这样:LockWindowUpdate hWndListViewfor xxx
给列表添加数据
next
LockWindowUpdate 0&
Call ValidateRect(cLvwMer.hwnd, rc)
DoEvents
p = p + 1
If p Mod 1000 = 0 Then
Call InvalidateRect(cLvwMer.hwnd, rc, True)
cLvwMer.Refresh
Call ValidateRect(cLvwMer.hwnd, rc)
End If这样可以每1000行显示一次,2,3万行数据也就10来秒钟,基本没有停顿感
'获 得listview的显示区域。
Call GetClientRect(cLvwMer.hwnd, rc)rc的定义
Public Type RECT '用来定义一个区域的坐标
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
求各位高手帮忙吧,谢谢各位了阿!
VB里边listview的virtual模式不知道怎么用,不是很明白也许他用的是分页,可滚动条如何处理呢?
'Form1 Code
Option ExplicitPrivate Sub Form_Load()
Dim Index As Long
ListView1.ColumnHeaders.Add , , "Column 1"
ListView1.LabelEdit = lvwManual
ListView1.View = lvwReport
ListView2.ColumnHeaders.Add , , "Column 1"
ListView2.LabelEdit = lvwManual
ListView2.View = lvwReport
For Index = 1 To 1000
ListView1.ListItems.Add , , "Item " & CStr(Index)
' ListView2.ListItems.Add , , "Item " & CStr(Index)
Next
ListViewSubClass ListView1.hwnd '子类化
'ListViewSubClass ListView2.hwndEnd SubPublic Sub Add1000() '滚动条移动一次增加1000条记录
Dim Index As Long
Dim I As Long
I = ListView1.ListItems.Count
If I < 30000 Then 'ListView1中当记录小于30000条时增加记录
For Index = I + 1 To I + 1000
ListView1.ListItems.Add , , "Item " & CStr(Index)
'ListView2.ListItems.Add , , "Item " & CStr(Index)
Next
End If
End Sub'Module1 CodeOption Explicit
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private lpfnOldWinProcLV As Long 'old WindowProc address for ListView
Private Const GWL_WNDPROC As Long = (-4)
Private Const WM_VSCROLL As Long = &H115
Private Const WM_DESTROY As Long = &H2
Private Const SB_THUMBPOSITION As Long = 4
Private Const SB_THUMBTRACK As Long = 5
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_SCROLL As Long = (LVM_FIRST + 20)Public Function ListViewSubClass(hwnd As Long) As Boolean
'This function enables subclassing
ListViewSubClass = True
'Get the address for the previous window procedure
lpfnOldWinProcLV = GetWindowLong(hwnd, GWL_WNDPROC)
If lpfnOldWinProcLV = 0 Then
ListViewSubClass = False
Exit Function
End If
'The return value of SetWindowLong is the address of the previous procedure,
'so if it's not what we just got above, something went wrong.
If SetWindowLong(hwnd, GWL_WNDPROC, AddressOf ListViewWndProc) <> lpfnOldWinProcLV Then
ListViewSubClass = False
End If
End Function
Public Function ListViewUnSubClass(hwnd As Long) As Boolean
'Restore default window procedure
If SetWindowLong(hwnd, GWL_WNDPROC, lpfnOldWinProcLV) = 0 Then
ListViewUnSubClass = False
Else
ListViewUnSubClass = True
lpfnOldWinProcLV = 0
End If
End Function
Private Function ListViewWndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Static bIgnore As Boolean
ListViewWndProc = CallWindowProc(lpfnOldWinProcLV, hwnd, uMsg, wParam, lParam)
If bIgnore Then
Exit Function
End If
'Determine the message that was received
Select Case uMsg
Case WM_VSCROLL '滚动条事件
'Debug.Print "1"
Call Form1.Add1000 '增加记录
Case WM_DESTROY
Call CallWindowProc(lpfnOldWinProcLV, hwnd, uMsg, wParam, lParam)
Call ListViewUnSubClass(hwnd)
ListViewWndProc = CallWindowProc(lpfnOldWinProcLV, hwnd, uMsg, wParam, lParam)
End Select
End FunctionPublic Function LoWord(num As Long) As Integer
LoWord = num Mod &H10000
End FunctionPublic Function HiWord(num As Long) As Integer
HiWord = (num And &HFFFF0000) / &H10000
End Function
不过LZ的要求,1秒内完成的话只能那样分页了。
sub form_load
dim i as long
LockWindowUpdate listview1.hwnd
For i = 0 To 100
ListView1.ListItems.Add ListView1.ListItems.Count + 1, ,ListView1.ListItems.Count + 1
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(1) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(2) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(3) = ("你好啊")
Next i
me.show
for i=101 to 10000
...
doevents
nextend sub
Dim Index As Long, i As Long
For i = 0 To 9
Timer1(i).Interval = 10
Timer1(i).Enabled = True
Next
End Sub
Private Sub Timer1_Timer(Index As Integer)
Dim i As Long
Static num As Long
Timer1(Index).Enabled = False
For i = num To num + 4999
ListView1.ListItems.Add ListView1.ListItems.Count + 1, , ListView1.ListItems.Count + 1
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(1) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(2) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(3) = ("你好啊")
Next i
num = i
DoEvents
End Sub
2、采用Virtual的Listview可以快速加载大量的数据,以下是参考例子http://www.mvps.org/vbvision/_samples/Virtual_ListView_Demo.zip
不知你想要的是不是这样的?
1、在父窗体初始化时下一个CBT钩子,拦截listview控件的WM_CREATE消息,然后设置LVS_OWNERDATA样式,并子类化listview窗口
2、在子类化listview过程中处理LVN_GETDISPINFO消息就
特别感谢vbload的给的例子
特别感谢bcrun给出链接感激不尽.....由于本人分数较少,只能给了150分,请各位勿怪....
顺便问一句楼主:)我看您在VB版有4个三角,“个人动态”却只有这一个帖子,是不是有好几年没上CSDN了?
硬盘:15G
内存:256M
IP : 1个 HK出口(可以提供电信/网通/国际出口)
Hot backup : 1
PBS VPS刚买的时候有点担心,因为一个月180块,如果买便宜的VPS,可以买好多个。在买之前我联系了他们试用了两天,打消了我的疑虑。我主要看中了有HK的出口,还有hot backup的功能,而且那里的NOC团队也给我了很大的帮助。在试用的两天,我装了几次系统和遇到了几个问题,他们的NOC团队总是能给我最好的解决。我让我HK和美国的朋友测试一下到我的网站速度,他们的感觉都是好快的。这点我是比较满意的。
有点不满意的是他们那里提供的VPS只有CentOS版的,我原本想要RHEL版的,不过他那里没有,不过都是相通的,就用了CentOS了。
好了,大家也可以去试试PBS VPS,有想了解的,可以站内发短信给我。
DoEvents
p = p + 1
If p Mod 1000 = 0 Then
Call InvalidateRect(cLvwMer.hwnd, rc, True)
cLvwMer.Refresh
Call ValidateRect(cLvwMer.hwnd, rc)
End If
硬盘:15G
内存:256M
IP : 1个 HK出口(可以提供电信/网通/国际出口)
Hot backup : 1
PBS VPS刚买的时候有点担心,因为一个月180块,如果买便宜的VPS,可以买好多个。在买之前我联系了他们试用了两天,打消了我的疑虑。我主要看中了有HK的出口,还有hot backup的功能,而且那里的NOC团队也给我了很大的帮助。在试用的两天,我装了几次系统和遇到了几个问题,他们的NOC团队总是能给我最好的解决。我让我HK和美国的朋友测试一下到我的网站速度,他们的感觉都是好快的。这点我是比较满意的。
有点不满意的是他们那里提供的VPS只有CentOS版的,我原本想要RHEL版的,不过他那里没有,不过都是相通的,就用了CentOS了。
好了,大家也可以去试试PBS VPS,有想了解的,可以站内发短信给我。
这个问题与重绘基本上也是没有关系的,在循环添加的时候,如果不加doevents,那么系统是无法取得重绘消息的,只有等循环结束系统重新掌握控制权的时候,窗口才有时间获得系统消息进行重绘,而且一定是一次性的。
另外,楼主的问题还在于并没有真正理解ListView,导致很多效率问题。我将楼主的代码和我的代码循环加大为100000,在不设置Sorted属性的情况下楼主可以试试看效率差多少!
'这是楼主的代码
Private Sub Command2_Click()
Dim i As Long
For i = 0 To 100000
ListView1.ListItems.Add ListView1.ListItems.Count + 1, , ListView1.ListItems.Count + 1
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(1) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(2) = ("你好啊")
ListView1.ListItems.Item(ListView1.ListItems.Count).SubItems(3) = ("你好啊")
Next i
End Sub'这是我的代码
Private Sub Command3_Click()
Dim nItems As ListItems
Dim nItem As ListItem
Dim i As Long
Set nItems = ListView1.ListItems
For i = 0 To 100000
Set nItem = nItems.Add(nItems.Count + 1, , nItems.Count + 1)
nItem.SubItems(1) = ("你好啊")
nItem.SubItems(2) = ("你好啊")
nItem.SubItems(3) = ("你好啊")
Next i
End Sub
仁兄说的sort我用时不会设置的,默认就false,说实话你说的这个方式实在没看出效率高在何处?原理是什么?建议仁兄看看17楼的代码吧这种实现方式还是不错的。http://www.mvps.org/vbvision/Sample_Projects.htm#Virtual_ListView_Demo
还有22楼给出的这个例子,这才是效率。这次真是学习了
C++来说
LISTVIEW有一个虚拟样式,这个样式不需要一个一个向列表中添加。
可重载内部某一函数(忘了……),每次需要获取某一项数据时,LISTVIEW会访问该函数(消息)进行获取。
而假如需要差入10W数据,只需要在LISTVIEW中设置一个总数量好象是就可以了。剩下的数据获取操作由你重载的函数提供。不好意思,好久没接触了。具体函数名还是什么都忘记了。你可以上网查查listview 的虚列表
C++来说
LISTVIEW有一个虚拟样式,这个样式不需要一个一个向列表中添加。
可重载内部某一函数(忘了……),每次需要获取某一项数据时,LISTVIEW会访问该函数(消息)进行获取。
而假如需要差入10W数据,只需要在LISTVIEW中设置一个总数量好象是就可以了。剩下的数据获取操作由你重载的函数提供。不好意思,好久没接触了。具体函数名还是什么都忘记了。你可以上网查查listview 的虚列表
Dim nItems As ListItems
Dim nItem As ListItem
Dim i As Long
With ListView1.ListItems
For i = 0 To 10000
With .Add(, , i + 1)
.SubItems(1) = ("ÄãºÃ°¡")
.SubItems(2) = ("ÄãºÃ°¡")
.SubItems(3) = ("ÄãºÃ°¡")
End With
Next i
End With
这个在我的T60机上测试,10000行只要0.18秒。
当然,如果从设计角度来看,一次向listview加入10000行数据本身不是一个好方案,耗时耗内存。并且用户也不需要同时观看10000条记录,显示器也显示不了,所以分段或者分页加入才是最好的办法。