unit Unit1;

interface

uses
SysUtils, Classes, QGraphics, QControls, QForms, QDialogs,
  QExtCtrls, QStdCtrls, QButtons, QImgList;

type

  TForm1 = class(TForm)
   PanelExec: TPanel;
   Bevel1: TBevel;
   Imagexec: TImage;
   Imagestop: TImage;
   ImageStep: TImage;
   BitBtnExec: TBitBtn;
   BitBtninterrup: TBitBtn;
   RadioButtonTrace: TRadioButton;
   RadioButtonPasapas: TRadioButton;
   BitBtnStep: TBitBtn;
   Timer1: TTimer;
   Timer2: TTimer;
   ImageListTrace: TImageList;
   Label1: TLabel;
   Label2: TLabel;
   procedure Timer1Timer(Sender: TObject);
   procedure Timer2Timer(Sender: TObject);
   procedure BitBtnExecClick(Sender: TObject);
   procedure BitBtninterrupClick(Sender: TObject);
   procedure RadioButtonTraceClick(Sender: TObject);
   procedure RadioButtonPasapasClick(Sender: TObject);
   procedure BitBtnStepClick(Sender: TObject);
  private
   { Déclarations privées }
   procedure Waitime;
  public
   { Déclarations publiques }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
var
Gtiming:integer;  // compte le nombre de passage timer
GNextStep,GStop:boolean; // flag "pas suivant" et "interrompre"
TMode:(Trace,Pasapas);   // flag trace automatique ou pas à pas
flashImageStep:boolean;  // var locale pour clignotement

procedure
TForm1.RadioButtonTraceClick(Sender: TObject);
// positionne le flag TMode en mode trace
begin
BitBtnStep.enabled:=false;
Timer2.enabled:=false;
TMode:=Trace;
end;

procedure TForm1.RadioButtonPasapasClick(Sender: TObject);
// positionne le flag TMode en mode pas à pas
begin
GNextStep:=false;   // flag "pas suivant" baissé
TMode:=Pasapas;
if Gstop=false then // si l'utilisateur n'a pas déjà interrompu
begin
  BitBtnStep.enabled:=true;
  Timer2.enabled:=true;
  RadioButtonTrace.enabled:=false;
end
end
;

procedure TForm1.Timer1Timer(Sender: TObject);
const nbrsec=1;   // durée=Timer1.interval*nbrsec(en miliseconde)
begin
if (Gtiming=nbrsec)or(GStop=true) then
begin
  Gtiming:=0;
  timer1.enabled:=false
end
else

  Gtiming:=Gtiming+1;
end;

procedure TForm1.BitBtnExecClick(Sender: TObject);
var IconeTrace: TBitmap;
begin
GStop:=false;
ImageStep.visible:=true;
if TMode=Pasapas then
begin
  BitBtnStep.enabled:=true;
  Timer2.enabled:=true;
  RadioButtonTrace.enabled:=false
end;
BitBtnExec.enabled:=false;
Imagexec.visible:=true;
BitBtninterrup.enabled:=true;
Imagestop.visible:=false;

(* ------  Actions à exécuter : ------ *)

while GStop=false do begin

  //.... vos actions
  if Label1.Left>=Form1.Width-Label1.Width-15 then Label1.Left:=0
  else Label1.Left:= Label1.Left+10; //ici déplacement de la label
  if Label2.Top>=Form1.Height-Label2.Height-30 then Label2.top:=0
  else Label2.Top:= Label2.Top+5;
  //.... vos actions

  Waitime; //temporisation obligatoire !!
end;
(* -------- fin des actions ------ *)

BitBtnExec.enabled:=true;
Imagexec.visible:=false;
BitBtninterrup.enabled:=false;
RadioButtonTrace.enabled:=true;
RadioButtonPasapas.enabled:=true;
Timer2.enabled:=false;
IconeTrace:=TBitmap.create;
ImageListTrace.GetBitmap(0,IconeTrace);
ImageStep.Picture.Assign(IconeTrace);
IconeTrace.free
end;

procedure TForm1.BitBtninterrupClick(Sender: TObject);
// arrête toutes les boucles et les calculs en cours
begin
GStop:=true;
BitBtnExec.enabled:=true;
Imagexec.visible:=false;
Imagestop.visible:=true;
BitBtnStep.enabled:=false;
ImageStep.visible:=true;
Timer2.enabled:=false;
RadioButtonTrace.enabled:=false;
RadioButtonPasapas.enabled:=false;
end;

procedure TForm1.BitBtnStepClick(Sender: TObject);
// bouton de passage au pas suivant
begin
if GNextStep=false then
  GNextStep:=true;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
//timer de flash d'une image (alternance entre 2 images)
var  IconeTrace:TBitmap;
begin
IconeTrace:=TBitmap.create;
if flashImageStep  then
begin
  ImageListTrace.GetBitmap(0,IconeTrace);
  ImageStep.Picture.Assign(IconeTrace);
end
else
begin

  ImageListTrace.GetBitmap(1,IconeTrace);
  ImageStep.Picture.Assign(IconeTrace);
end;
flashImageStep:=not flashImageStep;
IconeTrace.free
end;

//----------- Temporisation à l'intérieure d'un boucle  -----------
procedure TForm1.Waitime;
{assure le timing en pas à pas et en trace automatique  :
deux boucles infinies sont à la base de la temporisation.
repeat
   Application.ProcessMessages; // redonne la main à Windows
  until ...
pendant la boucle le système traite les messages de l'utilisateur
on peut tester dans le until les actions effectuées durant l'attente
}

begin
if GStop=true then  // le bouton interruption a été clické
begin
  Timer1.enabled:=false;   // arrêt du timing
  exit
end
else
if
TMode=Trace then    // le bouton trace a été clické
begin
  Timer1.enabled:=true; // lancement du time r
  Gtiming:=0; // RAZ timing
  repeat    // on attend que le timer ait terminé le décompte
   Application.ProcessMessages; // redonne la main à Windows
  until Timer1.enabled=false   // false après nbrsec d'attente
end
else
{pasapas}
begin
  Timer1.enabled:=false;{par précaution plus de timing}
  GNextStep:=false;{RAZ avant appui du bouton "pas suivant"}
  repeat  // on attend que l'utilisateur appui soit sur :
         // le bouton interrompre (GStop=true)
         // soit sur le bouton pas suivant ( GNextStep=true)

   Application.ProcessMessages;  // redonne la main à Windows
                                       // arrêt si bouton "pas suivant" clické

  until (GNextStep=true)or(GStop=true); // ou si bouton interrompre clické
  GNextStep:=false;{RAZ après appui du bouton "pas suivant"}
end
end
;

initialization

Gstop:=true
end.