Les Fonctions et les Flags

De Wiki AutoIt Français
Aller à : navigation, rechercher

Pour débuter ce tutoriel, vous devrez avoir un minimum de connaissances sur l'utilisation de Scite, l'éditeur de code fournit avec AutoIt, afin de pouvoir écrire et exécuter les exemples de code qui seront présentés ci-dessous.


Bases sur les fonctions et les paramètres

Définition d'une fonction :
En informatique, une fonction est un ensemble d'instructions réalisant certaine(s) tâche(s).
Une fonction prend zéro, un ou plusieurs paramètres et renvoie toujours un résultat.


Ma première fonction

Voici un exemple de l'appel à une fonction :

Ma_Fonction()


Voici le code d'une fonction de base (avec code de retour) :

Func Ma_Fonction()
	; Ici on met le code à exécuter.
	Return 1 ; Ici on renvoi le résultat (code de retour).
EndFunc


Maintenant que nous savons créer une fonction, nous allons lui demander d'exécuter une action. Pour ce faire, nous allons utiliser une fonction interne à l'interpréteur AutoIt.exe. Cette fonction s'appelle MsgBox() et affiche simplement une boite de dialogue.
Cette fonction utilise plusieurs paramètres que nous détaillerons ultérieurement pour les besoins de ce tutoriel. Mais pour l'instant, nous allons l'utiliser simplement pour afficher un texte tout bête.
Reprenons donc le code de la fonction précédente, et faisons-lui afficher dans une boite de dialogue basique un simple 'Hello World'.

  • Pour les besoins du tutoriel, l'appel de la fonction et la fonction elle même se suivent. Mais dans un code plus complexe, il est de bonne pratique de regrouper les fonctions à la fin du code ou dans un fichier secondaire qui sera inclus par l'appel à un mot clé spécifique.


Ma_Fonction()

Func Ma_Fonction()
	MsgBox(0, "", "Hello World")
	Return 1
EndFunc


Si l'utilisation d'une fonction était limitée à cela, l’intérêt de celle-ci serait bien pauvre. Mais nous allons voir maintenant deux notions supplémentaires.
Tout d'abord, nous allons envoyer un paramètre à la fonction, afin de lui faire afficher un texte de notre choix lors de l'appel à celle-ci, puis nous allons exploiter la valeur de retour.

Ajout d'un paramètre à une fonction

Ma_Fonction("Bonjour tout le monde")

Func Ma_Fonction($Param)
	MsgBox(0, "", $Param)
	Return 1
EndFunc

Dans le cas présent, le texte "Bonjour tout le monde" est attribué à la variable $Param puis traité à l'intérieur de la fonction.
La valeur 1 est renvoyée en code retour, afin d'indiquer le bon déroulement de la fonction.

Retour simple de fonction

Maintenant que nous avons vu la notion d'envoi de paramètre, voyons aussi la partie retour de valeur(s).
Une fonction peut renvoyer plusieurs types de valeurs, et cela, de plusieurs manières différentes.
Une des manières courantes, utilise la commande Return.


Nous allons voir maintenant, grâce à une nouvelle fonction que l'on nommera pour l'exemple Mon_Addition() comment une fonction peut ajouter la valeur d'un paramètre à une valeur définie, puis afficher le résultat :

$Retour = Mon_Addition(2)
MsgBox(0, "", $Retour)

Func Mon_Addition($Param)
	Return 1 + $Param
EndFunc

Dans cet exemple, nous exécutons la fonctions Mon_Addition() avec le chiffre 2 en paramètre, puis nous récupérons la valeur de retour de la fonction dans une variable nommée $Retour et enfin, nous affichons la valeur de celle-ci dans une boite de dialogue simple.

Dans la fonction elle-même, nous retournons directement l'addition du nombre 1 et du paramètre passé à la variable $Param (2), ce qui nous donne une valeur de retour de 3 (qui est bien la valeur affichée par la boite de dialogue).


Voyons maintenant, un cas concret un peut plus évolué :

$Ret = Ma_Fonction("Cliquez sur Oui ou sur Non")
If $Ret = 6 Then
	MsgBox(0, "", "Vous avez cliqué sur Oui")
Else
	MsgBox(0, "", "Vous avez cliqué sur Non")
EndIf

Func Ma_Fonction($Param)
	$Retour = MsgBox(4, "", $Param)
	Return $Retour
EndFunc

Dans cet exemple, nous exécutons la fonctions Ma_Fonction() avec un texte en paramètre, puis nous récupérons la valeur de retour de la fonction MsgBox dans une variable nommée $Retour, que nous renvoyons avec la commande Return et enfin, nous exploitons ce retour de fonction par un test de la valeur afin d'afficher le message qui correspond.

Pour information, le code ci-dessus peut être condensé/optimisé par ceci :

If Ma_Fonction("Cliquez sur Oui ou sur Non") = 6 Then
	MsgBox(0, "", "Vous avez cliqué sur Oui")
Else
	MsgBox(0, "", "Vous avez cliqué sur Non")
EndIf

Func Ma_Fonction($Param)
	Return MsgBox(4, "", $Param)
EndFunc


Lors de l'utilisation d'une fonction, il est de bonne pratique d'utiliser un code retour confirmant que la fonction s'est bien déroulée. Dans les exemples précédents, le résultat suffit amplement pour savoir si la fonction a été exécutée ou non. Mais dans certains cas, une fonction est exécutée pour faire un traitement qui n'est pas forcément visible ou affiché et dans ce cas on utilise des valeurs de retour diverses tel que le 1 pour signaler le bon déroulement de la fonction, ou le 0 en cas d'échec.

