Colocando um ProgressBar em um ListView

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (0)  (0)

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

Colocando um ProgressBar em um ListView

 

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.

 

Figura 1. Componentes da paleta Win32

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.

 

Figura 2. Como ficará nosso exemplo

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;

 

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?