1. Le contrôle de l’exécution en Delphi
...
2.
Exemples de contrôle de l’exécution en Delphi ...
3.
Le contrôle de l’exécution en Visual Basic ...
4.
Exemple de contrôle de l’exécution en Visual Basic ...
1. Le contrôle de l’exécution en Delphi
Les programmes s’exécutent
séquentiellement jusqu'à leur fin normale. Le programmeur peut
vouloir arrêter, interrompre temporairement, mettre en attente, ou
sauter l’exécution de portions de code. Cette opération se
définit comme le contrôle du flux d’exécution. Nous pouvons,
sans entrer dans des détails de bas niveau inutiles pour le débutant,
indiquer de quels moyens nous disposons pour contrôler ce flux.
1.1 le contrôle par les instructions structurées
Le premier niveau de contrôle de l’exécution que découvre l’étudiant, se situe dans la méthodologie de conception structurée descendante.
1.2 le contrôle par des procédures
La conception structurée par bloc donne le pouvoir aux procédures et aux fonctions de n’être exécutées que lorsque le programmeur décide de les " appeler ".
Il existe en Delphi des procédures
spéciales destinées uniquement au contrôle du flux d’exécution.
Procedure Break ;
Procedure Exit ; Procedure Halt ; |
Description :
La procédure Break, qui doit obligatoirement se trouver dans le corps d’une boucle while, for, repeat, fait quitter le flux de contrôle d'une instruction while, for, repeat, et poursuit l’exécution à la prochaine instruction qui suit l'instruction de boucle.
La procédure Exit se trouve obligatoirement dans une procédure ou dans une fonction ; elle fait passer le contrôle du flux d'exécution en dehors de la procédure. Si la procédure en cours est le programme principal, Exit termine l'exécution du programme. Exit continue la poursuite de l’exécution dans la procédure appelante avec l'instruction qui suit celle qui a appelé la procédure contenant le Exit.
La procédure Halt met fin volontairement à l’exécution d'un programme et renvoie le contrôle au système d'exploitation.
(Mentionnons aussi
dans ce cadre les procédures Continue et RunError)
1.3 le contrôle par
la fiche principale
Méthode Close |
Utilisation de la méthode Close pour fermer une fiche et le code associé.
Si la fermeture est possible,
l'événement OnClose a lieu. Si la fiche est la
fiche principale de l'application, la méthode Close termine l'application.
Exemple avec une seule fiche Form1 (donc principale) :
Le gestionnaire du bouton termine l’application
|
1.4 le contrôle par la variable Application
A chaque fois que nous écrivons
un programme en Delphi (nommé un projet), il lui est associé
lors de l’exécution un objet non visible nommé Application qui
encapsule tout notre programme. Il est possible d'exploiter cet objet Application
pour récupérer des informations concernant l'application en
cours d'exécution.
var Application: TApplication |
Comme toutes les classes, la
classe TApplication possède des méthodes et des événements.
Nous utilisons ici deux méthodes permettant d’interrompre le flux d’exécution
de notre application.
Méthode Terminate |
La méthode Terminate appelle la fonction PostQuitMessage
de l'API Windows pour effectuer la fermeture de l'application. PostQuitMessage
est une fonction de l'API windows qui signale au système qu'un thread
a introduit une requête de terminaison.
Méthode ProcessMessages |
La méthode ProcessMessages interrompt l'exécution de l'application pour que Windows puisse répondre aux événements présents dans la file d’attente de Windows. La méthode ProcessMessages interrompt le code qui l’a lancée pour parcourir la file d’attente des messages Windows jusqu'à ce que cette file soit vide, puis rend le contrôle du flux d’exécution à l'application.
Nous allons voir plus loin
des exemples de tels contrôles. Pour l’instant terminons ce petit tour
d’horizon avec un dernier outil faisant intervenir l’horloge interne de l’ordinateur
et la notion de temps.
Le programmeur peut vouloir interrompre son flux d’exécution non pas pour aller faire exécuter des messages venant d’ailleurs, mais tout simplement afin de temporiser des affichages ou des traitements. Dans un ordinateur, tout s’exécute à la vitesse de traitement des instructions, vitesse qui reste la même pour une instruction donnée. Il est clair que le souci de " ralentir " l’exécution du code est plus lié à la communication dans l’interface plutôt qu’au traitement interne des données qui souvent a besoin d’être accéléré.
Elle possède deux propriétés intéressantes :
property Enabled: Boolean; |
property Interval: Cardinal; |
Elle est sensible à un seul événement :
property OnTimer: TNotifyEvent; |
Exemple
var
Changer :boolean ;
Timer1.Interval := 250; // 250 ms On veut faire clignoter le fond de Edit1 alternativement
|
Le gestionnaire de l’événement OnTimer lancé toutes les 250 ms:
procedure TForm1.Timer1Timer(Sender: TObject);
begin if Changer then begin Edit1.color :=clblue ; Changer :=false // change alternativement de valeur end else begin Edit1. color :=clRed ; Changer :=true // change alternativement de valeur end end; |
Les
boutons servent à lancer,interrompre, reprendre
ou arrêter définitivement l’ exécution de la boucle
:
for i:=1 to 2000 do... qui affiche dans le Memo1 la valeur de l’indice i. Edit1 contient le
n° du "i" lors de l’appui sur Interrompre. Edit2 contient le n° du "i" lors de l’appui sur Arrêter. |
Code proposé pour ce contrôle de flux :
var FlagStop, FlagInterrupt:boolean; |
procedure
RAZTout; begin with Form1 do begin FlagInterrupt:=false; FlagStop:=false; Memo1.clear; Edit1.text:=''; Edit2.text:=''; end end; |
procedure
TForm1.ButtonArretClick(Sender: TObject); begin FlagStop:=true; // flag levé end; |
procedure
TForm1.ButtonInterruptClick(Sender: TObject); begin FlagInterrupt:=true; // flag levé end; |
procedure
TForm1.ButtonrepriseClick(Sender: TObject); begin FlagInterrupt:=false; // flag baissé end; |
procedure
TForm1.ButtonLancerClick(Sender: TObject); var i:integer; begin RAZTout; for i:=1 to 2000 do begin Memo1.lines.add(inttostr(i)); Application.ProcessMessages; if FlagStop then begin Edit2.text:='Arrêt demandé: '+inttostr(i); FlagStop:=false; Exit end; if FlagInterrupt thenbegin Edit1.text:='Interruption: '+inttostr(i); Repeat Application.ProcessMessages; until (FlagInterrupt=false)or(FlagStop=true) ; end end; Edit1.text:='Fin de la boucle ' end; |
2.2 Quelques explications sur le code
La structure générale
de la boucle est la suivante :
for
i:=1 to 2000 dobegin Memo1.lines.add(inttostr(i)); Application.ProcessMessages; if FlagStop then ... ; if FlagInterrupt then ... ; end ; |
L’appel à la méthode
ProcessMessages libère le système
en lui donnant " la main " par interruption de la boucle (le temps au système
de traiter les messages en suspens comme clic de souris, clavier etc...).
Si pendant l’interruption l’utilisateur n’a rien fait, la boucle continue.
Si par contre l’utilisateur a clické sur le ButtonInterrupt, le système
a alors eu le temps de faire exécuter (pendant l’interruption de la
boucle) le gestionnaire ButtonInterruptClick qui a mis le FlagInterrupt à
true. Lorsque la boucle reprend (après la fin du traitement des messages)
l’instruction if FlagInterrupt then ... déroute l’exécution
dans l’instruction composée qui suit le then.
Il en est de même lorsque
l’utilisateur a cliqué sur le ButtonArret le système a eu le
temps de faire exécuter (pendant l’interruption de la boucle) le gestionnaire
ButtonArretClick et a mis le FlagStop à true. Lorsque la boucle reprend
(après la fin du traitement des messages) l’instruction if FlagStop
then ... déroute l’exécution dans l’instruction composée
qui suit le then.
Traitement après le clic sur ButtonArret:
if
FlagStop then begin Edit2.text:='Arrêt demandé: '+inttostr(i); FlagStop:=false; Exit end; |
L’appel à la procédure
Exit fait sortir du gestionnaire qui l’a appelé en l’occurrence la
procedure TForm1.ButtonLancerClick.
Traitement après le click sur ButtonInterrupt:
if
FlagInterrupt thenbegin Edit1.text:='Interruption: '+inttostr(i); repeat Application.ProcessMessages; until (FlagInterrupt=false)or(FlagStop=true) end; |
Nous avons remis une boucle repeat...until qui semble être une boucle infinie, mais qui n’en est pas une (c’est une façon très classique de procéder dans ce genre de cas). Cette boucle bloque le flux d’exécution de ce programmme, mais ne bloque pas le traitement des messages systèmes par l’appel à la méthode ProcessMessages.
Nous allons profiter du fait que l’utilisateur peut pendant que la boucle repeat...until s’exécute, cliquer soit sur le ButtonArret, soit sur le Buttonreprise. Dans l’éventualité d’un tel clic, l’un des deux flags FlagInterrupt ou FlagStop est modifié ce qui a pour effet de sortir de la boucle " infinie " repeat...until.
Si l’utilisateur a cliqué sur le Buttonreprise, la boucle for continue son exécution comme précédemment.
Si l’utilisateur a cliqué
sur le ButtonArret, la boucle for continue son exécution pour un tour
seulement jusqu'à l’instruction if FlagStop then... qui
met fin à l’exécution de cette boucle.
Etudiez l’exemple comportant deux fiches dans :
Delphi.ProcessMessages\Message2fiches
3. Le contrôle de l’exécution
en Visual Basic
3.1. Présentation
des structures de contrôle
Les structures de décision
Les fonctions de sélection Les structures de boucle |
Les structures de contrôle
permettent de contrôler le déroulement de l'exécution
d'un programme. Si elle n'est pas vérifiée par des instructions
de contrôle du déroulement, la logique d'un programme parcourt
ces instructions de gauche à droite, de haut en bas de manière
séquentielle. La puissance et l'utilité même d'un langage
de programmation orienté objet découlent de sa capacité
à modifier l'ordre des instructions par des structures et des boucles.
Instruction If...Then |
La structure If...Then
permet d'exécuter une ou plusieurs instructions si certaines conditions
sont remplies. On peut utiliser une syntaxe monoligne :
Ifcondition
Then instruction |
ou une syntaxe multiligne
en blocs :
Ifcondition
Then instructionsEnd If |
Instruction If...Then..Else |
Le bloc If...Then...Else
permet de définir plusieurs blocs d'instructions dont un seul est exécuté
:
Ifcondition1
Then [instruction block-1][ElseIf condition2 Then [instruction block-2]]...[Else [instruction block-n]] End If |
Instruction Select Case |
Une instruction Select
Case assure des fonctionnalités similaires à celles de l'instruction
If...Then...Else, mais améliore la lisibilité du code
en présence de choix multiples. Une structure Select Case n'utilise
qu'une seule expression de test qui est évaluée une seule fois,
au début de la structure. Visual Basic compare ensuite le résultat
de cette expression aux valeurs de chaque clause Case de la structure. Si
les valeurs concordent, il exécute le bloc d'instructions associé
à cette clause Case :
Select Case
expression
[Caseexpression1 [instruction block-1]]End Select |
Les 3 instructions suivantes
sont issues du macrolangage VBA. Ce ne sont pas des structures de décision
à proprement parlé, mais elles constituent quand même
des outils de décision.
fonction IIf (...) |
IIf évalue
une expression et, selon la valeur logique prise par cette expression, affecte
une valeur ou une autre à une variable :
Valeur = IIf (expression, ValeurSiVrai, ValeurSiFaux) |
Les 2 tableaux de lignes
de code suivants sont identiques, quant au résultat :
Dim
x as integer
Dim y as integer ... If x > 100 then y = 1Else y = 10End If |
Dim
x as integer
Dim y as integer ... y% = IIf
( x% > 100 , 1 , 10 )
|
fonction Choose (...) |
Choose sélectionne
et renvoie une valeur dans une liste d'arguments :
Valeur = Choose ( Index , sélection1 [, selection2 , ... [, sélectionN]]) |
Les 2 tableaux de lignes
de code suivants sont identiques, quant au résultat :
Dim
A as String
... Select Case Index Case 1 A = "Rouge"Case 2 A = "Vert"Case 3 A = "Bleu"Case Else A = ""End Select |
Dim
A as String
... A = Choose
(Index, "Rouge", "Vert", "Bleu")
|
fonction Switch (...) |
Switch évalue une
liste de conditions et renvoie la valeur ou l'expression correspondant à
la première condition remplie:
Valeur = Switch (Expression1, Valeur1 [,Expression2, Valeur2] ... [,ExpressionN, ValeurN]) |
Ainsi, les 2 tableaux
de lignes de code suivants sont identiques, quant au résultat :
Dim
Couleur as String
Dim A as Integer ... If Couleur = "Rouge" Then A = 1ElseIf Couleur="Vert" Then A = 2ElseIf Couleur="Bleu" Then A = 3End If |
Dim
Couleur as String
Dim A as Integer ... A = Switch (Couleur = "Rouge", 1, _ Couleur="Vert", 2, _
|
Instruction Do..Loop |
La boucle Do permet d'exécuter un bloc d'instructions un nombre infini de fois. Il existe plusieurs variantes de l'instruction Do...Loop, mais elles évaluent chacune une condition numérique pour déterminer si l'exécution doit être poursuivie.
Dans les boucles Do...Loop
suivantes, les instructions sont exécutées aussi longtemps que
'condition' est True (boucle do while) ou False (boucle dountil)
:
Do Whilecondition
instructions Loop |
Do Untilcondition
instructions Loop |
Une autre variante de
l'instruction Do...Loop exécute tout d'abord les instructions,
puis teste la condition après chaque exécution. Cette variante
garantit au moins une exécution de 'instructions' :
Do
instructions Loop While condition |
Do
instructions Loop Until condition |
Instruction For..Next |
Contrairement à
la boucle Do, la boucle For inclut une variable appelée compteur dont
la valeur augmente (ou diminue) à chaque itération de la boucle
:
Forcompteur
= début To fin [Step increment]
instructions Next [compteur ] |
Instruction For..Each |
Une boucle For Each...Next
est semblable à une boucle For...Next, à la différence
toutefois qu'elle répète un groupe d'instructions pour chaque
élément d'une collection d'objets ou d'un tableau, plutôt
que de répéter les instructions un certain nombre de fois. Cette
boucle est utile lorsque l'on ne connaît pas le nombre d'éléments
d'une collection (groupe d'objets par exemple) :
For Each element
In groupe
instructions Next element |
3.2 utilisation des structures de contrôle
Structures de contrôle imbriquées
Sortie d'une structure de contrôle Sortie d'une procédure sub, fonction, ou property |
Structures de contrôle imbriquées
Il est possible de placer des structures de contrôle au sein d'autres structures de contrôle (un bloc If...Then au sein d'une boucle For...Next, par exemple).
Le nombre de niveaux d'imbrication dans les structures de contrôle est illimité en Visual Basic. L'imbrication permet de représenter des structures de décision ou des structures en boucle de manière plus lisible en mettant en retrait le corps de la structure de décision ou de la boucle.
Dans les instructions
If imbriquées, les instructions End If s'appliquent
automatiquement à l'instruction If précédente
la plus proche. Les structures Do...Loop fonctionnent de façon
similaire, l'instruction Loop la plus imbriquée correspondant
à l'instruction Do la plus imbriquée.
Sortie d'une structure de contrôle
Instruction Exit |
L'instruction EXIT permet de sortir directement d'une boucle For ou Do, ou encore d'une procédure Sub, Function ou Property.
La syntaxe de l'instruction
Exit est simple : Exit For peut apparaître autant de
fois qu'il est nécessaire à l'intérieur d'une boucle
For, et il en est de même pour Exit Do dans une boucle
Do :
For compteur
= début To fin [Step increment]
instructions [Exit For] instructions Next element |
Do [{While
| Until} condition]
instructions [Exit Do] instructions Loop |
Remarque
L'instruction Exit Do fonctionne avec toutes les versions de la syntaxe de la boucle. Une instruction Exit apparaît presque toujours dans une instruction If ou Select Case imbriquée dans la boucle. |
Sortie d'une procédure sub, fonction, ou property
Il est possible de quitter
une procédure à partir d'une structure de contrôle.
La syntaxe de Exit Sub, Exit Function et de Exit Property est semblable à celle de Exit For et de Exit Do. |
Exit Sub, ExitFunction et Exit Property peuvent apparaître autant de fois qu'il le faut dans le corps de la procédure. L'exécution se poursuit par l'instruction suivant celle qui a appelé la propriété. |
Pour temporiser l'affichage ou les traitement de son application, le programmeur peut utiliser la classe non visuelle fournit par VB6 :
La classe Timer :
Elle dispose de 2 propriétés
principales et n'est sensible qu'à un seul évènement
:
Propriété
:
Enabled |
Renvoie ou définit une valeur qui détermine si une feuille ou un contrôle peuvent répondre aux événements générés par l'utilisateur. |
Propriété
:
Interval |
Renvoie ou définit le nombre de millisecondes s'écoulant entre deux appels de l'événement Timer d'un contrôle Timer. |
Evènement
:
Timer |
Se produit lorsque l'intervalle prédéfini pour un contrôle Timer est écoulé. La fréquence de l'intervalle est stockée dans la propriété Interval du contrôle et spécifie une durée en millisecondes. |
Exemple :
Le fond de Text1 clignote
alternativement du jaune au blanc, toutes les 250 ms.
Instruction Stop |
L'instruction Stop peut être placée n'importe où dans les procédures afin d'en interrompre l'exécution. Cela revient à placer un point d'arrêt dans le code. Elle ne doit être utilisée que pour le test d'un programme.
L'instruction Stop
interrompt l'exécution d'un programme, mais contrairement à
End, elle ne ferme pas les fichiers et n'efface pas les variables (sauf si
elle est placée dans un fichier exécutable .exe compilé).
Instruction End |
L'instruction End met
immédiatement fin, et de manière inconditionnelle, à
l'exécution du code, sans appeler d'événement Unload,
QueryUnload, ou Terminate, ou tout autre code Visual Basic.
Instruction Unload |
L'instruction End permet
de forcer l'arrêt du programme. Pour qu'un programme Visual Basic se
termine normalement, il est préférable de décharger toutes
les feuilles avec l'instruction UNLOAD. Son exécution en liaison avec
des feuilles déclenche 3 autres évènements, c'est à
dire QueryUnload, Unload et Terminate.
Evènement : QueryUnload | Se produit avant la fermeture d'une feuille ou d'une application. Lorsqu'un objet MDIForm se ferme, l'événement QueryUnload se produit d'abord pour lafeuille MDI, puis dans toutes les feuillesfilles MDI. Si aucune feuille n'annule l'événement QueryUnload, l'événement Unload se produit dans toutes les autres feuilles avant de s'appliquer à une feuille MDI. Lorsqu'une feuille fille ou un objet Form se ferme, l'événement QueryUnload de cette feuille intervient avant l'événement Unload de la feuille. |
Evènement : Unload | Se produit lorsqu'une feuille est sur le point d'être supprimée à l'écran. Lorsque cette feuille est chargée à nouveau, le contenu de tous ses contrôles est réinitialisé. Cet événement est déclenché par une instruction Unload ou lorsque l'utilisateur ferme la feuille en cliquant dans le menu Système sur la commande Fermeture. |
Evènement : Terminate | Se produit lorsque toutes les références à une instance d'un objet Form, MDIForm, UserControl, PropertyPage ou d'une classe sont supprimées de la mémoire soit parce que la valeur Nothing a été affectée à toutes les variables faisant référence à l'objet, soit parce que la dernière référence à l'objet est hors deportée. |
Exemple :
La ficheForm1 est déchargée
lors d'un clic sur la feuille, et l'on demande à l'utilisateur de valider
la sortie de l'application.
Si l'utilisateur clique sur 'Oui', la feuille est affichée, la procédure sub se termine mais l'application reste active.
4. Exemple de contrôle de l’exécution
en Visual Basic
4.1 le contrôle par la fonction DoEvents
La fonction DoEvents passe le contrôle au noyau du système d'exploitation. L'application reprend le contrôle dès que toutes les autres applications de l'environnement ont répondu aux événements en attente. Le focus reste toujours sur l'application en cours, mais le traitement des événements en arrière-plan est activé.
Attention
lorsque un processeur reprend la main de manière temporaire dans une procédure d'événement, la procédure ne doit pas être exécutée à nouveau par une autre portion du programme, avant que le résultat du premier appel ne soit renvoyé. Cette situation peut avoir des conséquences inattendues : fin de procédures dans l'ordre inverse de leur appel, renvoie de résultats inattendus dans le cas ou la procédure utilise des variables globales... |
Remarque
En outre, il faut éviter d'utiliser DoEvents s'il existe un risque d'interaction imprévisible entre d'autres applications et la procédure pendant que l'exécution est suspendue. |
Exemple :
Dans le code suivant, la
fonction DoEvents permet l'annulation d'une tâche. Un premier clic
sur le bouton Lancer fait démarrer une boucle de calcul de 5 millions
d'opération en virgule flottante. Un second clic interrompt la tâche
en cours d'exécution.
Exécution du programme avec un seul clic ! |
Exécution
du programme avec 2 clic ! |
Visual Basic 6 dispose de nombreuses structures de contrôle (fonctions de sélection...) qui permettent de s'éloigner de la programmation séquentielle et de structurer les lignes de codes du programmeur.
Attention cependant,
car pour des raisons de compatibilité avec les anciennes versions,
VB6 dispose toujours des instructions de saut GOTO et GOSUB. Ces instructions
ne doivent être utilisées que pour l'importation d'anciens textes
sources. Elles seront avantageusement remplacées par des procédures
personnalisées et des structures étendues de contrôle.
L'application créée sous VB6 n'est pas un objet comme en Delphi. Ainsi, il n'existe pas de méthode associée pour stopper son exécution telle que Application.Terminate. |