我一直致力于在Visual Basic 6中创建自己的Virtual Listview控件。我已经在UserControl中创建了SysListView32类的子类,并且能够成功地对控件进行编码以添加,删除甚至对项目进行排序。所有这些都很快,因为它应该在Virutal Listview控件(LVS_OWNERDATA
窗口样式集)中。但是,当我通过单击拖动鼠标(缺少LVS_SINGLESEL
窗口样式)来启动多个项目的选取框选择时,选择过程相当慢,并且随着选择更多项目进入列表的更下方而变慢。即使只有2-3个项目添加到列表中,也会发生这种情况。查看效果的最佳样本量约为500项。
由于我一直在构建控件,我还添加了几乎所有SysListView32类通常会得到的消息,以及UserControl应该获取的每个通知代码,以便在更改DEBUGFLAG常量变量时,我可以使用VB6中的“立即”窗格告诉我到底发生了什么。在对控件发送和接收的消息进行进一步调查后,我注意到NM_CUSTOMDRAW
通知代码的发生频率远远超过应有的范围,项目索引从项目'0','1'开始,在每个新的“波浪”选择中,“2”等等,即使这些项目实际上不可见。
我尝试通过尝试发送NM_CUSTOMDRAW
返回值来尝试处理那些不在视图中的项目的CDRF_SKIPDEFAULT
消息。请注意,第一个NM_CUSTOMDRAW
通知不存储相关的项目索引;您需要使用CDRF_NOTIFYITEMDRAW
值处理第一个通知,以便检索正在重新绘制的项目的项目索引。
Case NM_CUSTOMDRAW
Dim NotifyLVCDraw As NMLVCUSTOMDRAW
CopyMemory NotifyLVCDraw, ByVal lParam, 60
Select Case NotifyLVCDraw.nmcd.dwDrawStage
Case CDDS_PREPAINT
If ICount Then
IVBSubClass_WndProc = CDRF_NOTIFYITEMDRAW
bHandled = True
End If
Case CDDS_ITEMPREPAINT
Dim I As Long, J As Long
I = SendMessageW(hUniListView, LVM_GETTOPINDEX, 0, ByVal 0&)
J = SendMessageW(hUniListView, LVM_GETCOUNTPERPAGE, 0, ByVal 0&) + I
If NotifyLVCDraw.nmcd.dwItemSpec >= I And NotifyLVCDraw.nmcd.dwItemSpec <= J Then
'Item Back Colour / Text Colour code
Else
IVBSubClass_WndProc = CDRF_SKIPDEFAULT
End If
bHandled = True
然而,这并没有解决问题。似乎即使没有重新绘制项目,这些消息在后台发送的事实足以减慢多个项目的选择速度。在每个wave之前甚至会有LVN_ODCACHEHINT
个通知,它们会给最后一个可见项索引提供一个“0”范围,而实际上它们不应该是。
我不需要提供我的所有代码;我没有对我的代码做任何过于花哨的事情,并且它似乎是使用LVS_OWNERDATA
时控件的默认行为,所以我怀疑它有助于解决问题。但是,我确实怀疑我需要做一些想要解决问题的事情。
我也看过 this question ,但是反思已经超出了我的知识领域,我似乎无法找到与子类化窗口程序相关的任何消息到WM_REFLECT_NOTIFY
。
提前致谢。