さまざまな状態のアイテムをペイントするのを忘れました。アイテムが現在どのような状態にあるかを判断し、それに従って描画する必要があります。
あなたがあなたの写真に持っているものは、この方法で得ることができます. ただし、複数選択を有効にして複数のアイテムを選択している場合、これはうまくいきません。
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
var
Offset: Integer;
begin
with (Control as TListBox) do
begin
Canvas.Font.Color := Font.Color;
if (odSelected in State) then
begin
Canvas.Pen.Color := $00FF9932;
Canvas.Brush.Color := $00FDDDC0;
end
else
begin
Canvas.Pen.Color := Color;
Canvas.Brush.Color := Color;
end;
Canvas.Rectangle(Rect);
Canvas.Brush.Style := bsClear;
Offset := (Rect.Bottom - Rect.Top - Canvas.TextHeight(Items[Index])) div 2;
Canvas.TextOut(Rect.Left + Offset + 2, Rect.Top + Offset, Items[Index]);
end;
end;
そして、ItemHeight
16に設定した結果:

ボーナス - 連続選択:
これは、連続選択を実装するトリッキーなソリューションです。原則として、以前と同じようにアイテムを描画しますが、アイテムの境界の上下の線を、前後のアイテムの選択状態に応じた色の線で上書きします。それ以外は、現在のアイテムの外でもレンダリングする必要があります。これは、アイテムの選択によって隣接するアイテムが自然に再描画されるわけではないためです。したがって、水平線は、現在のアイテム境界の 1 ピクセル上と 1 ピクセル下に描画されます (これらの線の色は、相対的な選択状態にも依存します)。
ここで非常に奇妙なのは、アイテム オブジェクトを使用して各アイテムの選択状態を保存していることです。ドラッグ アンド ドロップ項目の選択を使用する場合Selected
、マウス ボタンを離すまで、プロパティは実際の状態を返さないためです。幸いなことに、OnDrawItem
イベントはもちろん実際の状態で発生するため、回避策として、OnDrawItem
イベントからこれらの状態を保存することを使用しました。
重要:
項目オブジェクトを使用して実際の選択状態を保存していることに注意してください。項目オブジェクトを別の目的で使用している場合は、この実際の状態をブール値の配列などに保存してください。
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
const
SelBackColor = $00FDDDC0;
SelBorderColor = $00FF9932;
var
Offset: Integer;
ItemSelected: Boolean;
begin
with (Control as TListBox) do
begin
Items.Objects[Index] := TObject((odSelected in State));
if (odSelected in State) then
begin
Canvas.Pen.Color := SelBorderColor;
Canvas.Brush.Color := SelBackColor;
Canvas.Rectangle(Rect);
end
else
begin
Canvas.Pen.Color := Color;
Canvas.Brush.Color := Color;
Canvas.Rectangle(Rect);
end;
if MultiSelect then
begin
if (Index > 0) then
begin
ItemSelected := Boolean(ListBox1.Items.Objects[Index - 1]);
if ItemSelected then
begin
if (odSelected in State) then
begin
Canvas.Pen.Color := SelBackColor;
Canvas.MoveTo(Rect.Left + 1, Rect.Top);
Canvas.LineTo(Rect.Right - 1, Rect.Top);
end
else
Canvas.Pen.Color := SelBorderColor;
end
else
Canvas.Pen.Color := Color;
Canvas.MoveTo(Rect.Left + 1, Rect.Top - 1);
Canvas.LineTo(Rect.Right - 1, Rect.Top - 1);
end;
if (Index < Items.Count - 1) then
begin
ItemSelected := Boolean(ListBox1.Items.Objects[Index + 1]);
if ItemSelected then
begin
if (odSelected in State) then
begin
Canvas.Pen.Color := SelBackColor;
Canvas.MoveTo(Rect.Left + 1, Rect.Bottom - 1);
Canvas.LineTo(Rect.Right - 1, Rect.Bottom - 1);
end
else
Canvas.Pen.Color := SelBorderColor;
end
else
Canvas.Pen.Color := Color;
Canvas.MoveTo(Rect.Left + 1, Rect.Bottom);
Canvas.LineTo(Rect.Right - 1, Rect.Bottom);
end;
end;
Offset := (Rect.Bottom - Rect.Top - Canvas.TextHeight(Items[Index])) div 2;
Canvas.Brush.Style := bsClear;
Canvas.Font.Color := Font.Color;
Canvas.TextOut(Rect.Left + Offset + 2, Rect.Top + Offset, Items[Index]);
end;
end;
そして結果:
