Si l’exécution d’une action prend beaucoup de temps, il est souhaitable d’informer l’utilisateur de la façon dont les choses se passent : quel pourcentage des actions ont été réalisées et ce que fait exactement le programme maintenant. Et la fonction universelle d’affichage du formulaire de progression nous y aidera.

const
  PROGRESS_FORM_WIDTH = 400;
  PROGRESS_FORM_HEIGHT = 96;
  PROGRESS_FORM_FRAME_COLOR = clBlack;
  PROGRESS_IMAGE_SIZE = 80; // Taille de l’image animée
  PROGRESS_IMAGE_FILENAME = IMAGES_DIR + 'progress.gif';
  PROGRESS_FORM_CAPTION = 'Data processing';

Var 
  ProgressForm:TForm;

procedure Progress(ACurrent: Integer = 0; AMax: Integer = 0; AHint: string = ''; ACancelButton:boolean = False);
// Affiche la form du processus de progression
// ACurrent – valeur curante;
// AMax – valeur maximum : if AMax = 0, alors l’indicateur n’est pas affiché, on n’affiche qu’une explication
// AHint – cette explication
// Si elle est appelée sans paramètres, la form sera affichée mais invisible.
Var 
  tmpImage:TdbImage;
  tmpAppName: TdbLabel;
  tmpStatus: TdbLabel;
  tmpProgressBar: TProgressBar;
  tmpShape: TShape;
  tmpButton: TdbButton;
begin
  if ProgressForm = nil then
  begin
    ProgressForm := TForm.Create(Application);
    // La form
    with ProgressForm do
    begin
      Name := 'frmProgress';
      Caption := PROGRESS_FORM_CAPTION;
      Width := PROGRESS_FORM_WIDTH;
      Height := PROGRESS_FORM_HEIGHT;
      BorderStyle := bsNone;
      DoubleBuffered := True;
    end;
    // Le cadre
    tmpShape := TShape.Create(ProgressForm);
    with tmpShape do
    begin
      Name := T_SHAPE+'Border';
      Parent := ProgressForm;
      Align := alClient;
      Pen.Color := PROGRESS_FORM_FRAME_COLOR;
      Brush.Style := bsClear;
    end;
    // L’image animée
    tmpImage := TdbImage.Create(ProgressForm);
    with tmpImage do
    begin
      Name := T_IMAGE+'GIFAnimation';
      Parent := ProgressForm;
      Left := 0;
      Top := 8;
      Width := PROGRESS_IMAGE_SIZE;
      Height := PROGRESS_IMAGE_SIZE;
      Transparent := True;
      Picture.LoadFromFile( ExtractFilePath(Application.ExeName)+PROGRESS_IMAGE_FILENAME);
      // TGIFImage(Picture.Graphic).AnimationSpeed:= 500; // contrôle de la vitesse
    end;
    //Texte statique
    tmpAppName := TdbLabel.Create(ProgressForm);
    with tmpAppName do
    begin
      Name := T_LABEL+'AppName';
      Parent := ProgressForm;
      Autosize := False;
      Top := 0;
      Left := PROGRESS_IMAGE_SIZE;
      Height := 48;
      Width := PROGRESS_FORM_WIDTH - PROGRESS_IMAGE_SIZE - 8;
      LayOut := tlCenter;
      Alignment := taCenter;
      Caption := PROGRESS_FORM_CAPTION;
      Font.Size := 16;
    end;
    // Indicateur de la progression
    tmpProgressBar := TProgressBar.Create(ProgressForm);
    with tmpProgressBar do
    begin
      Name := 'prbIndicator';
      Parent := ProgressForm;
      Top := 48;
      Left := PROGRESS_IMAGE_SIZE;
      Height := 16;
      Width := tmpAppName.Width;
    end;
    // Explication sur l’action courante
    tmpStatus := TdbLabel.Create(ProgressForm);
    with tmpStatus do
    begin
      Name := T_LABEL+'Status';
      Parent := ProgressForm;
      Autosize := False;
      Top := 64;
      Left := PROGRESS_IMAGE_SIZE;
      Height := 32;
      Width := tmpAppName.Width;
      LayOut := tlCenter;
      Alignment := taRightJustify;
      Caption := '';
      Font.Size := 11;
      Font.Style := fsItalic;
    end;
    // Bouton d’arrêt
    tmpButton := TdbButton.Create(ProgressForm);
    with tmpButton do
    begin
      Name := 'btnCancel';
      Parent := ProgressForm;
      Width := 120;
      Height := 36;
      Font.Size := 11;
      Caption := ‘Abandon';
      Top := PROGRESS_FORM_HEIGHT;
      Left := PROGRESS_FORM_WIDTH - Width - PROGRESS_BUTTON_MARGIN;
      AssignEvents(tmpButton);
      dbOnClick := 'Progress_Cancel_OnClick';
      //Image du bouton
      Images_Set( tmpButton, DeleteSuffix(DeleteClassName(tmpButton.Name)), IMAGES_FORMAT_BUTTON, IMAGES_SIMPLE_MODEL );
    end;
  end;
  // Recherche des éléments
  FindC(ProgressForm,T_IMAGE+'GIFAnimation',tmpImage);
  FindC(ProgressForm,T_LABEL+'AppName',tmpAppName);
  FindC(ProgressForm,'prbIndicator',tmpProgressBar);
  FindC(ProgressForm,T_LABEL+'Status',tmpStatus);
  FindC(ProgressForm,'btnCancel',tmpButton);
  //
  if (ACurrent = 0) and (AMax = 0) and (AHint = '') then
  begin
    TGIFImage(tmpImage.Picture.Graphic).Animate := False; // On lance l’animation
    ProgressForm.Hide;
  end
  else
  begin
    TGIFImage(tmpImage.Picture.Graphic).Animate := True; // On arête l’animation
    // Réinitialiser l'indicateur d'interruption à chaque fois que le formulaire de progression apparaît.
    if not ProgressForm.Visible then
    begin
      if ACancelButton then
      begin
        ProgressCancel := False;
        ProgressForm.Height := tmpButton.Top + tmpButton.Height + PROGRESS_BUTTON_MARGIN;
      end
    else
    begin
      ProgressForm.Height := PROGRESS_FORM_HEIGHT;
    end;
  end;
  ProgressForm.Show;
  Form_Centered(ProgressForm);
  tmpStatus.Caption := AHint + ' '; // Un espace est nécessaire pour afficher correctement la police italique
  if AMax = 0 then
  begin
    tmpProgressBar.Visible := False;
  end
  else
  begin
    tmpProgressBar.Visible := True;
    tmpProgressBar.Max := AMax;
    tmpProgressBar.Position := ACurrent;
  end;
  Application.ProcessMessages;
  end;