Il existe aussi une autre variable utilisée couramment : @error
Cette variable est initialisée à zéro à chaque 'entrée' dans une fonction, donc il suffit de lui donner une valeur pour pouvoir l'exploiter en dehors de la fonction.
Ceci dit, @error étant une variable spéciale (que l'on appelle Macro dans le jargon AutoIt), on ne peut lui attribuer une valeur qu'en utilisant la fonction SetError.

Paramètre(s) optionnel(s) d'une fonction

Maintenant que nous avons vu l'utilisation d'un paramètre, nous allons voir comment rendre ce paramètre optionnel.
Pour qu'un paramètre soit optionnel, il faut plusieurs conditions :

  • Il doit être 'prédéfini' dans la déclaration de la fonction.
  • Il ne doit pas précéder un paramètre obligatoire sous peine de provoquer une erreur lors de l'exécution du script.


Voici notre fonction Ma_Fonction avec le paramètre $Param réglé pour être optionnel :

Func Ma_Fonction($Param = "Hello World")
	MsgBox(0, "", $Param)
EndFunc


Si vous appelez la fonction comme ceci :

Ma_Fonction("Bonjour tout le monde")

alors, c'est le texte "Bonjour tout le monde" qui sera affiché.


Si vous appelez la fonction sans paramètre :

Ma_Fonction()

alors, c'est le texte "Hello World" qui sera affiché.


Attention :

Si vous appelez une fonction sans paramètre(s), alors que celle-ci est définie pour en recevoir,
alors vous aurez lors de l'exécution du code, un message d'erreur de paramètre manquant.


Combien de paramètres a reçu ma fonction ?

Si vous avez besoin de connaitre le nombre de paramètres envoyés à votre fonction, vous pouvez utiliser la variable @NumParams.


Ma_Fonction("Paramètre 1", "Paramètre 2")

Func Ma_Fonction($Param1 = "Val 1", $Param2 = "Val 2")
	MsgBox(0, "", @NumParams)
EndFunc

L'exécution de cette fonction affichera 2, qui est bien le nombre de paramètres envoyés à la fonction.


Utilisation des mots clé Default, ByRef et Const

Default

  • Dans certaines circonstances nous avons besoin d'utiliser des fonctions avec plusieurs paramètres. Certains de ces paramètres ont des valeurs par défaut et si vous ne souhaitez pas ressaisir ces valeurs utilisez le mot clé : Default


Dans la fonction ci dessous, nous utilisons le mot clé Default en premier paramètre afin de ne pas modifier la valeur de celui-ci, puis nous donnons une valeur spécifique au deuxième paramètre qui sera utilisé au lieu de la valeur définie dans la fonction.


Ma_Fonction(Default, "Is in English")

Func Ma_Fonction($Param1 = Default, $Param2 = Default)
	If $Param1 = Default Then $Param1 = "Hello World"
	If $Param2 = Default Then $Param2 = "Bonjour tout le monde"
	MsgBox(0, "", $Param1 & @CRLF & $Param2)
EndFunc


Const

  • Une erreur que l'on retrouve fréquemment dans la création de fonction, c'est la modification de la valeur entrée en paramètre pour effectuer un traitement. Malheureusement, une fois celle-ci redéfinie dans la fonction, il est impossible de retrouver sa valeur d'origine.


Afin d'éviter cette erreur, nous vous conseillons l'utilisation du mot clé Const. Celui-ci protège la variable de paramètre de toute modification non désirée.


Func Ma_Fonction(Const $Param1)
	; Mon traitement
EndFunc


ByRef

  • Pour finir cette partie, nous pouvons aussi utiliser le mot clé ByRef. Ce mot clé implique deux choses :
    • Le paramètre qui lui est affecté est une variable non optionnelle et en aucun cas un texte littéral.
    • Un lien est créé entre la variable d'origine et la variable de la fonction.

Habituellement, la variable envoyée en paramètre est copiée dans la variable de la fonction. En utilisant ce mot clé, le paramètre est traité comme une référence à l'objet originel. Ceci est souvent utilisé lors du traitement de données importantes ou de tableaux.


Global $Tableau[6] = ["1", "2", "3", "4", "5"]
Ma_Fonction($Tableau)

Func Ma_Fonction(ByRef $Param1)
	; Mon traitement
EndFunc


L’inconvénient de passer un tableau comme ceci, c'est qu'il est très facile de perdre la totalité du tableau, par le simple fait de donner une valeur quelconque à la variable tableau à l'intérieur de la fonction.

Global $Tableau[6] = ["1", "2", "3", "4", "5"]
Ma_Fonction($Tableau)

Func Ma_Fonction(ByRef $Param1)
	$Tableau = 5  ; Ici nous perdons l'intégralité du tableau.
EndFunc


Afin de protéger celui-ci, nous combinerons l'utilisation des mots-clé ByRef et Const (peu importe le sens d'utilisation, du moment que ces mots précèdent la variable à protéger).

Global $Tableau[6] = ["1", "2", "3", "4", "5"]
Ma_Fonction($Tableau)

Func Ma_Fonction(Const ByRef $Param1)
	; Traitement sur les valeurs du tableau.
EndFunc

Dans le code ci-dessus, le tableau est protégé, mais il est quand même possible d'intervenir directement sur les valeurs qu'il contient.


Voici pour les bases sur les fonctions et leurs paramètres.
Certains aspects tels que l'utilisation complexe des retours et les UDFs sont volontairement omis, afin de ne pas alourdir ce tutoriel.

Portée d'une variable dans une fonction

Nous allons voir dans les quelques lignes qui suivent, ce qu'est la portée d'une variable et ses implications. Commençons par un code simple, qui fait appel à quelques notions de base, que nous venons de voir précédemment.


Exemple :

$Var1 = "Bonjour tout le monde"
Ma_Fonction("Hello World")
MsgBox(0, "", $Var1)


Func Ma_Fonction($Param)
	$Var1 = $Param
EndFunc

On constate dans ce code que la valeur passée en paramètre de la fonction Ma_Fonction() vient écraser la valeur de la variable $Var1, et donc ce n'est pas le texte en Français qui s'affiche, mais celui en Anglais.
Donc prudence lorsque vous utilisez des noms de variables dans une fonction.


Pour éviter cet effet qui peut devenir gênant, utilisez le mot clé Local devant la variable, afin de la définir localement et de limiter sa portée à l'intérieur de la fonction.

Exemple :

$Var1 = "Bonjour tout le monde"
Ma_Fonction("Hello World")
MsgBox(0, "", $Var1)


Func Ma_Fonction($Param)
	Local $Var1 = $Param
EndFunc

Cette fois-ci, c'est bien le texte en Français qui s'affiche, car la variable $Var1 n'a pas été écrasée, alors qu'elle a quand même été 'redéfinie' dans la fonction.


  • Il est à noter :
- Une variable locale ne peut être utilisée que dans la fonction ou elle a été déclarée et ne
peut intervenir sur une autre variable de même nom déclarée ou utilisée ailleurs dans le code.

