Bookstore

Recent

Author Topic: Way to specify the color of each line in a TListBox?  (Read 326 times)

JamesSci

  • New Member
  • *
  • Posts: 30
Way to specify the color of each line in a TListBox?
« on: February 24, 2020, 02:33:11 pm »
I have a program that generates an RGB color value (for example: 13816544). Is there a way to, when adding a line to a listbox, specify the background color of the line?

Thank you

howardpc

  • Hero Member
  • *****
  • Posts: 3355
Re: Way to specify the color of each line in a TListBox?
« Reply #1 on: February 24, 2020, 02:39:28 pm »
Yes.
You need to set the listbox's Style property to lbOwnerDrawnFixed (or lb...Variable if the items use different sized fonts).
Then you use the listbox's OnDrawItem event to draw each item manually as you wish.

JamesSci

  • New Member
  • *
  • Posts: 30
Re: Way to specify the color of each line in a TListBox?
« Reply #2 on: February 24, 2020, 03:02:07 pm »
When I do the following from a Delphi project, I get the error "Illegal type conversion: TObject to TGraphicsColor":

Code: Pascal  [Select]
  1. procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: integer;  Rect: TRect; State: TOwnerDrawState);
  2. var
  3.   ListBox: TListBox;
  4.   Canvass: TCanvas;
  5.   S: string;
  6. begin
  7.   ListBox := Control as TListBox;
  8.   Canvass := ListBox.Canvas;
  9.  
  10.   Canvass.Brush.Color := TColor(ListBox.Items.Objects[Index]); // Error happens on the line
  11.   Canvass.FillRect(Rect);
  12.   S := ListBox.Items[Index];
  13.   // Canvass.TextRect(Rect, S, [tfSingleLine, tfVerticalCenter]);
  14. end;        

How can I get this to work?

Handoko

  • Hero Member
  • *****
  • Posts: 3434
  • My goal: build my own game engine using Lazarus
Re: Way to specify the color of each line in a TListBox?
« Reply #3 on: February 24, 2020, 03:32:27 pm »
I think it should be:

... TColor(ListBox.Items[Index]);

winni

  • Hero Member
  • *****
  • Posts: 1110
Re: Way to specify the color of each line in a TListBox?
« Reply #4 on: February 24, 2020, 03:34:33 pm »
Hi!

Assuming you save the integer values of the colors in the stringlist it must be done this way:

 
Code: Pascal  [Select]
  1. Canvas.Brush.Color := StrToInt (ListBox.Items[Index]);  

Winni

JamesSci

  • New Member
  • *
  • Posts: 30
Re: Way to specify the color of each line in a TListBox?
« Reply #5 on: February 24, 2020, 03:56:29 pm »
Thank you for help everyone! Let me show you the whole picture, this is my code so far:

Code: Pascal  [Select]
  1. procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: integer;  Rect: TRect; State: TOwnerDrawState);
  2. var
  3.   ListBox: TListBox;
  4.   Canvas: TCanvas;
  5.   S: string;
  6. begin
  7.   ListBox := Control as TListBox;
  8.   Canvas := ListBox.Canvas;
  9.  
  10.   Canvas.Brush.Color := StrToInt(ListBox.Items[Index]);
  11.   Canvas.FillRect(Rect);
  12.   S := ListBox.Items[Index];
  13. end;
  14.  
  15. procedure TForm1.FileProcedure;
  16. var
  17.   StrList, FileList: TStringList;
  18.   String1, ColorVal: string;
  19.   i: integer;
  20. begin
  21.   for i := 0 to StrList.Count -1 do
  22.   begin
  23.     FileList := TStringList.Create;
  24.     try
  25.       FileList.LoadFromFile(StrList.Strings[i]);
  26.       String1 := FileList[0];
  27.       ColorVal := FileList[1];
  28.     finally
  29.       FileList.Free;
  30.     end;
  31.  
  32.     ListBox1.Items.AddObject(String1, { Whichever color ColorVal is would be the background of this item });
  33.   end;
  34. end;

So if the file reads:

Quote
Hey123
13816544

The string added to the ListBox would be "Hey123" with that colored background.

I don't know how to logically do this though without maybe a function(?) that would return the color?

Does anybody have any idea how to do this? Many thanks!!

Handoko

  • Hero Member
  • *****
  • Posts: 3434
  • My goal: build my own game engine using Lazarus
Re: Way to specify the color of each line in a TListBox?
« Reply #6 on: February 24, 2020, 04:08:58 pm »
Maybe something like this:

Code: Pascal  [Select]
  1. If not(Sender is TListBox) then Exit;
  2. with (Sender as TListBox).Canvas
  3.   Pen.Color := StrToInt(ListBox.Items[Index])
  4.   TextOut(Rect.Left, Rect.Top, 'Hey123');
  5. end;
« Last Edit: February 24, 2020, 04:13:09 pm by Handoko »

JamesSci

  • New Member
  • *
  • Posts: 30
Re: Way to specify the color of each line in a TListBox?
« Reply #7 on: February 24, 2020, 06:50:29 pm »
I still don't understand how I can put that into a for do loop, checking the second line of the file, and making the listbox item's background color based on the second line of the file?