end;

procedure Progress_Cancel_OnClick( Sender: TObject; var Cancel: boolean);
begin
  ProgressCancel := True;
End;Langage du code : Delphi (delphi)

Pour afficher le formulaire de progression, il suffit d’appeler la procédure Progress() avec des paramètres non vides :

  • ACurrent – valeur de la progression actuelle;
  • AMax – valeur maximale : si AMax = 0, alors l’indicateur n’est pas affiché
  • AHint – explication affichée sur le formulaire
  • ACancelButton – afficher un bouton d’interruption de processus

Pour masquer le formulaire de progression, vous devez appeler la procédure Progress() sans paramètre.

Les lignes 26 à 121 du script vérifient si le formulaire à afficher existe et le crée si nécessaire. Le formulaire contient du texte statique, une explication et un indicateur de progression – une instance de la classe TProgressBar.

Sur le côté gauche du formulaire se trouve une image animée chargée à partir d’un fichier GIF, qui donne vie au formulaire.

La procédure FindC() recherche un composant par son nom sur le formulaire et le place dans la variable spécifiée.

procedure FindC(AForm: TForm; AName: string; var AComponent: TComponent; ACheck: boolean = True);
// Recherche d’un composant sur un formulaire avec contrôle
begin
  if AForm = nil then
    RaiseException('FindC() - AForm = nil');
  AComponent := AForm.FindComponent(AName);
  if ACheck and (AComponent = nil) then
    RaiseException('FindC() - Component not found: ' + AForm.Name + '.' + AName);
end;Langage du code : Delphi (delphi)

La procédure Form_Centered() centre le formulaire sur l’écran.

procedure Form_Centered(Sender: TObject);
// Place la forme au centre de l’écran
var 
  tmpForm: TAForm;
begin
  tmpForm := TAForm(Sender);
  tmpForm.Left := (Screen.Width - tmpForm.Width) div 2;
  tmpForm.Top := (Screen.Height - tmpForm.Height) div 2;
end;
Langage du code : Delphi (delphi)

Un exemple d’utilisation de la procedure Progress() :

Progress(0,0,'Actualisation de la liste des projets');
tmpSQL := 'SELECT count(*) FROM project';
tmpMaxCount := SQLExecute(tmpSQL);
tmpCount := 0;
try
  // Vérification des enregistrements existants
  tmpSQL := 'SELECT * FROM project';
  SQLQuery(tmpSQL,tmpDataSet);
  try
    while not tmpDataSet.EOF do
    begin
      Progress(tmpCount,tmpMaxCount,'Contrôle des dossiers');
      if not DirectoryExists( tmpDataSet.FieldByName('path').asString ) then
      begin
        tmpSQL := 'UPDATE project SET status = "Path not found" WHERE id = '+tmpDataSet.FieldByName('id').asString;
        SQLExecute(tmpSQL);
      end;
      tmpDataSet.Next;
      inc(tmpCount);
    end;
  finally
    tmpDataSet.Free;
  end;
finally
  Progress();
end;
Langage du code : Delphi (delphi)

Le formulaire est rendu conformément au thème de style d’application sélectionné et s’intègre parfaitement dans la conception globale de l’application.

Si vous utilisez le paramètre, le formulaire de progression augmentera en hauteur afin que le bouton d’interruption de traitement devienne disponible. Lorsque le bouton est cliqué, la valeur de la variable globale ProgressCancel est définie sur True. Cela peut être utilisé dans les algorithmes de tourniquet pour interrompre le traitement précoce.

Mais pour atteindre l’idéal, vous devrez peut-être ajouter une fonction qui sélectionnera un fichier pour l’animation, en fonction du style sélectionné, afin que les couleurs de l’image correspondent à la couleur du formulaire.

Selon vous, qu’est-ce qu’une forme de progrès devrait pouvoir faire d’autre ?

J’ai utilisé ce formulaire dans l’application Manuel du développeur, dans la nouvelle fonctionnalité liée au projet. Au cours de plusieurs années de travail et de lecture du forum, j’ai accumulé de nombreuses applications créées à l’aide de My Visual Database, et j’ai décidé d’ajouter un outil pratique pour les classer, ainsi que pour améliorer le travail avec les modules, dans le livre de référence du développeur. Mais j’en parlerai dans le prochain article.

Traduction : Yann Yvnec

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *