如何使用鼠标在虚拟列表视图中选择多个项目时防止过多的消息?

时间:2013-11-07 07:27:25

标签: listview vb6 subclassing syslistview32

我一直致力于在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

提前致谢。

0 个答案:

没有答案