Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Trucos (https://www.clubdelphi.com/foros/forumdisplay.php?f=52)
-   -   HELPER: Insertar ProgressBar en LISTITEM (https://www.clubdelphi.com/foros/showthread.php?t=93028)

bucanero 24-04-2018 18:36:03

HELPER: Insertar ProgressBar en LISTITEM
 
Hola a todos,

Hace algún tiempo descubrí los HELPER como una posibilidad muy interesante que incluye el lenguaje PASCAL, aunque realmente no se en que momento se introdujo en el lenguaje.

Básicamente lo que permite es añadirle funcionalidades que no existen o que podamos necesitar, a classes u otras estructuras de datos, con la ventaja de que se puede utilizar directamente sin necesidad de modificar nada de lo que ya hay creado por debajo. No necesita llamar a create/destroy, ni hacer nada especial con lo que ya hay creado o funcionando.

Tiene algunas limitaciones como no poder utilizar nuevas estructuras de datos dentro del propio HELPER, siempre y cuando sean necesarias crearlas junto con el propio componente, por la imposibilidad de sobreescribir los procedimientos constructor/destructor del método original sobre el que se aplica el HELPER y porque si no esta incluida nuestra nueva unidad con el HELPER en el resto de código entonces todas las modificaciones existentes es como si no existieran.

Como ejemplo simple pero bastante interesante es el típico código para insertar un ProgressBar a un LISTITEM de un LISTVIEW y aquí como quedaría insertado como un HELPER de un LISTITEM en una unidad independiente:

Código Delphi [-]
unit ListItemHelpers;

interface

uses Windows, ComCtrls;

type
  TListItemHelper = class helper for TListItem
  private
    function GetRect(AColumn: Integer): TRect;
    function GetProgressBar: TProgressBar;
  public
    procedure AdjustProgressBar;
    function AddPRogressBar(AColumn: integer = 1): TProgressBar;
    procedure DeleteProgressBar;
    property ProgressBar: TProgressBar read GetProgressBar;
  end;

implementation

uses
  Dialogs, System.SysUtils;

procedure Error(E:Exception; const msgTxt:String);
begin
  MessageDlg(E.Message + #13 + msgTxt, mtError, [mbOK], 0);
end;


{ TListItemHelper }

function TListItemHelper.AddPRogressBar(AColumn: integer): TProgressBar;
/// Si AColumn es igual 0 entonces se situa en la ultima columna
begin
  if assigned(Data) then begin
    Result := data;
    exit;
  end;
  ///  se le asigna como OWNER del PROGRESSBAR el listView propietario del LISTITEM
  ///  en donde queremos el PROGRESSBAR, para que asi, se libere automaticamente
  ///  tambien al liberar el listView
  result := TProgressBar.Create(ListView);
  /// se le asigna como padre el listView
  result.parent := ListView;
  /// El dobleBuffered evita el parpadeo
  result.DoubleBuffered := true;
  if (AColumn <= 0) then
    AColumn := 1;
  /// El tag del progresBass va a ser el numero de columna
  /// dentro del listItem donde se situa el propio ProgressBar
  result.Tag := AColumn;
  /// se guarda el puntero al ProgressBar en el campo DATA del ListItem
  Data := result;
  AdjustProgressBar;
end;

procedure TListItemHelper.AdjustProgressBar;
var
  pb: TProgressBar;
begin
  pb := Data;  //<-- listItem.data
  if assigned(pb) then
    /// El tag del progresBass va a ser el numero de columna
    /// dentro del listItem donde se situa el propio ProgressBar
    pb.BoundsRect := GetRect(pb.Tag);
end;

procedure TListItemHelper.DeleteProgressBar;
var
  pb: TProgressBar;
begin
  /// al liberar el ProgressBar no se por que da un error,
  /// asi que en principio lo dejo sin liberar.
  /// Aunque queda pendiente de ver por que lo hace.
  /// Tampoco supone un gran problema porque se creo con padre
  /// y ya se encarga el proceso de eliminarlo automaticamente
  try
    pb := Data;
    if assigned(pb) then
    try
      freeAndNil(pb);
      data := Nil;
    except
      on E: Exception do
        error(e, 'TListItemHelper.DeleteProgressBar');
    end;
  except
    on E: Exception do
      error(E, 'TListItemHelper.DeleteProgressBar');
  end;
end;

function TListItemHelper.GetProgressBar: TProgressBar;
begin
  try
    Result := nil;
    if not Assigned(Data) then
      AddPRogressBar;
    result := TObject(Data) as TProgressBar
  except
    on E: Exception do
      Error(E, 'TListItemHelper.GetProgressBar');
  end;
end;

function TListItemHelper.GetRect(AColumn: Integer): TRect;
var
  i: longint;
begin
  result := DisplayRect(drBounds);
  // last column is to take progress bar
  with TListView(ListView) do begin
    if AColumn = 0 then
      AColumn := columns.Count - 1;
    for i := 1 to AColumn do
      result.left := result.left + columns[i - 1].Width;
    result.right := result.Left + columns[AColumn].Width;
  end;
end;

end.


Para usarlo solamente es necesario añadir la unidad con el HELPER a nuestro formulario y listo, tendremos las nuevas funciones disponibles para su uso:

Código Delphi [-]
uses ..., ListItemHelpers;

...

procedure TForm1.AddProgressBarClick(Sender: TObject);
begin
  ListView1.Selected.addProgressBar;
end;

procedure TForm1.DeleteProgressBarClick(Sender: TObject);
begin
  ListView1.Selected.DeleteProgressBar;
end;

procedure TForm1.DeleteItemClick(Sender: TObject);
begin
  /// IMPORTANTE:
  ///     el progressBar no se elimina de forma automatica al
  ///     eliminar el LISTITEM y hay que hacerlo a mano, 
  ///     aunque si se elimina al eliminar el LISTVIEW
  ListView1.selected.DeleteProgressBar;
  ListView1.DeleteSelected;
end;

procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  /// esta llamada es para que el tamaño de los progressBar insertados, se ajusten automáticamente 
  /// al cambiar la columna sobre la que esta insertado su tamaño
  Item.AdjustProgressBar;
end;

Esta técnica sobre todo la veo interesante por su simplicidad de uso,
Espero les sea util

Un saludo

Casimiro Notevi 24-04-2018 19:31:14

^\||/^\||/^\||/

jhonny 24-04-2018 22:42:21

Muchas gracias por el aporte, como bien dices la simplicidad de uso es muy interesante. Utilizar Helpers suele dejar el código más claro.

ElKurgan 25-04-2018 10:08:13

Gracias por el aporte

Saludos

ecfisa 27-04-2018 20:06:02

Muy buen ejemplo, muchas gracias ^\||/

Saludos :)

AgustinOrtu 28-04-2018 15:48:34

Excelente, gracias por compartir!!

Menthor 07-09-2018 09:19:28

Gracias por la info


La franja horaria es GMT +2. Ahora son las 22:26:31.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi