Colocando um ProgressBar em um ListView

Veja neste artigo, como adicionar um Progressbar em um componente ListView. Acesso exclusivo para Assinantes.

Veremos como adicionar uma barra de progresso (ou qualquer outro componente Delphi) a um controle ListView. A maioria dos gerenciadores de download, utilizam um ListView para visualização do andamento do carregamento para cada item. O ListView exibe uma lista de items de várias maneiras.

Um ProgressBar exibe uma barra de progresso simples. Barras de progresso proporcionam aos usuários visualização sobre o progresso de um procedimento dentro de uma aplicação. Veremos como colocar uma barra de progresso em uma coluna do ListView.

ProgressBar em ListView

Quando atribuímos vsReport à propriedade ViewStyle de um ListView, cada item aparece em sua própria linha com as informações organizadas em colunas. A coluna mais à esquerda, contém o pequeno ícone e o rótulo e as colunas subseqüentes contêm subitens conforme especificados pela aplicação. Provavelmente todo dia vemos isto ao utilizarmos o Windows Explorer em modo de visão Details.

Suponhamos que temos um ListView em um formulário com vsReport em ViewStyle. Duas colunas são definidas utilizando a propriedade Columns: a primeira coluna contém o nome do item, enquanto a segunda coluna deveria conter um indicador de progresso.

Quando clicarmos o botão Adicionar um novo item com uma barra de progresso deveria ser adicionado à lista:

procedure TForm1.AddItemButtonClick(Sender: TObject); const pbColumnIndex = 1; pbMax = 100; var li: TListItem; lv: TListView; pb: TProgressBar; pbRect : TRect; begin lv := ListViewEx1; li := lv.Items.Add; li.Caption := 'Item ' + IntToStr(lv.Items.Count); pb := TProgressBar.Create(nil); pb.Parent := lv; li.Data := pb; pbRect := li.DisplayRect(drBounds); pbRect.Left := pbRect.Left + lv.Columns[-1 + pbColumnIndex].Width; pbRect.Right := pbRect.Left + lv.Columns[pbColumnIndex].Width; pb.BoundsRect := pbRect; end; //AddItemButtonClick

Quando clicamos no botão um novo item de lista (TListItem) é acrescentado ao controle ListView (chamado ListViewEx1). Uma barra de progresso é criada, uma referência para a barra de progresso é adicionada à propriedade Data do item de lista e, finalmente, uma barra de progresso é colocada na coluna especificada por pbColumnIndex. Alguns cálculos são utilizados para fazer a barra de progresso aparecer no lugar certo.

Quando quisermos remover um item da lista, precisamos ter certeza de que a memória da barra de progresso “anexada” seja liberada e todas as barras de progresso sob a selecionada são movidas uma posição para cima (como acontece com todos os itens restantes de um ListView):

procedure TForm1.RemoveItemButtonClick( Sender: TObject); var lv: TListView; li: TListItem; i, idx: integer; pb: TProgressBar; begin lv := ListViewEx1; li := lv.Selected; if li <> nil then begin idx := li.Index; TProgressBar(li.Data).Free; lv.Items.Delete(idx); for i := idx to -1 + lv.Items.Count do begin li := lv.Items.Item[i]; pb := TProgressBar(li.Data); pb.Top := pb.Top - (pb.BoundsRect.Bottom - pb.BoundsRect.Top); end; end; end; //RemoveItemButtonClick

Apenas para testarmos, adicionaremos algum código dentro do evento OnTimer de um Timer, para ter algum progresso nas barras (colocar um Timer em um formulário e utilizar o código abaixo para o evento OnTimer). Obviamente, em aplicações reais atualizaríamos a barra de progresso de um item com base em algum critério, só precisamos localizar “a” barra de progresso (“armazenada“ na propriedade Data de um item):

procedure TForm1.Timer1Timer( Sender: TObject); var idx: integer; pb: TProgressbar; lv: TListView; begin lv := ListViewEx1; if lv.Items.Count = 0 then Exit; idx := Random(lv.Items.Count); pb := TProgressBar(lv.Items[idx].Data); if pb.Position < pb.Max then pb.StepIt else pb.Position := 0; end;//Timer1Timer

Rodamos a aplicação, clicamos no botão Adicionar várias vezes e vemos como se comporta o progresso. Agora, tentemos redimensionar qualquer coluna... uuoopps! Quando redimensionamos as colunas necessárias para reposicionar a barra de progresso, ListView não fornece nenhum evento para tratar o redimensionando de colunas!

TListViewEx - ListView com eventos de redimensionamento de colunas

A solução para tratar o redimensionamento de colunas, consiste em utilizar um ListView derivado: TListViewEx. O TListViewEx (componente que esta disponível junto com o exemplo do artigo) é um descendente de TListView com os eventos BeginColumnResize, ColumnResize e EndColumnResize publicados. Agora, com o poder do TListViewEx, podemos controlar facilmente o redimensionamento de colunas. Veremos como tratar o evento OnEndColumnResize para ajustar a largura e a margem esquerda das barras de progresso:

procedure TForm1.ListViewEx1EndColumnResize( sender: TCustomListView; columnIndex, columnWidth: Integer); var lv: TListViewEx; idx: integer; pb: TProgressBar; begin lv := ListViewEx1; if columnIndex = 0 then begin for idx := 0 to -1 + lv.Items.Count do begin pb := TProgressBar(lv.Items[idx].Data); pb.Left := columnWidth; end; end; if columnIndex = 1 then begin for idx := 0 to -1 + lv.Items.Count do begin pb := TProgressBar(lv.Items[idx].Data); pb.Width := columnWidth; end; end; end;
Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados