lundi 31 mars 2008

Actionner les événements les plus courants

1.1. Mettre en œuvre des actions sur les évènements les plus courants :

Dans le code, on peut créer soi-même de toutes pièces, des contrôles et leurs évènements.

1.1.1. Créer par code des contrôles


Dans le code d'une procédure, il est possible de créer de toute pièce un contrôle, mais attention, il faut tout faire!!

Créons le bouton.

Dim Button1 As New Button


Modifions ses propriétés
Me.Button1.Location = New System.Drawing.Point(56, 144)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(104, 24)
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"

Le bouton existe mais il faut l'ajouter à la collection Controls de la fenêtre (Cette collection contient tous les contrôles contenus dans la fenêtre):

Me.Controls.Add(Button1)


1.1.2. Ajouter des évènements.

Le bouton existe mais pour le moment, il ne gère pas les évènements.
Il faut inscrire le bouton dans une méthode de gestion d'évènements. En d'autres termes, Vb doit savoir quelle procédure évènement doit être déclenchée quand un évènement survient. Pour cela, il y a 2 méthodes:
Déclarer la variable avec le mot clé WithEvents ce qui permet ensuite d'utiliser le Handles du contrôle dans la déclaration d'une Sub:
Déclaration dans la partie déclaration du module(en haut) (WithEvents n'est pas accepté dans une procédure):
Private WithEvents Button1 As New Button
Remarque Button1 est accessible dans la totalité du module .
Puis écrire la sub évènement.
Sub OnClique ( sender As Object, EvArg As EventArgs) Handles Button1.Click
End Sub
Ainsi VB sait que pour l'évènement Button1.Click , il faut déclencher la Sub OnClique.
Il semble que quand on fait:Private WithEvents Button1 As Button (sans New) dans la partie déclaration puis DIM Button1 As New Button dans une procédure, la Sub OnClique ne fonctionne pas!!
C'est un problème de 'visibilité' donc bien faire Private WithEvents Button1 As New Button
Remarque: il pourrait y avoir plusieurs Handles sur une même sub, donc des évènements différents sur des objets différents déclenchant la même procédure.
Utiliser AddHandler
Déclaration (possible dans une procédure):
Dim Button1 As New Button
Puis écrire la gestion de l'évènement.( L'évènement Button1.click doit déclencher la procédure dont l'adresse est BouttonClique)
AddHandler Button1.Click, AddressOf BouttonClique
(ne pas oublier la virgule avant AddressOf)
Enfin on écrit la sub qui 'récupère ' l'évènement:
Private Sub BouttonClique (sender As Object, evArgs As EventArgs)
End Sub
Ainsi VB sait que pour un évènement du Button1 , il faut déclencher la Sub ButtonClique
Exemple avec AddHandler:
Créons un TextBox nommé TB et une procédure déclenchée par KeyUp de ce TextBox:
Dans une procédure (Button1_Click par exemple): Je crée un TextBox nommé TB, je le positionne, je met dedans le texte 'ici une textbox'. Je l'ajoute aux Contrôles du formulaire.
Grâce à 'AddHandler', je lie l'évènement Keyup de cet objet TB à la sub que j'ai crée :TextboxKeyup.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim TB As New System.Windows.Forms.TextBox
TB.Location = New System.Drawing.Point(2, 2)
TB.Text = "ici une textBox"
Me.Controls.Add(TB)
AddHandler TB.Keyup, AddressOf TextboxKeyup.
End sub

Sub TextboxKeyup.(ByVal sender As Object, ByVal e As KeyEventArgs)
...
End Sub

Si je crée un autre bouton TB2, j'ajoute de la même manière AddHandler TB2.Click, AddressOf TextboxKeyup2, ainsi chaque évènement de chaque contrôle à ses propres routines évènement et en cliquant sur le bouton TB2 on déclenche bien TextboxKeyup2
Attention, la procédure TextboxKeyup doit recevoir impérativement les bons paramètres: un objet et un KeyEventArgs car ce sont les paramètres retournés par un KeyUp.
Autre exemple avec AddHandler mais avec 2 boutons:
Il est possible de créer plusieurs contrôles ayant la même procédure évènement:
Exemple: Créons 2 boutons (BT1 et BT2) déclenchant une seule et même procédures (BoutonClique).
Dans ce cas, comment savoir sur quel bouton l'utilisateur à cliqué ?
En tête du module déclarons les boutons (Ils sont public):
Public BT1 As New System.Windows.Forms.Button
Public BT2 As New System.Windows.Forms.Button


Indiquons dans form_load par exemple la routine évènement commune (BoutonClique) grâce a AddHandler.
Form_Load
BT1.Location = New System.Drawing.Point(2, 2)
BT1.Text = "Bouton 1"
Me.Controls.Add(BT1)
BT2.Location = New System.Drawing.Point(100, 100)
BT2.Text = "Bouton 2"
Me.Controls.Add(BT2)
AddHandler BT1.Click, AddressOf BoutonClique
AddHandler BT2.Click, AddressOf BoutonClique
End Sub


Si c'est le bouton 1 qui a été cliqué, afficher "button1" dans une TextBox:
Sub BoutonClique(ByVal sender As Object, ByVal e As EventArgs)
If sender Is BT1 Then
TextBox1.Text = "button 1"
ElseIf sender Is BT2 Then
TextBox1.Text = "button 2"
End If
End Sub
La ruse est que déterminer quel objet (quel bouton) à déclenché l'évènement, pour cela on utilise le premier paramètre, le sender;
If sender Is BT1 Then : Si le sender est le bouton1..
Noter bien:
- le mot clé handles permet d'associer un événement à une procédure au moment de la conception.
Le concepteur sait qu'une procédure doit gérer les événements (il peut y en avoir plusieurs).
- le mot clé addhandler permet d'associer un événement à une procédure au moment de l'exécution.
Ceci est utile dans un cadre producteur-consommateur d'événements. Un objet produit un événement qui doit informer d'autres objets; au cours de l'exécution on crée l'association entre l'évènement et une procédure.
Remarque importante:
Les Handler ne sont en fait libérés qu’au déchargement complet du programme (application.exit) et non à la fermeture de la fenêtre et des objets contenus dans celle-ci... Aussi , si vous ouvrez plusieurs fois un même formulaire possédant AddHandler sur un bouton, cela créera à chaque fois un Handler qui s'ajoute aux précédents et l'évènement se déclenchera plusieurs fois lors de l'appuie du bouton!!
Il faut donc utiliser RemoveHandler pour libérer le Handler. L’instruction s’utilise de la même façon que le AddHandler ! (reprendre les lignes d’ajout du handler et remplacer AddHandler par RemoveHandler) .


Pour la petite histoire, nous créons un délégué à chaque fois que nous créons une procédure gestionnaire d'évènement avec le mot Handles ou avec AddHandler.
En C on utilise des pointeurs de fonction , adresse en mémoire indiquant ou le logiciel doit sauter quand on appelle une fonction ou un évènement. En VB on parle de délégué.

Aucun commentaire: