Visual Basic 6 で独自の仮想リストビュー コントロールの作成に取り組んできました。UserControl で SysListView32 クラスをサブクラス化し、項目の追加、削除、さらには並べ替えを行うコントロールを正常にコーディングできました。Virutal 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
.
前もって感謝します。