howardpc

  • Hero Member
  • *****
  • Posts: 3355
Re: Way to specify the color of each line in a TListBox?
« Reply #8 on: February 24, 2020, 07:08:58 pm »
It's less complicated for parsing to put the item data all on one comma-separated line, and store the colors in RGB format as hex "strings".

The example file
Code: Text  [Select]
  1. Hey123,82f3f8
  2. test2,88ffff
  3. test White,ffffff
  4. test Red,ff0000
  5. test Green,00ff00
  6. test Blue,0000ff
gives the attached image with the following code:
Code: Pascal  [Select]
  1. unit uMainForm;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, StdCtrls;
  9.  
  10. type
  11.   TForm1 = class(TForm)
  12.     ListBox1: TListBox;
  13.     procedure FormCreate(Sender: TObject);
  14.     procedure ListBox1DrawItem(Control: TWinControl; Index: Integer;
  15.       ARect: TRect; {%H-}State: TOwnerDrawState);
  16.   end;
  17.  
  18.   procedure LoadListboxFromFile(const aFilename: String; aListbox: TListBox);
  19.  
  20. var
  21.   Form1: TForm1;
  22.  
  23. implementation
  24.  
  25. procedure LoadListboxFromFile(const aFilename: String; aListbox: TListBox);
  26. type
  27.   Ts2 = String[2];
  28.   THexBytes = record
  29.     case Boolean of
  30.       True:  (arr: array[1..3] of Byte);
  31.       False: (value: longword);
  32.   end;
  33.  
  34. var
  35.   sl: TStringList;
  36.   sa: TStringArray;
  37.   h: PtrInt;
  38.   i: Integer;
  39.  
  40.   function Str6ToHex(aString: String): Int64;
  41.   var
  42.     hb: THexBytes;
  43.  
  44.     function StrToHex(s: Ts2): Byte;
  45.  
  46.       function GetValue(c: Char): Byte;
  47.       begin
  48.         if c in ['0'..'9'] then
  49.           Exit(Ord(c) - 48)
  50.         else if c in ['A'..'F'] then
  51.           Exit(Ord(c) - 55)
  52.         else if c in ['a'..'f'] then
  53.           Exit(Ord(c) - 87)
  54.         else Assert(True,'Error in hex string value');
  55.       end;
  56.  
  57.     begin
  58.       result := GetValue(s[2]) + 16*GetValue(s[1]);
  59.       WriteLn('Result is $',Result);
  60.     end;
  61.  
  62.   begin
  63.     hb := Default(THexBytes);
  64.     hb.arr[3] := StrToHex(Copy(aString, 1, 2));
  65.     hb.arr[2] := StrToHex(Copy(aString, 3, 2));
  66.     hb.arr[1] := StrToHex(Copy(aString, 5, 2));
  67.     Result := hb.value;
  68.   end;
  69.  
  70. begin
  71.   if FileExists(aFilename) then
  72.     begin
  73.       aListbox.Clear;
  74.       sl := TStringList.Create;
  75.       try
  76.         sl.LoadFromFile(aFilename);
  77.         for i := 0 to sl.Count-1 do
  78.           begin
  79.             sa := sl[i].Split([','], '"');
  80.             Assert(Length(sa[1])=6,'invalid hex string "'+sa[1]+'"');
  81.             h := Str6ToHex(sa[1]);
  82.             aListbox.Items.AddObject(sa[0], TObject(h));
  83.           end;
  84.       finally
  85.         sl.Free;
  86.       end;
  87.     end;
  88. end;
  89.  
  90. {$R *.lfm}
  91.  
  92. procedure TForm1.FormCreate(Sender: TObject);
  93. begin
  94.   LoadListboxFromFile('text.txt', ListBox1);
  95. end;
  96.  
  97. procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState);
  98. var
  99.   lb: TListBox absolute Control;
  100.   ts: TTextStyle;
  101. begin
  102.   lb.Canvas.Brush.Color := PtrInt(lb.Items.Objects[Index]);
  103.   lb.Canvas.FillRect(ARect);
  104.  
  105.   ts := lb.Canvas.TextStyle;
  106.   ts.Alignment := taLeftJustify;
  107.   ts.Layout := tlCenter;
  108.   lb.Canvas.Pen.Color := clBlack;
  109.   lb.Canvas.TextRect(ARect, ARect.Left+2, ARect.Top, lb.Items[Index], ts);
  110. end;
  111.  
  112. end.

Handoko

  • Hero Member
  • *****
  • Posts: 3434
  • My goal: build my own game engine using Lazarus
Re: Way to specify the color of each line in a TListBox?
« Reply #9 on: February 24, 2020, 07:20:33 pm »
@JamesSci

What you want to do seems to be to far from what you able to understand. Basically you need to understand these:
- Save/load data from a file
- How to use ownerdrawn

Do you already have the code for loading data from the file? If yes, please show us. If no, please write one and then show us. If you don't understand how to load data from a file, then I suggest you to learn from these examples:
https://forum.lazarus.freepascal.org/index.php/topic,45911.msg325205.html#msg325205
https://forum.lazarus.freepascal.org/index.php/topic,48241.msg347331.html#msg347331