- Bien qu'il soit possible de déclarer une variable globale dans une fonction, il est de bonne
pratique d'effectuer cette déclaration en début de code et à l'extérieur de toute fonction.
Sans quoi, vous risquez d'obtenir le message d'erreur suivant lors de la compilation :
'WARNING: $Var: possibly used before declaration'


Conclusion :
Dans vos fonctions, déclarez toujours vos variables localement en les précédant du mot clé Local (sauf si vous voulez intervenir sur une variable globale déclarée ou non avec le mot clé Global à l'extérieur de toute fonction.


Qu'est-ce qu'un flag et comment l'utiliser ?

Définition généralement trouvée sur internet :
En informatique, un flag ou encore drapeau est une valeur binaire (de type vrai ou faux) indiquant le résultat d'une opération ou le statut d'un objet.


Mais, attention, car dans AutoIt, il existe trois types de flags différents.


Utilisation d'un flag simple tel que 0 ou 1 (flag booléen)

Afin d'activer ou de désactiver une option, il est souvent fait appel à un paramètre particulier, du nom de flag. Dans le cas présenté ci-dessous, il est de type booléen. En logique et en programmation informatique, c'est un type de variable à deux états. Les variables de ce type sont soit à l'état True (1), soit à l'état False (0). En Français Vrai ou Faux.


Voici un exemple de fonction, utilisant un flag booléen :

Ma_Fonction(1)

Func Ma_Fonction($Flag)
	If $Flag = 0 Then MsgBox(0, "", "Hello World")
	If $Flag = 1 Then MsgBox(0, "", "Bonjour tout le monde")
EndFunc

Cette fonction permet de choisir si on veut afficher le texte en Anglais (Flag = 0) ou en Français (Flag = 1).
Les valeurs 0 ou 1 peuvent être remplacées par les mots clé True ou False.


Exemple d'utilisation du booléen :

Ma_Fonction(True)



Attention aussi de prendre en compte l'envoi de paramètres non désirés (ce qui n'est pas le cas ci-dessus).



Afin de parfaire notre fonction, nous allons rendre le flag optionnel et prendre en compte une éventuelle erreur d'entrée de paramètre (autre que 0 ou 1) :

Ma_Fonction()

Func Ma_Fonction($Flag = 1)
	If $Flag = 0 Then
		MsgBox(0, "", "Hello World")
	ElseIf $Flag = 1 Then
		MsgBox(0, "", "Bonjour tout le monde")
	Else
		MsgBox(0, "", "Parameter Error / Erreur de paramètre")
	EndIf
EndFunc


Voilà pour la présentation d'un flag booléen. Ceci dit, il est des cas ou deux valeurs ne suffisent pas car une troisième voire plusieurs autres valeurs seraient nécessaires au paramétrage de l'option. Nous devons donc utiliser des valeurs numériques plus grandes que 0 et 1.

Utilisation d'un flag à plus de deux valeurs (flag décimal)

Dans cette partie, vous allons voir une autre possibilité de l'utilisation d'un flag, mais qui cette fois-ci ne sera pas booléen, mais plutôt décimal.

Lorsque deux valeurs ne suffisent pas au paramétrage d'une option, il est courant de voir l'utilisation de valeurs supplémentaires et de se retrouver avec des valeurs de flag comme le 2, le 3, etc ...
Il est aussi courant de voir l'utilisation de valeur(s) négative(s).


Voici un exemple de code simple, exploitant ce type de flag :

Ma_Fonction(3)

Func Ma_Fonction($Flag = 1)
	Switch $Flag
		Case 0
			MsgBox(0, "", "Hello World")

		Case 1
			MsgBox(0, "", "Bonjour le monde")

		Case 2
			MsgBox(0, "", "Guten Tag die Welt")

		Case 3
			MsgBox(0, "", "Buenos días el mundo")

		Case Else
			MsgBox(0, "", "Parameter Error")

	EndSwitch
EndFunc

Dans cet exemple, nous utilisons une fonction de sélection de cas, car au-delà de quelques valeurs à tester, les conditions If/ElseIf/Else peuvent paraitre lourdes. Dans l'exemple ci-dessus, Switch $Flag permet à la fonction de choisir le cas le plus approprié en fonction de la valeur du paramètre de la variable $Flag.

Cette fonction peut recevoir quatre paramètres différents :
0 pour afficher le message en Anglais, 1 pour le Français, 2 pour l'Allemand et 3 pour l'Espagnol.



Il est à noter, que jusqu'à présent, le type de flag utilisé (Booléen ou binaire) est unique et ne peut représenter qu'une seule valeur à la fois. Ceci dit, il est des cas ou dans une fonction, nous avons besoin de passer de nombreux paramètres et l'utilisation d'une fonction avec 10 ou 20 paramètres deviendrait totalement invraisemblable.

Nous allons voir dans le chapitre suivant, comment contourner ce problème et comment envoyer plusieurs valeurs de plusieurs paramètres par un seul flag.


Utilisation d'un flag à multiples valeurs (flag binaire ou hexadécimal)

Nous avons vu précédemment comment envoyer à une fonction une valeur par le biais d'un paramètre appelé flag. Pour l'instant, cette valeur est unique et ne permet l'utilisation que d'un seul paramètre simultanément.


Il est des cas, en programmation, où il est nécessaire de passer à la fonction une multitude de valeurs afin de régler un certains nombre de paramètres.
Imaginez devoir passer 10 ou 20 paramètres à votre fonction. Rien qu'à l'écriture de celle-ci, le code deviendrait vite lourd et difficile à manipuler ou à comprendre.

Func Ma_Fonction($Param1, $Param2, $Param3, $Param4, $Param5, $Param6, $Param7, $Param8, $Param9, $Param10)
	; Traitement
EndFunc

Afin de résoudre ce problème, il suffit d'envoyer par le même flag une certaine quantité de paramètres.



Mais, comment cela est-il possible !!!


Hé bien, tout simplement en additionnant ces paramètres et en utilisant la logique binaire !
La logique binaire peut paraitre compliquée de prime abord, mais en réalité elle est bien plus simple qu'on ne peut le penser, car elle fait appel à une logique intrinsèque et ne fait intervenir que des suites de 0 et de 1.


Dans le cas qui nous intéresse, l'utilisation de la logique binaire permet d'utiliser la représentation binaire d'un nombre et de l'utiliser comme autant de paramètres possibles.


