下載管理器需在列表每一列顯示進度條。TListView (vsReport 模式) 原生不支援在子項嵌入控制項,但可動態建立 TProgressBar、設定 Parent 為 ListView、並依據 SubItem 矩形定位。
ViewStyle := vsReport,建立兩欄:檔案名、進度。Items.Add 取得 TListItem,建立 TProgressBar,存入 Item.Data。DisplayRect(drBounds) + 欄位寬度偏移),設定 ProgressBar BoundsRect。TProgressBar(Item.Data).Free 釋放控制項,再 Items.Delete,並調整後續項目 ProgressBar 的 Top 座標。TTimer 模擬進度更新,隨機挑選項目遞增 Position。// 新增項目
procedure TForm1.AddItem(const FileName: string);
var
Item: TListItem;
PB: TProgressBar;
R: TRect;
begin
Item := ListView1.Items.Add;
Item.Caption := FileName;
PB := TProgressBar.Create(Self);
PB.Parent := ListView1;
PB.Min := 0; PB.Max := 100; PB.Position := 0;
Item.Data := PB;
UpdateProgressBarPos(Item);
end;
// 依據 SubItem 矩形定位 ProgressBar
procedure TForm1.UpdateProgressBarPos(Item: TListItem);
var
PB: TProgressBar;
R: TRect;
begin
PB := TProgressBar(Item.Data);
R := Item.DisplayRect(drBounds); // 第一欄矩形
R.Left := R.Left + ListView1.Columns[0].Width; // 移至第二欄
R.Right := R.Left + ListView1.Columns[1].Width;
PB.BoundsRect := R;
end;
// 刪除項目
procedure TForm1.DeleteSelectedItem;
var
Item: TListItem;
i: Integer;
PB: TProgressBar;
begin
Item := ListView1.Selected;
if Item = nil then Exit;
TProgressBar(Item.Data).Free;
ListView1.Items.Delete(Item.Index);
// 後續項目上移
for i := Item.Index to ListView1.Items.Count - 1 do
begin
PB := TProgressBar(ListView1.Items[i].Data);
PB.Top := PB.Top - PB.Height;
end;
end;
// Timer 更新進度
procedure TForm1.Timer1Timer(Sender: TObject);
var
Item: TListItem;
PB: TProgressBar;
begin
if ListView1.Items.Count = 0 then Exit;
Item := ListView1.Items[Random(ListView1.Items.Count)];
PB := TProgressBar(Item.Data);
if PB.Position < PB.Max then PB.StepIt else PB.Position := 0;
end;