2008. november 7., péntek

How to create a TProgressBar inside a TListView


Problem/Question/Abstract:

I would like to display a progress bar as a sub item in a TListView (vsReport mode). How can I do that?

Answer:

Well, you can in fact parent a live progressbar to a listview, you just have to do it at run-time. The sample below has timer that randomly steps the progress bars. The bar is added to the last column of the listview.

There are some gotchas here: the DisplayRect method of a listitem does not return the correct position unless the control is visible, thus the hack used at the top of the method to ensure this. And of course you will have to adjust the width and left bound of the progress bars if the user resizes columns. And you need to add new bars if the user can add items and destroy bars if the user can delete item.

procedure TForm1.FormCreate(Sender: TObject);
var
  pb: TProgressBar;
  r: TRect;
  i, k: Integer;
begin
  Show;
  Application.ProcessMessages;
  for i := 0 to listview1.items.count - 1 do
  begin
    r := listview1.items[i].DisplayRect(drBounds);
    {last column is to take progress bar}
    for k := 1 to listview1.columns.Count - 1 do
      r.left := r.left + listview1.columns[k - 1].Width;
    r.right := r.Left + listview1.columns[listview1.columns.Count - 1].Width;
    pb := TProgressBar.Create(self);
    pb.Parent := listview1;
    pb.BoundsRect := r;
    listview1.items[i].Data := pb;
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  i: Integer;
  pb: TProgressbar;
begin
  i := Random(listview1.items.count);
  pb := TProgressBar(listview1.Items[i].Data);
  if assigned(pb) then
    if pb.Position = pb.Max then
      pb.Position := 0
    else
      pb.StepBy(pb.Max div 10);
end;

Nincsenek megjegyzések:

Megjegyzés küldése