Principe de base sur le binaire

Petite explication ultra-simplifiée :
Généralement, la représentation binaire d'un nombre se fait sur 4 ou 8 chiffres binaires (de type 0 ou 1) que l'on appelle des bits. La représentation binaire sur 8 bits est appelée un octet.


Si vous souhaitez en connaitre plus sur les bits, les octets, les bytes, etc ..., je vous conseille la consultation de [cet article] sur Wikipédia.


Voyons à quoi ressemble le codage binaire classique des nombres de 0 à 5 :

codage binaire 4 bits codage binaire 8 bits
0 0000 0 00000000
1 0001 1 00000001
2 0010 2 00000010
3 0011 3 00000011
4 0100 4 00000100
5 0101 5 00000101


Si vous observez bien ce tableau, vous constaterez que pour chaque valeur décimale, il y a une représentation binaire qui est une combinaison unique des bits qui la compose. Si l'on considère que chaque bit peut servir de flag booléen (puisque chaque bit peut avoir pour valeur 0 ou 1), alors sur un codage de 4 bits, nous pouvons gérer 4 paramètres simultanément.


Principe des flags binaire dans AutoIt

Il faut retenir deux choses essentielles dans l'utilisation du codage binaire dans AutoIt :

  • La valeur True de chaque paramètre est généralement exprimée en nombre décimal puissance de deux 2 (0, 2, 4, 8, 16, 32, 64, 128, 256, etc ...). Voir les explications ci-dessous.


  • Parfois, au lieu d'utiliser la représentation binaire, c'est la représentation hexadécimale qui est utilisée mais sur le même principe que la représentation binaire. Voir les explications ci-dessous.


Pourquoi utiliser un nombre décimal puissance de 2 ?
Tout simplement, parce que sa représentation binaire se compose d'un ensemble de bits à 0 et d'un seul bit à 1.

Valeur décimale codage binaire 8 bits Valeur hexadécimale
0 00000000 0x0
1 00000001 0x1
2 00000010 0x2
4 00000100 0x4
8 00001000 0x8
16 00010000 0x10
32 00100000 0x20
64 01000000 0x30
128 10000000 0x40

Représentez-vous cela comme une suite d'interrupteurs (8 dans le tableau ci-dessus) qui commandent chacun un paramètre booléen.

L'avantage d'une telle utilisation, c'est que les valeurs peuvent être additionnées facilement afin de gérer plusieurs paramètres simultanément, la valeur de résultat de cette addition étant unique et jamais déjà présente dans le tableau. Mais comme l'utilisation de nombres binaires serait relativement peu conviviale, on utilise donc leurs valeurs décimales.
Par exemple, en utilisant le tableau ci-dessus, si je veux activer le premier et le dernier paramètre, il me suffit d'additionner 128 et 1, ce qui nous donne une valeur décimale de 129 dont la représentation binaire vaut bien 10000001 (le premier et le dernier bit sont à 1, alors que les autres sont à 0).


Attention :
Tout comme nous l'avons vu dans le chapitre 'Utilisation d'un flag à plus de deux valeurs (flag décimal)', lorsque l'utilisation d'un booléen (deux valeurs, 0 et 1) ne suffit plus car le paramètre doit utiliser plus de 2 valeurs, alors AutoIt utilise la représentation hexadécimale sur le même principe que le binaire.
En effet, la représentation binaire limite chaque flag à une valeur booléenne, alors que la représentation hexadécimale permet jusqu'à 16 valeurs par flag (de 0 à F) !!!


Cas concret d'utilisation d'un flag avec la fonction MsgBox()

Nous allons voir ci-dessous comment AutoIt utilise son système de flag le plus complexe, car il est fait ici un mélange d'utilisation de nombres 'décimaux' de 1 à 6 et de puissances de deux.
Si vous comprenez cette partie, alors vous maîtriserez les cas plus simples (booléen, numérique et binaire sous forme de puissance de 2).


Une des fonctions internes à AutoIt qui utilise ce système est MsgBox.


Voici le paramétrage de la fonction :

MsgBox ( $flag, "title", "text" [, $timeout [, hwnd]] )

Nous n'allons pas ici détailler l'ensemble des paramètres de la fonction, mais plutôt nous concentrer sur celui qui nous intéresse, c'est à dire le premier paramètre : $flag


Ci-dessous, une reproduction du tableau des valeurs du paramètre flag de la fonction MsgBox :

Valeur décimale Résultat Concernant le bouton Valeur hexadécimale
0 Bouton OK 0x0
1 OK et Annuler 0x1
2 Abandonner, Recommencer, et Ignorer 0x2
3 Oui, Non, et Annuler 0x3
4 Oui et Non 0x4
5 Recommencer et Annuler 0x5
6 Annuler, Réessayer, Continuer 0x6
Valeur décimale Résultat lié à l'icône Valeur hexadécimale
0 Pas d'icône 0x0
16 Icône signe-stop 0x10
32 Icône point d'interrogation 0x20
48 Icône point d'exclamation 0x30
64 Icône signe d'information qui est constitué d'un 'i' dans un cercle 0x40
Valeur décimale Résultat du bouton par défaut Valeur hexadécimale
0 Le premier bouton est le bouton par défaut 0x0
256 Le deuxième bouton est le bouton par défaut 0x100
512 Le troisième bouton est le bouton par défaut 0x200
Valeur décimale Résultat Concernant la modalité Valeur hexadécimale
0 Application 0x0
4096 Système modal (la boîte de dialogue a une icône) 0x1000
8192 Tâche modale 0x2000
Valeur décimale Divers résultats liés Valeur hexadécimale
0 rien de spécial 0x0
262144 MsgBox a le premier plan 0x40000
524288 Le titre et le texte sont justifiés à droite 0x80000


Observez comment est utilisé le principe du système de flag numérique pour chacune des options.
Dans le cas présent, AutoIt utilise 5 options regroupées dans le même flag.

1 - L'option du type de bouton (les unités 0x1)
2 - L'option du type d'icône (les dizaines 0x10)
3 - L'option du bouton par défaut (les centaines 0x100)
4 - L'option du type de modalité (les milliers 0x1000)
5 - Quelques options supplémentaires (les dizaines de milliers 0x10000)

La combinaison de chaque option étant unique, cela permet de paramétrer plusieurs options simultanément.


