Is there a way, at runtime, other than using styles, to change the background color of item rows of a TListBox? Can I use the OnPaint event?
"Can I use the OnPaint
event?"
Yes, you can. But maybe it is not considered the orthodox way, as it isn't made available and may fall apart in future Delphi releases. Anyway, if you want to try it, here goes:
You want to use the OnPaint
event of the TListBoxItem
class. However, OnPaint
event of the item is not made available in the designer, so you will need to add it manually to your form class.
type
TForm1 = class(TForm)
Label1: TLabel;
ListBox1: TListBox;
Button1: TButton;
procedure Button1Click(Sender: TObject);
// add following manually (copy & paste)
procedure ListBoxItemPaint(Sender: TObject; Canvas: TCanvas;
const ARect: TRectF);
private
{ Private declarations }
procedure PopulateListBox;
public
{ Public declarations }
end;
Then, when you add items to ListBox1
, it is important to assign ListBoxItemPaint
to each items OnPaint
event (see end of procedure):
procedure TForm1.PopulateListBox;
var
i: integer;
item: TListBoxItem;
begin
// Set default item height
// Individual heights are not possible
ListBox1.ItemHeight := 48;
// Set nr of columns, items arranged horizontally first, then vertically
ListBox1.Columns := 1; // 3;
// Add items
for i := 0 to 7 do
begin
item := TListBoxItem.Create(nil);
item.Parent := ListBox1;
item.Width := Listbox1.Width;
item.StyledSettings := []; // You are now responsible for corresponding
// item.TextSettings, e.g. font, style, color etc.
item.tag := i;
item.Text := 'Item ' + IntToStr(i);
item.OnPaint := ListBoxItemPaint; // This links the OnPaint event to your code
end;
end;
And this is the ListBoxItemPaint()
procedure:
procedure TForm1.ListBoxItemPaint(Sender: TObject; Canvas: TCanvas;
const ARect: TRectF);
var
Brush: TBrush;
Color: TAlphaColor;
Txt: string;
LocRect: TRectF;
begin
begin
Txt := (Sender as TListBoxItem).Text;
case (Sender as TListBoxItem).Tag of
0: Color := TAlphaColors.Aliceblue;
1: Color := TAlphaColors.Antiquewhite;
2: Color := TAlphaColors.Aqua;
3: Color := TAlphaColors.Aquamarine;
4: Color := TAlphaColors.Azure;
5: Color := TAlphaColors.Beige;
6: Color := TAlphaColors.Bisque;
else
Color := TAlphaColorRec.Chocolate;
end;
// Item background, color and shape
Brush := TBrush.Create(TBrushKind.Solid, Color);
try
Canvas.FillRect(ARect, 1, Brush); // rectangular item band
// alternatively use rounded corners
// Canvas.FillRect(ARect,11, 11, AllCorners, 1, Brush); // rounded corners
finally
Brush.Free;
end;
// Text color, font, style and size
Canvas.Fill.Color := TAlphaColors.Red;
Canvas.Font.Family := 'Segoe UI';
Canvas.Font.Style := [TFontStyle.fsBold, TFontStyle.fsItalic];
Canvas.Font.Size := 16;
// Item text location and drawing
LocRect := ARect;
LocRect.Left := LocRect.Left + 10;
Canvas.FillText(LocRect, Txt, False, 1, [], TTextAlign.Leading, TTextAlign.Leading);
end;
end;
Code is written and tested with Delphi 10.4 and demonstrates how you can have different bg colors for each item in a TListBox
.
To change the color of the items at run time you need to move the color selection out from the OnPaint
to a lookup function with selection logic you want to use.