1

我一直致力于在 Visual Basic 6 中创建自己的 Virtual Listview 控件。我在 UserControl 中继承了 SysListView32 类,并且能够成功地对控件进行编码以添加、删除甚至排序项目。所有这些都可以快速运行,就像在虚拟 Listview 控件(LVS_OWNERDATA窗口样式集)中一样。但是,当我通过单击拖动鼠标(没有窗口样式)开始对多个项目进行选取框选择时LVS_SINGLESEL,选择过程相当缓慢,并且随着选择的项目越往下走越慢,该过程会变得越来越慢。即使只有 2 - 300 个项目添加到列表中,也会发生这种情况。查看效果的最佳样本量约为 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

但是,这并不能解决问题。似乎即使不重绘项目,这些消息在后台发送的事实也足以减慢多个项目的选择速度。甚至LVN_ODCACHEHINT在每一波之前都有通知,将最后一个可见项目索引的范围为“0”,而实际上它们不应该是。

我不需要提供我所有的代码;我并没有对我的代码做任何过于花哨的事情,而且它似乎是使用时控件的默认行为LVS_OWNERDATA,所以我怀疑它是否有助于解决问题。然而,我确实怀疑我需要做一些花哨的事情来解决这个问题。

我也看过这个问题,但是反思超出了我的知识范围,我似乎找不到与WM_REFLECT_NOTIFY.

提前致谢。

4

0 回答 0