En reprenant le tableau ci-dessus, nous allons combiner diverses options afin d'obtenir une boite de dialogue personnalisée :
Tout d'abord, nous voulons une boite de dialogue avec les boutons Oui et Non (option 0x4) avec l'icône indiquant une question (0x20), puis avec le deuxième bouton (Non), comme bouton par défaut (option 0x100) et enfin, nous voulons que cette boite de dialogue reste par dessus toutes les autres fenêtres et soit donc au premier plan (option 0x40000).


Additionnons ces valeurs : 0x4 + 0x20 + 0x100 + 0x40000 = 0x40124
Si nous prenons cette valeur hexadécimale, nous constatons bien que le dernier bit à la valeur 4 unités (boutons Oui et Non), l'avant dernier, la valeur 2 dizaines (Icône point d'interrogation), l'avant avant dernier la valeur 1 centaine (Le deuxième bouton est le bouton par défaut), etc ...


Bien que AutoIt soit prévu pour utiliser une telle 'numérotation' d'options, la méthode décimale est plus largement utilisée, car elle est plus conviviale.
Pour cela, on remplace tout simplement chaque valeur hexadécimale par sa correspondance décimale.
Nous nous retrouvons donc avec une addition de ce type : 4 + 32 + 256 + 262144
En règle générale, on ne calcule pas la valeur finale, mais on écrit directement l'addition en tant que paramètre.


Voici comment utiliser l'appel de la fonction MsgBox avec les options que nous venons de déterminer :

Mode hexadécimal :

MsgBox(0x4 + 0x20 + 0x100 + 0x40000, "Exemple", "Avez-vous compris comment utiliser le système des flags ?")
;ou
MsgBox(0x40124, "Exemple", "Avez-vous compris comment utiliser le système des flags ?")


Mode décimal :

MsgBox(4 + 32 + 256 + 262144, "Exemple", "Avez-vous compris comment utiliser le système des flags ?")
;ou
MsgBox(262436, "Exemple", "Avez-vous compris comment utiliser le système des flags ?")


Voilà. Libre à vous d'utiliser la numérotation que vous voulez. Gardez seulement à l'esprit que chaque valeur correspond à une option et que différentes options peuvent être combinées par la simple addition de leur représentation numérique (basée sur le principe d'un codage binaire ou d'un codage hexadécimal).


Cas concret d'utilisation d'un flag avec la fonction GuiCreate()

Puisque nous venons de voir le cas le plus avancé de traitement sur des flags, Je vais présenter ci-dessous un cas plus simple, mais oh combien utilisé.


Dans AutoIt, il est fréquent de créer une interface graphique pour y mettre différents contrôles tel que des boutons ou des champs de saisie. Pour ce faire, nous utilisons une fonction spécifique dont voici la syntaxe :

GUICreate ( "title" [, width [, height [, left [, top [, style [, exStyle [, parent]]]]]]] )

Une bien belle fonction avec pas mal de paramètres, n'est-ce pas ?!


