Olvidó pintar los artículos para diferentes estados. Debe determinar en qué estado se encuentra actualmente el artículo y según lo que lo dibuje.
Lo que tienes en la foto puedes obtenerlo de esta manera. Sin embargo, esto no se ve bien si ha habilitado selección múltiple y seleccionar más de un elemento:
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;
Y el resultado con ItemHeight
conjunto a 16:
Bonus - selección continua :
Aquí hay una solución compleja que implementa una selección continua. El principio es dibujar el elemento como antes, pero luego sobreescriba las líneas superior e inferior del borde del artículo con las líneas de un color dependiendo del estado de selección del artículo anterior y siguiente. Excepto que, también se debe representar fuera del elemento actual, ya que la selección del elemento no invoca naturalmente los elementos vecinos para volver a pintar. Por lo tanto, las líneas horizontales se pintan un píxel por encima y un píxel por debajo de los límites del elemento actual (los colores de estas líneas también dependen de los estados de selección relativa).
Muy extraño aquí es el uso de objetos de elemento para almacenar el estado seleccionado de cada elemento. Lo hice porque, al utilizar una opción de arrastrar & soltar elemento, la propiedad Selected
no devuelve el estado real hasta que suelta el botón del mouse. Afortunadamente, el evento OnDrawItem
, por supuesto, se activa con el estado real, por lo que como solución alternativa he utilizado el almacenamiento de estos estados desde el evento OnDrawItem
.
Importante:
Aviso, que estoy usando los objetos de elemento para almacenar el estado actual selección, así que tenga cuidado, y cuando se está utilizando objetos de elemento para otra cosa, almacenar este real estados, por ejemplo en una matriz de Boolean.
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;
Y el resultado:
No creo que existe este tipo de una selección temática de cuadro de lista. Hay ['LBCP_ITEM'] (http://msdn.microsoft.com/en-us/library/windows/desktop/bb(v = vs.85) .aspx) partes para el cuadro de lista, pero se ven exactamente como el caja de lista dibujada sin dueño - aburrida. Por lo tanto, tal vez pueda pedir prestados los elementos de la selección temática, p. desde la vista de árbol como describió Andrew en ['this post'] (http://stackoverflow.com/a/10936108/960757). Solo necesitará modificar ese código para los estados del cuadro de lista. – TLama
Esto es lo que me preocupaba, a diferencia de Treeview y Listview que pintan selecciones temáticas que Listbox no hace. –
Cuando se trata de colores difíciles de codificar, no olvide que un usuario puede tener un esquema de color completamente diferente. –