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