Je pense que les paramètres title, width , height, left, top qui veulent respectivement dire titre, largeur, hauteur, gauche et haut n'ont pas besoin d'explications. Mis à part le paramètre parent (dont nous ne parlerons pas ici car ce n'est pas le sujet), il nous reste les paramètres :

  • style
  • exStyle

Ces deux paramètres permettent de choisir les styles communs et les styles étendus de votre fenêtre, afin d'en changer l'aspec. Comme vous pouvez le constater sur ce lien, le nombre des options de chaque paramètre est plutôt impressionnant !


Cette fois-ci, difficile de réfléchir avec des nombres (hexadécimaux ou puissance de 2), car vu le nombre de choix, cela deviendrait trop vite compliqué. Pour simplifier la tâche, chaque valeur à été affectée à une variable dont le nom est évocateur. Pour que vous vous en rendiez compte, éditez par exemple le fichier :

C:\Program Files\AutoIt3\Include\WindowsConstants.au3

A chaque fois que vous rajoutez la ligne
#Include <WindowsConstants.au3>
au début de votre code, toutes ces variables feront partie intégrante de celui-ci.


Voyons maintenant à quoi cela va nous servir, en créant une fenêtre (GUI) simple, de 200x200 pixels :

#include <WindowsConstants.au3> ; Le fichier des variables

GUICreate("Ma GUI", 200, 200, -1, -1) ; La fenêtre GUI

GUISetState(@SW_SHOW) ; Affiche la GUI

; Boucle d'attente de fermeture de la GUI.
Do
$msg = GUIGetMsg()
Until $msg = -3

Si vous lancez ce code, vous verrez une magnifique fenêtre graphique toute bête.

L'utilisation des nombres -1 ne sert que pour centrer la fenêtre sur l'écran, et correspond
à l'option par défaut de ces deux paramètres (voir documentation de la fonction).


Ceci étant fait, jouons maintenant avec le paramètre style.
Avez vous remarqué que la fenêtre précédemment crée, ne peut pas être redimensionnée ?
Dans la liste des styles communs, il existe le paramètre $WS_SIZEBOX, qui d'après ce qui est écrit, permet de rendre la fenêtre redimensionnable. Essayons le :

#include <WindowsConstants.au3>

GUICreate("Ma GUI", 200, 200, -1, -1, $WS_SIZEBOX) ; on ajoute le style $WS_SIZEBOX

GUISetState(@SW_SHOW)

Do
$msg = GUIGetMsg()
Until $msg = -3

Cool, ça marche au poil, mais bizarrement, les contrôles de réduction et d’agrandissement de la fenêtre ont disparut !!!


L'explication est toute simple et elle est indiquée dans la documentation de la fonction GuiCreate :

le style par défaut qui inclu une combinaison des styles 
$WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP et $WS_SYSMENU.
Certains styles sont toujours inclus :
$WS_CLIPSIBLINGS et $WS_SYSMENU si $WS_MAXIMIZEBOX ou $WS_SIZEBOX sont spécifiés.

Donc en ne mettant que $WS_SIZEBOX, seul les styles $WS_CLIPSIBLINGS et $WS_SYSMENU sont conservés et combinés avec $WS_SIZEBOX.
Il nous manque donc les styles $WS_MAXIMIZEBOX et $WS_MINIMIZEBOX.

Pas de problème, appliquons la méthode d'addition que nous avons déjà vu dans les chapitres précédemments :

#include <WindowsConstants.au3>

GUICreate("Ma GUI", 200, 200, -1, -1, $WS_SIZEBOX + $WS_MAXIMIZEBOX + $WS_MINIMIZEBOX)

GUISetState(@SW_SHOW)

Do
$msg = GUIGetMsg()
Until $msg = -3

Et voilà, nous avons bien une fenêtre que l'on peut redimensionner et dont les boutons de réduction et d'agrandissement sont bien présent.
Ceci dit, il aurait été plus simple de reprendre le style par défaut ($GUI_SS_DEFAULT_GUI) et d'y ajouter le style $WS_SIZEBOX.


Petite note finale à cette partie :
Sans revenir et reprendre la logique booléenne, il est à noter qu'il est aussi possible d'écrire l'addition des paramètres comme ceci :

GUICreate("Ma GUI", 200, 200, -1, -1, BitOr($WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX)

Je vous laisse le soin d'en apprendre plus sur la fonction BitOr et le OU logique en cliquant sur leur lien respectif. ^^


Lecture d'un flag binaire ou hexadécimal

Nous avons vu dans les chapitres précédents, comment coder diverses options dans un seul paramètre, que l'on appelle flag. Mais pour l'instant, ce flag était utilisé pour l'envoi de paramètre(s) dans une fonction existante.


Comment faire pour reproduire ce comportement et 'décoder' ces différentes options à partir de ce flag ?


En réalité cela est aussi simple que la combinaison de plusieurs valeurs en un seul flag.
Pour cela, nous allons tout simplement utiliser une fonction logique intégrée à AutoIt : la fonction BitAnd.


Principe du ET logique

Nous n'allons pas ici faire un cours complet sur la logique binaire. Mais afin d’appréhender au mieux l'utilisation de la fonction BitAnd, il est intéressant d'avoir quelques bases sur l'opérateur logique ET.


Si ce qui suit ne vous suffit pas, je vous conseille de lire les articles suivant sur l’encyclopédie Wikipédia :
Algèbre de Boole (Article Conjonction)
Fonction logique ET
Représentation graphique des fonctions logiques


La fonction ET (AND en Anglais) est un opérateur logique (de l'algèbre de Boole) qui compare deux valeurs logiques (opérandes) de valeur Vrai ou Faux (0 ou 1) et retourne un résultat Vrai (1) seulement si les deux valeurs logiques (opérandes) ont la valeur Vrai.


Afin d'illustrer l'opérateur logique ET, voici ce que l'on appelle sa table de vérité :

Opérandes Résultat
A B A ET B
0 0 0
0 1 0
1 0 0
1 1 1


Opération logique ET entre deux représentations binaires

Fort des connaissances acquises précédemment sur l'opérateur logique ET, voyons comment nous allons pouvoir l'utiliser.


Prenons par exemple, la représentation binaire sur 4 bits du nombre 4 : 0100
Si j'effectue une opération ET logique entre cette représentation et elle même, voici ce que j'obtiens :

Opération logique ET entre A et B
A = 4 0 1 0 0
B = 4 0 1 0 0
Résultat = 0 1 0 0

Nous constatons que le résultat est égal à l'opérande lui-même.


Voyons maintenant ce que nous pouvons faire de mieux ...
Cette fois-ci, nous allons toujours utiliser la représentation binaire sur 4 bit du nombre 4, mais nous allons aussi utiliser la représentation binaire sur 4 bit du nombre 6 !!! (ceci n'est pas fortuit et nous servira dans la suite de cette explication).

Si je fais une opération logique ET entre ces deux représentations, voici ce que j'obtiens :

Opération logique ET entre A et B
A = 6 0 1 1 0
B = 4 0 1 0 0
Résultat = 0 1 0 0

Nous constatons, que le résultat est égal à 0100, soit 4 en décimal !!!

Mais qu'est-ce que cela signifie ...
Hé bien dans le cas présent, cela signifie que le deuxième bit en partant de la gauche est commun aux deux opérandes.


Champ d'application binaire

Nous venons de voir précédemment qu'il est possible avec l'opération logique ET de connaitre l'état des bits d'une représentation binaire d'un nombre.


Mais comment cela va t-il nous servir pour 'décoder' un flag de valeur binaire !
Vous vous souvenez, que dans la partie Cas concret d'utilisation d'un flag hexadécimal nous avons vu comment combiner des valeurs hexadécimales afin d'utiliser un flag à multiples options.
Faisons la même chose, mais cette fois-ci avec des représentations binaires de nombres.
Vous vous souvenez aussi que dans AutoIt, on utilise comme paramètres des nombres décimaux de puissance de deux (2, 4, 8, 16, 32, etc ...), car leur représentation binaire ne contient qu'un seul bit à 1.
Prenons par exemple les nombres 2 (0010 en binaire), 4 (0100 en binaire) et 8 (1000 en binaire), qui pourraient être les paramètres d'une fonction.

Faisons l'addition de leur représentation binaire :

0010 + 0100 + 1000 = 1110

Puisque chaque bit de cette représentation binaire correspond à un paramètre :
En partant de la gauche, le premier bit correspond aux milliers et donc au paramètre du nombre 8 (1000), le deuxième correspond aux centaines et donc au paramètre du nombre 4 (0100), le troisième correspond aux dizaines et donc au paramètre du nombre 2 (0010) et le quatrième aux unités et donc au nombre 1, nous avons donc dans la représentation binaire de l'addition de nos trois nombres (1110) :

Le paramètre du nombre 8 est à 1 (True)
Le paramètre du nombre 4 est à 1 (True)
Le paramètre du nombre 2 est à 1 (True)
Le paramètre du nombre 1 est à 0 (False)

Utilisons maintenant l'opérateur logique ET pour tester un des paramètres. Pour cela faisons un ET logique entre l'addition des trois nombres (1110) et par exemple la représentation binaire du paramètre du nombre 2 (0010) :

Opération logique ET entre A et B
A = 1110 1 1 1 0
B = 0010 0 0 1 0
Résultat = 0 0 1 0

Nous constatons que le résultat est égal à 0010, soit 2 en décimal !!!
Cela signifie donc que le paramètre du nombre 2 est bien à True. ^^


Champ d'application dans AutoIt

Reprenons l'exemple que nous avons utilisé avec la fonction MsgBox dans ce chapitre :

MsgBox(0x40124, "Exemple", "Avez-vous compris comment utiliser le système des flags ?")
; ou en décimal
MsgBox(262436, "Exemple", "Avez-vous compris comment utiliser le système des flags ?")

Nous allons tester le flag, pour voir si le paramètre de l'icône et bien celui de l'icône point d'interrogation. Dans les options de la fonction, ce paramètre est réglé en utilisant la valeur décimale 32 ou la valeur hexadécimale 0x20.


Voyons tout cela du coté binaire :
Si nous convertissons la valeur hexadécimale 0x40124 ou la valeur décimale 262436 en binaire (demandez à Google, il vous le fera !), nous obtenons bien la même représentation binaire : 1000000000100100100

Si nous faisons la même chose avec 0x20 ou 32, nous obtenons : 100000


Maintenant, faisons un ET logique entre ces deux valeurs :

Opération logique ET entre A et B
A 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0
B 1 0 0 0 0 0
Résultat = 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0

Nous obtenons bien la représentation binaire de 0x20 ou 32 !
Donc notre valeur B est bien présente dans la valeur A, ce qui implique que notre option 0x20 est bien présente dans le flag de valeur 0x40124 ...


Le binaire c'est bien, mais pas très pratique à écrire en AutoIt (ou dans un autre langage), alors faisons le test avec du code AutoIt et utilisons enfin la fonction BitAnd citée dans l'un des chapitres précédents :


En hexadécimal :

Msgbox(0, "", BitAnd(0x40124, 0x20))


Et en décimal :

Msgbox(0, "", BitAnd(262436, 32))


Le résultat des deux lignes de code affichera la même valeur : 32
On peut donc en conclure que la valeur de l'option 32 est bien présente dans la valeur du flag 262436 et donc que l'option est bien activée.


Voilà, vous savez maintenant utiliser AutoIt pour faire un ET logique entre deux valeurs hexadécimales ou décimales afin de tester les options d'un flag.
Bien qu'il soit possible dans AutoIt d'utiliser la représentation binaire ou hexadécimale d'un nombre pour gérer des flags, il est de bonne pratique d'utiliser sa représentation décimale, sous forme de puissance de deux (2, 4, 8, 16, 32, 64, 128, 256, etc ...).


Exemple d'utilisation

Nous avons vu le chapitre Utilisation d'un flag à plus de deux valeurs (flag décimal), comment créer une fonction à plusieurs valeurs.
Utilisons cette base pour créer une fonction avec plusieurs paramètres combinés.


Tout d'abord, déterminons les différentes options qui vont la composer :

  • La première option (optionnelle), sera la langue du message, et sera composée de 4 valeurs, dont une par défaut.
  • La deuxième option (optionnelle), sera l'affichage de l'icône de la boite de message, et sera composée aussi de quatre valeurs.
  • La troisième et dernière option (optionnelle) sera l'utilisation d'un signal (Beep) sonore avant l'affichage de la boite de message.


Prenons exemple sur la fonction MsgBox, et créons nos propres valeurs de paramètres :

Valeur décimale Langue du message Valeur hexadécimale
1 Anglais 0x1
2 Français 0x2
3 Allemand 0x3
4 Espagnol 0x4
Valeur décimale Icône à afficher Valeur hexadécimale
0 Pas d'icône 0x0
16 Icône signe-stop 0x10
32 Icône point d'interrogation 0x20
48 Icône point d'exclamation 0x30
64 Icône signe d'information qui est constitué d'un 'i' dans un cercle 0x40
Valeur décimale Beep sonore Valeur hexadécimale
0 Pas de beep 0x0
256 Beep sonore 0x100

En raisonnant sur les nombres hexadécimaux, nous avons :

L'option 1 pour la langue, qui utilise les unités (0x1) hexadécimales.
L'option 2 du type d'icône, qui utilise les dizaines (0x10) hexadécimales.
L'option 3 pour le signal sonore, qui utilise les centaines (0x100) hexadécimales.

Ce type de raisonnement, permet 9 possibilités par paramètre (voir 15 si utilisation des lettres hexadécimales A, B, C, D, E, F):

De 0x1 à 0x9 pour le premier (de 1 à 9 en décimal).
De 0x10 à 0x9 (de 16 à 144 en décimal puissance de 2)pour le second.
De 0x100 à 0x900 (de 256 à 2304 en décimal puissance de 2)pour le dernier.

Les valeurs de paramètre de l'affichage de l'icône sont volontairement identiques à ceux de la fonction MsgBox (on ne va pas refaire ce qui est déjà fait !!!).


Utilisons du code AutoIt pour faire nos déclarations de valeurs (il est plus facile d'interpréter un nom de variable plutôt qu'une valeur ($Francais est plus évocateur que la valeur 2 ou 0x2 !):

$Anglais	= 0x1	; 1 en décimal   (00000001)
$Francais	= 0x2	; 2 en décimal   (00000010)
$Allemand	= 0x3	; 3 en décimal   (00000011)
$Espagnol	= 0x4	; 4 en décimal   (00000100)

$Icon1		= 0x10	; 16 en décimal  (00010000)
$Icon2		= 0x20	; 32 en décimal  (00100000)
$Icon3		= 0x30	; 48 en décimal  (00110000)
$Icon4		= 0x40	; 64 en décimal  (01000000)

$Beep		= 0x100	; 256 en décimal (10000000)

Nous reprenons bien le même principe de gestion des options :
Les Unités pour la langue, les dizaines pour l'icône et les centaines pour le beep.

Par la même occasion, vous constatez que chaque représentation binaire est unique et on pourrait l'associer à un système d'interrupteur qui permet d'avoir telle ou telle option par le simple fait d'activer les bits qui la composent en combinant chaque option.


Créons maintenant la structure de notre fonction, selon ce qui a été dit précédemment (c'est à dire que les options sont optionnelles, mais la langue est pré-déterminée) :

Func Ma_Fonction($Flag = 2)
     ; Traitement
EndFunc

Nous mettons le flag à 2 afin d'avoir le message en Français par défaut.


Bien, nous allons maintenant regrouper le tout et rajouter l'appel à la fonction, afin de tester ce que ça donne :

$Anglais	= 0x1	; 1
$Francais	= 0x2	; 2
$Allemand	= 0x3	; 3
$Espagnol	= 0x4	; 4
$Icon1		= 0x10	; 16
$Icon2		= 0x20	; 32
$Icon3		= 0x30	; 48
$Icon4		= 0x40	; 64
$Beep		= 0x100	; 256


Ma_Fonction()


Func Ma_Fonction($Flag = 2)
	; Traitement
EndFunc

Bon, pour l'instant cette fonction ne sert pas à grand chose, mais nous allons rajouter le traitement interne.


Afin de gérer plus facilement les résultats des différents traitements (langue, icône et beep), nous allons utiliser à l'intérieur de notre fonction des variables locales (temporaires).

Lorsque vous devez nommer une variable, il est de bonne pratique d'utiliser la méthode dite : Notation hongroise
Ceci dit, vous pouvez utiliser la méthode mnémotechnique qui vous convient le mieux.

Dans notre cas, je vais utiliser les noms $sText et $iIcon, pour respectivement le texte à afficher et le type d'icône à utiliser. En ce qui concerne le Beep, puisque le résultat sera oui ou non, je n'ai pas besoin de créer de variable.


Bien, entrons dans le vif du sujet.
Nous avons vu précédemment comment utiliser la fonction BitAnd pour tester les valeurs d'un flag. Hé bien allons y, et attribuons nos valeurs respectives aux variables de traitement, puis utilisons directement ces variables dans la fonction MsgBox.

$Anglais	= 0x1	; 1
$Francais	= 0x2	; 2
$Allemand	= 0x3	; 3
$Espagnol	= 0x4	; 4
$Icon1		= 0x10	; 16
$Icon2		= 0x20	; 32
$Icon3		= 0x30	; 48
$Icon4		= 0x40	; 64
$Beep		= 0x100	; 256


Ma_Fonction()


Func Ma_Fonction($Flag = 2)
	Local $sText, $iIcon

	If BitAND($Flag, 0x1) = 0x1 Then $sText = "Hello World"
	If BitAND($Flag, 0x2) = 0x2 Then $sText = "Bonjour le monde"
	If BitAND($Flag, 0x3) = 0x3 Then $sText = "Guten Tag die Welt"
	If BitAND($Flag, 0x4) = 0x4 Then $sText = "Buenos días el mundo"

	If BitAND($Flag, 0x10) = 0x10 Then $iIcon = 0x10
	If BitAND($Flag, 0x20) = 0x20 Then $iIcon = 0x20
	If BitAND($Flag, 0x30) = 0x30 Then $iIcon = 0x30
	If BitAND($Flag, 0x40) = 0x40 Then $iIcon = 0x40

	If BitAND($Flag, 0x100) = 0x100 Then Beep(500, 200)

	MsgBox($iIcon, "Ma_Fonction", $sText)
EndFunc

Voilà, notre fonction est prête et fonctionnelle. Si vous la lancez, vous verrez s'afficher le texte en Français.


Maintenant, pour jouer avec cette fonction, nous allons tester diverses valeurs.
Tout d'abord, essayons de mettre le texte en Anglais (0x1 soit 1 en décimal) et d'utiliser l'icône point d'interrogation (0x20 soit 32 en décimal).


Additionnons les valeurs :

1 + 32 = 33


Utilisons cette valeur 33 dans notre appel de fonction :

Ma_Fonction(33)


Nous avons bien une boite de dialogue avec l'icône point d'interrogation, ainsi que le texte en Anglais qui s'affiche.
Ceci dit, il n'est pas très pratique de faire à chaque fois l'addition, c'est pourquoi il est de pratique courante d'écrire directement l'addition en paramètre.


Essayons cela, en rajoutant le beep sonore :

Ma_Fonction(1 + 32 + 256)

Magnifique, cela fonctionne !!! Ceci dit, cette fonction n'est pas complètement terminée, car il est des cas ou elle ne fonctionnera pas, ou mal !!!


Par exemple :

Ma_Fonction(16)
; ou
Ma_Fonction(256)


En effet, nous avons déterminé toutes les valeurs, mais si l'une des valeurs de la langue n'est pas spécifiée, alors le texte n'est pas assigné.
Pour contourner ce problème, il suffit de modifier le traitement de la langue, pour que si l'option n'est pas définie dans le paramètre flag, alors on le détermine par défaut dans la fonction. Pour cela, nous allons utiliser le système conditionnel If/ElseIf/Else.
Nous n'allons pas nous occuper du paramètre $iIcon ni du beep, puisque ce sont des paramètres qui peuvent être omis.

Nous allons tester chaque condition (sauf celle par défaut) et si aucune n'est valable, alors nous déterminons la valeur par défaut :

$Anglais	= 0x1	; 1
$Francais	= 0x2	; 2
$Allemand	= 0x3	; 3
$Espagnol	= 0x4	; 4
$Icon1		= 0x10	; 16
$Icon2		= 0x20	; 32
$Icon3		= 0x30	; 48
$Icon4		= 0x40	; 64
$Beep		= 0x100	; 256


Ma_Fonction()


Func Ma_Fonction($Flag = 2)
	Local $sText, $iIcon

	If BitAND($Flag, 0x1) = 0x1 Then
		$sText = "Hello World"
	ElseIf BitAND($Flag, 0x3) = 0x3 Then
		$sText = "Guten Tag die Welt"
	ElseIf BitAND($Flag, 0x4) = 0x4 Then
		$sText = "Buenos días el mundo"
	Else
		$sText = "Bonjour le monde"
	EndIf

	If BitAND($Flag, 0x10) = 0x10 Then $iIcon = 0x10
	If BitAND($Flag, 0x20) = 0x20 Then $iIcon = 0x20
	If BitAND($Flag, 0x30) = 0x30 Then $iIcon = 0x30
	If BitAND($Flag, 0x40) = 0x40 Then $iIcon = 0x40

	If BitAND($Flag, 0x100) = 0x100 Then Beep(500, 200)

	MsgBox($iIcon, "Ma_Fonction", $sText)
EndFunc




Voilà, c'est la fin de ce tutoriel.
J'espère que vous avez eu plaisir à le lire et qu'il vous a apporté les réponses que vous attendiez. Je vous souhaite de bons codes et vous dis à bientôt pour d'autres tutoriels. ^^




Tutoriel basé sur le sujet Les flags (écrit par Iste) sur le forum AutoItScript.fr.