4

TListBox (lbVirtualOwnerDraw) を描画した所有者がいます。そのコンテンツは動的に更新されます (1 秒間に 10 回もの更新が行われる可能性があります)。リスト ボックスには、一度に最大 300 個のアイテムを含めることができます。各項目には、約 5 行のテキストとそれに関連付けられた画像が含まれる場合があります。項目が更新されるたびに、VCL フレームワークによって ListBoxDrawItem が呼び出されるように、TListBox を更新 (または無効化) する必要があります。ただし、これは冗長な再描画がすべて行われるため、全体的なパフォーマンスに悪影響を及ぼします。だから私の質問は:

  1. 1 つの項目またはその一部の描画を含むキャンバスのごく一部のみを無効にする方法はありますか? (たとえば、1 行のテキストまたはビットマップを含む四角形)。

  2. Draw Item でこのような選択的な無効化長方形をどのように処理できますか? Refresh または invalidate の一部として整数を渡すことができれば、DrawItem でそれを使用して何を更新するかを決定できます。

  3. 項目が TListBox で (インデックスによって) まったく表示されているかどうかを確認する方法はありますか?

前もって感謝します!

4

1 に答える 1

12

API を使用してInvalidateRect、ウィンドウの一部を無効にすることができます。項目が占める領域を見つけるにItemRectは、ListBox のメソッドを使用できます。たとえば、4 番目のアイテムを無効にするには:

var
  R: TRect;
begin
  R := ListBox1.ItemRect(3);
  InvalidateRect(ListBox1.Handle, @R, True);
end;

(または、'InvalidateRect' の 'bErase' として 'False'、そのドキュメントを参照してください)。ビットマップまたはテキストのみを無効にするには、InvalidateRect に渡す前に、それに応じて四角形を変更します。


更新または無効化するために、インデックスまたは任意の種類のユーザー データを渡すことはできません。ペイント ルーチンでは、場所に応じて描画するアイテムを決定するか、どうしても必要な場合はグローバル変数を使用する必要があります。OnDrawItemただし、1 つのアイテムのみの一部を無効にすると、そのアイテムのみが呼び出されるので、その必要はありません。いずれにせよ、無効化されていないアイテムの描画についてあまり心配する必要はありません。更新領域の外に実際の描画が行われることはないため、パフォーマンスに大きな影響を与えることはありません (ここの 3 番目の段落を参照してください)。


アイテムが表示されているかどうかを判断するには、一番上にある最初の表示されているアイテムから開始し、連続するアイテムの高さをコントロールの ClientHeight まで追加します。一番上の項目はTopIndexです。アイテムの高さが固定されている場合、最大でいくつのアイテムが表示されるかはすでにわかっています。そうでない場合は、それらを合計する必要があります。

于 2011-04-06T02:00:35.000 に答える