TD : Mise en oeuvre des formulaires et contrôles
(5, fin)
Deuxième partie : Les contrôles (suite), filtrer les saisies.
Il y a plusieurs façons différentes de valider une saisie
utilisateur. Nous allons, dans cette page, voir deux façons différentes de
faire qui sont complémentaires. La première méthode est celle que la plupart
des programmeurs non professionnels emploie. Il s'agit d'utiliser l'événement
"Validate" pour vérifier le contenu du contrôle avant de
donner le focus au contrôle suivant. Notez que l'événement "Validate"
n'existe que depuis VB6. Dans les versions précédentes, nous utilisions
l'événement "LostFocus".
L'événement "Validate" d'un contrôle se déclenche
au moment où l'utilisateur valide sa saisie (par Return, Tabulation ou en
cliquant sur le contrôle suivant). Attention, toutefois il ne se déclenche que
si le contrôle qui va avoir le focus (le contrôle suivant dans l'ordre de
tabulation de la feuille) a la valeur "True" dans sa
propriété "CausesValidation". C'est la valeur par défaut, il
n'y a donc rien à changer de ce côté là pour utiliser "Validate".
L'événement "Validate" comporte un argument :
Cancel. Celui-ci permet d'annuler la validation si la saisie de l'utilisateur
n'est pas correcte. Dans ce cas, le curseur ne quittera pas la zone de texte
incriminée et l'utilisateur pourra recommencer sa saisie.
Ici, nous voulons des saisies numériques. Visual-basic 6.0 nous
fournit une fonction pour vérifier que le contenu d'une chaîne ne comporte que
des caractères numériques (ou assimilés : séparateur de milliers,
séparateur décimal ...). C'est la fonction IsNumeric( MaChaine ), qui retourne
Vrai (True) ou Faux (False) en fonction de l'argument passé.
Vous allez coder l'événement "Validate" de
nos deux zones de saisie : txtC1 et txtC2. Tapez le code suivant
dans la fenêtre du module source de frmCalc :
|
'---------------------------------------------
Private Sub txtC1_Validate(Cancel As
Boolean)
'---------------------------------------------
If Not IsNumeric(txtC1.Text) Then
MsgBox "Saisie numérique requise !",
vbExclamation, "Zone de texte 1"
Cancel = True
End If
End Sub
'---------------------------------------------
Private Sub txtC2_Validate(Cancel As
Boolean)
'---------------------------------------------
If Not IsNumeric(txtC2.Text) Then
MsgBox "Saisie numérique requise !",
vbExclamation, "Zone de texte 2"
Cancel = True
End If
End Sub
|
Exécutez le programme, vous constaterez que, dès à
présent, vous ne pouvez plus faire de saisies alphabétiques dans nos deux
zones destinées à recevoir les nombres servant d'opérandes à notre calcul.
Cette méthode est tout à fait valide. Toutefois, nous
pouvons améliorer l'aspect "convivialité" de notre calculatrice. En
effet, il est dommage de laisser l'utilisateur saisir de l'alpha pour, ensuite,
lui dire que ce qu'il a saisi n'est pas correct. Il serait plus appréciable de travailler
"en amont", c'est à dire de ne pas laisser l'utilisateur taper autre
chose que du numérique. Une solution simple serait d'utiliser la propriété
masque de saisie (n'hésitez pas à consulter la documentation Microsoft à ce
sujet). Personnellement, je n'aime pas cette solution car je trouve que la
saisie dans des zones de texte utilisant un masque de saisie est un peu
"pénible". C'est pourquoi je vous propose une autre solution, encore
plus en amont. Il s'agit de filtrer les saisies au niveau du buffer clavier,
c'est à dire avant que les caractères n'apparaissent à l'écran.
Pour cela, il va nous falloir utiliser l'événement
"KeyPressed". Cet événement possède un argument
"KeyAscii" (Integer) qui contient le code Ascii de la touche pressée.
En testant ce code, nous aillons pouvoir accepter ou refuser le caractère
saisi.
 |
Pour
manipuler les codes Ascii des caractères, VB met à notre
disposition 2 fonctions dédiées :
- Asc( "A" ) retourne le code Ascii du caractère (ici, 65)
- Chr$( 65 ) retourne le caractère associé au code (ici,
"A") |
Ajoutez le code suivant pour gérer l'événement KeyPressed de
vos deux zones de texte txtC1 et txtC2 :
Faites un essai en exécutant le programme ... voilà une interface qui
commence à devenir conviviale. Elle ne laisse plus à l'utilisateur le loisir,
par distraction, d'entrer des opérandes qui déclencheraient une erreur lors de
l'exécution du calcul. Vous remarquerez la syntaxe, un peu spéciale, utilisant
LIKE qui est dérivée de l'utilisation des caractères génériques (
"[" et "]" ) dans les clauses SQL de Ms-Access.
Notez aussi le test de la touche Retour ou BackSpace ( vbBack,
chr$(8) qui permet à l'utilisateur de corriger sa saisie et que nous devons,
donc, autoriser.
Il nous reste à autoriser la saisie du séparateur décimal. Le
problème est que nous ne connaissons pas ce caractère qui peut être le point
"." ou la virgule ",". Nous pourrions interroger le système
via un appel d4API Windows mais nous n'en sommes pas encore à ce niveau de
programmation !
Une astuce consiste à utiliser la fonction IsNuméric() que nous
avons vue plus haut dans cette page. En effet, si "1.1" est numérique
c'est que le point est la séparateur décimal sinon, c'est la virgule ! c'est
aussi simple que cela !
Tapez le code suivant pour terminer cette partie du TD. Vous devez taper la
nouvelle fonction GetSep qui nous retourne le séparateur décimal valide
et modifier le code des procédures événementielles txtC1_KeyPress et txtC2_KeyPress
pour "laisser passer" le séparateur décimal.
Et voilà, le tour est joué !! Votre saisie est, maintenant, sécurisé au
maximum. Pour faire une erreur de saisie, il faudrait vraiment le vouloir !
Une dernière chose pourrait nous être utile : sélectionner le contenu des
TextBox lorsqu'elles prennent le focus. C'est à dire que lorsque le curseur
arrive dans une zone de texte, il faudrait sélectionner automatiquement le
contenu afin que l'utilisateur n'ait pas à effacer la valeur pour en mettre une
autre. Il lui suffira de taper la nouvelle valeur et celle-ci remplacera
l'ancienne.
Pour cela, vous allez taper le code de la procédure "Remplace" et
vous appellerez celle-ci lors de l'exécution de l'événement
"GotFocus" des zones de texte txtC1 et txtC2. Tapez le code de la
nouvelle fonction et son appel dans les procédures événementielles.
Notez l'emploi de la fonction TypeName qui renvoie, sous forme de chaîne
de caractères, le nom de la classe de l'objet. Cela nous permet de tester le type
du contrôle et de ne pas tenter d'appliquer un test pour des propriétés
qui n'existent pas pour d'autres types de contrôles (SelStart, SelLength ... ).
Notez aussi l'utilisation de la clause With qui permet de préfixer
automatiquement les propriétés avec un objet donné (ici,
Screen.ActiveForm.ActiveControl
qui désigne le contrôle actif du formulaire actif de l'objet écran)
et de ne pas avoir à taper de nombreuses fois son
nom.
Utilisez le lien ci-dessous pour télécharger le corrigé du projet si vous
avez rencontré des difficultés. Ne le faites que dans ce cas car, pour ce qui
est de votre formation à VB, il est nettement plus profitable, pour vous, de
taper le code afin de bien vous imprégner de la philosophie VB et des différents
mots de la syntaxe de ce langage.