Thursday, February 21, 2008

TListBox review

TListBox is a simple visual component that always use for display a list of items but it has some nice features that we always neglected. Using TListBox to show column-like data
procedure TForm1.FormCreate(Sender: TObject);
var L: TListBox;
begin
 L := TListBox.Create(Self);
 L.Parent := Self;
 L.Align := alClient;
 L.TabWidth := 20;
 with L.Items do begin
   Add('Item 01'^I'This is Item 01'^I'3.00');
   Add('Item 02'^I'This is Item 02'^I'5.00');
   Add('Item 03'^I'This is Item 03'^I'23.00');
   Add('Item 04'^I'This is Item 04'^I'33.00');
   Add('Item 05'^I'This is Item 05'^I'43.00');
 end;
end;
Custom Draw items in TListBox #1
procedure TForm1.FormCreate(Sender: TObject);
var L: TListBox;
begin
 L := TListBox.Create(Self);
 L.Parent := Self;
 L.Align := alClient;
 L.Style := lbOwnerDrawFixed;
 L.OnDrawItem := OnDrawItem;
 with L.Items do begin
   Add('Item 01');
   Add('Item 02');
   Add('Item 03');
   Add('Item 04');
   Add('Item 05');
 end;
end;

procedure TForm1.OnDrawItem(Control: TWinControl; Index: Integer;
 Rect: TRect; State: TOwnerDrawState);
var C: TColor;
begin
 with Control as TListBox do begin
   Canvas.FillRect(Rect);

   if odSelected in State then
     C := Canvas.Font.Color
   else if Index mod 2 = 0 then
     C := clGreen
   else
     C := clBlue;
   Canvas.Font.Color := C;

   Canvas.TextOut(Rect.Left, Rect.Top, Items[Index]);
 end;
end;
Custom Draw items in TListBox #2
procedure TForm1.FormCreate(Sender: TObject);
var L: TListBox;
begin
 L := TListBox.Create(Self);
 L.Parent := Self;
 L.Align := alClient;
 L.Style := lbOwnerDrawVariable;
 L.OnDrawItem := OnDrawItem;
 L.OnMeasureItem := OnMeasureItem;
 with L.Items do begin
   Add('Item 01');
   Add('Item 02');
   Add('Item 03');
   Add('Item 04');
   Add('Item 05');
 end;
end;

procedure TForm11.OnDrawItem(Control: TWinControl; Index: Integer;
 Rect: TRect; State: TOwnerDrawState);
var iSize: integer;
begin
 with Control as TListBox do begin
   Canvas.FillRect(Rect);

   if Index mod 2 = 0 then
     iSize := 12
   else
     iSize := 20;
   Canvas.Font.Size := iSize;

   Canvas.TextOut(Rect.Left, Rect.Top, Items[Index]);
 end;
end;

procedure TForm11.OnMeasureItem(Control: TWinControl; Index: Integer; var
 Height: Integer);
var iSize: integer;
   L: TListBox;
begin
 L := Control as TListBox;
 if Index mod 2 = 0 then
   iSize := 12
 else
   iSize := 20;
 L.Canvas.Font.Size := iSize;
 Height := L.Canvas.TextHeight(L.Items[Index]);
end;


Custom Draw items in TListBox #3 Due to the design of windows list box control, the OnMeasure event is trigger once only if an item is added. The following code shows example of how to draw item with custom item height.
procedure TForm1.BeforeDestruction;
begin
 inherited;
 Font1.Free;
 Font2.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
var L: TListBox;
begin
 L := TListBox.Create(Self);
 L.Parent := Self;
 L.Align := alClient;
 L.Style := lbOwnerDrawVariable;
 L.OnDrawItem := OnDrawItem;

 Font1 := TFont.Create;
 Font1.Name := 'Tahoma';
 Font1.Size := 25;
 Font1.Color := clGreen;

 Font2 := TFont.Create;
 Font2.Name := 'Arial';
 Font2.Size := 15;
 Font2.Color := clNavy;
 Font2.Style := [fsBold];

 with L.Items do begin
   AddObject('Item 01', Font1);
   AddObject('Item 02', Font2);
   AddObject('Item 03', Font1);
   AddObject('Item 04', Font2);
   AddObject('Item 05', Font1);
 end;
end;

procedure TForm1.OnDrawItem(Control: TWinControl; Index: Integer;
 Rect: TRect; State: TOwnerDrawState);
var C: TColor;
 L: TListBox;
begin
 L := Control as TListBox;
 L.Canvas.FillRect(Rect);

 C := L.Canvas.Font.Color;
 L.Canvas.Font.Assign(L.Items.Objects[Index] as TFont);
 if odSelected in State then
   L.Canvas.Font.Color := C;

 SendMessage(L.Handle, LB_SETITEMHEIGHT, Index, L.Canvas.TextHeight(L.Items[Index]));
 L.Canvas.TextOut(Rect.Left, Rect.Top, L.Items[Index]);
end;

No comments: