Author: Tomas Rutkauskas
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.
1 procedure TForm1.FormCreate(Sender: TObject);
2 var3 pb: TProgressBar;
4 r: TRect;
5 i, k: Integer;
6 begin7 Show;
8 Application.ProcessMessages;
9 for i := 0 to listview1.items.count - 1 do10 begin11 r := listview1.items[i].DisplayRect(drBounds);
12 {last column is to take progress bar}13 for k := 1 to listview1.columns.Count - 1 do14 r.left := r.left + listview1.columns[k - 1].Width;
15 r.right := r.Left + listview1.columns[listview1.columns.Count - 1].Width;
16 pb := TProgressBar.Create(self);
17 pb.Parent := listview1;
18 pb.BoundsRect := r;
19 listview1.items[i].Data := pb;
20 end;
21 end;
22 23 procedure TForm1.Timer1Timer(Sender: TObject);
24 var25 i: Integer;
26 pb: TProgressbar;
27 begin28 i := Random(listview1.items.count);
29 pb := TProgressBar(listview1.Items[i].Data);
30 if assigned(pb) then31 if pb.Position = pb.Max then32 pb.Position := 0
33 else34 pb.StepBy(pb.Max div 10);
35 end;