Recent

Author Topic: [SOLVED] Listbox and more than column  (Read 2106 times)

superc

  • Sr. Member
  • ****
  • Posts: 251
[SOLVED] Listbox and more than column
« on: April 03, 2023, 04:19:02 pm »
Hello,

I've see this post on StackOverlof
https://stackoverflow.com/questions/73090492/how-to-add-multiple-column-items-to-tlistbox

but in Lazarus property TabWidth  seems not present; it's possible use tlistbox in Lazarus with more than one column as in Delphi?
Thanks in advance.
« Last Edit: April 04, 2023, 03:31:31 pm by superc »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Listbox and more than column
« Reply #1 on: April 03, 2023, 06:57:00 pm »
Delphis version was made for Windows only, Lazarus variant is crosscompile compatible and thus of that it does not offer that feature.
You can switch to a TListView in vsReport style to have what you want.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

wp

  • Hero Member
  • *****
  • Posts: 13489
Re: Listbox and more than column
« Reply #2 on: April 03, 2023, 08:18:31 pm »
You always can owner-draw the listbox and thus create effects difficult to achieve otherwise: Set the Listbox.Style to lbOwnerDrawFixed and use the following event handler for OnDrawItem:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
  2.   ARect: TRect; State: TOwnerDrawState);
  3. const
  4.   COL_DIST = 16;
  5. var
  6.   sa: TStringArray;
  7.   x, y: Integer;
  8.   i: Integer;
  9. begin
  10.   Listbox1.Canvas.FillRect(ARect);
  11.   sa := Listbox1.Items[Index].Split(#9);
  12.   x := ARect.Left + 2;
  13.   y := (ARect.Top + ARect.Bottom - Listbox1.Canvas.TextHeight('Tg')) div 2;
  14.   for i := 0 to High(sa) do
  15.   begin
  16.     Listbox1.Canvas.TextOut(x, y, sa[i]);
  17.     inc(x, FColWidths[i] + COL_DIST);
  18.   end;
  19. end;

The array FColWidths here denotes the column widths which can be predefined or, better, must be measured in a previous step, after populating the listbox. Since there might not yet exist a valid canvas at this time I am using a temporary bitmap for text length determination:
Code: Pascal  [Select][+][-]
  1. var
  2.   FColWidths: array of Integer;
  3.  
  4. procedure TForm1.MeasureColWidths(AListBox: TListbox);
  5. var
  6.   bmp: TBitmap;
  7.   i, j: Integer;
  8.   s: String;
  9.   sa: TStringArray;
  10.   w: Integer;
  11. begin
  12.   SetLength(FColWidths, 0);
  13.   bmp := TBitmap.Create;
  14.   try
  15.     bmp.SetSize(1, 1);
  16.     bmp.Canvas.Font.Assign(AListbox.Font);
  17.     for i := 0 to AListbox.Items.Count-1 do
  18.     begin
  19.       sa := AListbox.Items[i].Split(#9);
  20.       if Length(sa) > Length(FColWidths) then
  21.         SetLength(FColWidths, Length(sa));
  22.       for j := 0 to High(sa) do
  23.       begin
  24.         w := bmp.Canvas.TextWidth(sa[j]);
  25.         if w > FColWidths[j] then FColWidths[j] := w;
  26.       end;
  27.     end;
  28.   finally
  29.     bmp.Free;
  30.   end;
  31. end;

In the list items, finally, the columns are defined by putting tab characters into the item text:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   Listbox1.Items.Add('Item 1'#9'Item 2'#9'Item 3');
  4.   Listbox1.Items.Add('A'#9'ABC'#9'abcdefg');
  5.   Listbox1.Items.Add('Item 4'#9'Item 5'#9'Item 6');
  6.   Listbox1.Items.Add('Testing...'#9'One more test'#9'ttt');
  7.   Listbox1.Items.Add('Some rather long text'#9#9'xyz');
  8.   Listbox1.Items.Add(#9'Only cell in this row');
  9.  
  10.   MeasureColWidths(Listbox1);
  11. end;
« Last Edit: April 03, 2023, 10:44:24 pm by wp »

jamie

  • Hero Member
  • *****
  • Posts: 7662
Re: Listbox and more than column
« Reply #3 on: April 03, 2023, 10:58:00 pm »
StringGrid.
The only true wisdom is knowing you know nothing

superc

  • Sr. Member
  • ****
  • Posts: 251
Re: Listbox and more than column
« Reply #4 on: April 04, 2023, 03:31:18 pm »
StringGrid.
for what I need the TStringGrid fits well, Thank you

superc

  • Sr. Member
  • ****
  • Posts: 251
Re: Listbox and more than column
« Reply #5 on: April 04, 2023, 04:33:15 pm »
Delphis version was made for Windows only, Lazarus variant is crosscompile compatible and thus of that it does not offer that feature.
You can switch to a TListView in vsReport style to have what you want.
I believe that is incorrect: Delphi 10 is cross-platform and does it well too.

jamie

  • Hero Member
  • *****
  • Posts: 7662
Re: Listbox and more than column
« Reply #6 on: April 04, 2023, 10:51:35 pm »
StringGrid.
for what I need the TStringGrid fits well, Thank you

A little imagination is needed here.

A TStringGrid has everything you need to implement a listbox with all the columns you need.
The only true wisdom is knowing you know nothing

VisualLab

  • Hero Member
  • *****
  • Posts: 721
Re: Listbox and more than column
« Reply #7 on: April 04, 2023, 11:23:57 pm »
Delphis version was made for Windows only, Lazarus variant is crosscompile compatible and thus of that it does not offer that feature.
You can switch to a TListView in vsReport style to have what you want.
I believe that is incorrect: Delphi 10 is cross-platform and does it well too.

Yes, but only when using the FireMonkey library. VCL is only available on Windows. On the other hand, Lazarus on systems other than Windows uses the libraries available in these OSes (Linux - GTK, Qt, MacOS X - Cocoa). So I guess that's the reason.

jamie

  • Hero Member
  • *****
  • Posts: 7662
Re: Listbox and more than column
« Reply #8 on: April 07, 2023, 12:03:05 am »
StringGrid.
for what I need the TStringGrid fits well, Thank you
I miss read your reply, Sorry about that.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018