Nous allons à présent éclaircir quelques points concernant les procédures évènementielles.
Pour cela reprenons l'exemple du projet Addition. Lorsque vous double-cliquez pour la première fois sur le bouton d'addition, Lazarus génère automatiquement la déclaration de la procédure évènementielle associée à ce bouton dans l'unité du formulaire. Voici ce code:
Dans ce code, il y a deux choses que nous n'avons jamais expliqué: pourquoi le nom de la procédure est-il préfixé par TForm1. ?, que signifie le paramètre sender de type TObject ?
D'autre part, rappelez vous que lorsque vous voulez accéder à un composant de l'interface dans une procédure non évènementielle, il faut préfixer le nom du composant par Form1.. Dans une procédure évènementielle, ce n'est pas nécessaire. Pour quelle raison ?
Enfin, vous avez sans doute remarqué que les entêtes des procédures évènementielles sont automatiquement ajoutées à l'intérieur de la déclaration de la classe TForm1. Par exemple dans le projet Addition, le double-clic sur le bouton Additionner génère également le code suivant (en blanc):
On y retrouve donc l'entête de la procédure évènementielle. Pourquoi cela?
Les réponses à toutes ces questions se trouvent dans la programmation objet et plus précisemment, dans la manière dont la programmation objet est utilisée dans Lazarus pour représenter des interfaces graphiques. Reprenons chacune de ces questions.
Dans les entêtes des procédures évènementielles, le nom de la procédure est toujours préfixé par TForm1.. Pour quelle raison ?
Le préfixage des procédures évènementielle par TForm1 s'explique par le fait que les procédures évènementielles sont des méthodes de la classe TForm1. Or, lorsque l'on déclare une méthode en Lazarus, il faut obligatoirement préfixer le nom de la procédure par le nom de la classe (nous reviendrons là dessus plus en détails dans le deuxième cours de programmation objet).
Pour quelle raison les entêtes des procédures évènementielles apparaissent-elles à l'intérieur de la déclaration de la classe Tform1 ?
L'explication est encore une fois dans la manière de déclarer une méthode d'une classe: en pascal objet, les entêtes des méthodes d'une classe doivent forcément figurer à l'intérieur de la déclaration de la classe.
Dans une procédure non-évènementielle, les composants doivent être préfixés par Form1., mais ce n'est pas nécessaire dans une procédure évènementielle. Pour quelle raison ?
Rappelons nous que les procédures évènementielles sont des méthodes de la classe TForm1 et que les composants sont des attributs de cette classe.
Or, à l'intérieur d'une méthode d'une certaine classe , un nom d'attribut de cette classe désigne implicitement l'attribut de l'objet auquel il sera appliqué au moment de son exécution.
Comme les procédures évènementielles sont des méthodes de la classe TForm1, que les composants sont des attributs de cette classe et que les procédures évènementielles sont forcément appliquées à l'objet Form1 de cette classe, tout nom de composant apparaissant à l'intérieur d'une procédure évènementielle est automatiquement interprèté comme un attribut de l'objet Form1. A l'intérieur d'une procédure évènementielle, le préfixage des composants par Form1. est donc inutile.
Par exemple, à l'intérieur de la procédure évènementielle Button1Click du projet Addition, Edit1 désigne implicitement la zone de texte Edit1 de l'objet Form1, car Edit1 est un attribut de la classe TForm1.
D'un autre coté, dans une procédure non évènementielle le préfixage des composants est obligatoire car, tout simplement, les procédures non-évènementielles ne sont pas des méthodes de la classe TForm1 (à moins, bien sur de les déclarer en tant que telles).
Dans l'entête d'une procédure évènementielle figure toujours un mystérieux paramètre de type TObject nommé Sender. Que représente ce paramètre ?
Le paramètre sender contient l'adresse du composant qui a déclenché l'évènement. Par exemple, dans la procédure Button1Click:
Sender contient l'adresse de l'objet Button1.
On peut se demander quel est l'intéret de ceci, étant donné que l'on peut tout simplement accéder à cet objet en utilisant son nom.
En fait, l'utilité du paramètre Sender apparait lorsque l'on cherche à réutiliser la même procédure évènementielle pour plusieurs composants de l'interface.
Il est en effet possible, via l'inspecteur d'objet d'associer la même procédure évènementielles à plusieurs composants. Ces composants peuvent même être de types différents ! (d'où l'intéret de déclarer Sender comme un objet de la classe TObject).
Pour vous en convaincre, ouvrez ProjetSender dans le dossier exemple. Le formulaire contient un bouton et une case à cocher. Ces deux composants sont associés à la même procédure évènementielle qui affiche le nom du composant sur lequel l'utilisateur a cliqué.
Le code de la procédure évènementielle utilisé par les deux composants est le suivant:
procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage ('Vous avez cliqué sur le composant ' +(Sender As TComponent).Name); end;
Ce code utilise le polymorphisme, une notion de programmation objet sur laquelle nous reviendrons dans le cours suivant.