logo UsualSoft   Skip Navigation Links
Accueil
Références
Tutoriels
Formations
Liens téléchargements

Contact : cgruchet@usualsoft.fr - Tél: 02 38 34 99 88 / 06 22 82 90 55
Microsoft Certified Professional
Cours : Visual-Basic

Interface utilisateur

TD : Formulaires et contrôles

Claude Gruchet
Initiation TD1-P5  

Retour Début du TD1  

TD : Mise en oeuvre des formulaires et contrôles (5, fin)

Télécharger le début du projet

Prévu pour se décompacter dans "C:\Mes documents\PForms"

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 :

'-------------------------------------------------
Private Sub txtC1_KeyPress(KeyAscii As Integer)
'-------------------------------------------------
   If (Not Chr$(KeyAscii) Like "[0-9]") _
   And (Chr$(KeyAscii) <> vbBack) Then
      Beep
      KeyAscii = 0
   End If
End Sub

'--------------------------------------------------
Private Sub txtC2_KeyPress(KeyAscii As Integer)
'--------------------------------------------------
   If (Not Chr$(KeyAscii) Like "[0-9]") _
   And (Chr$(KeyAscii) <> vbBack) Then
      Beep
      KeyAscii = 0
   End If
End Sub


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.

'---------------------------------------------
Private Function GetSep() As String
'---------------------------------------------
   If IsNumeric("1.1") Then
      GetSep = "."
   Else
      GetSep = ","
   End If
End Function

'---------------------------------------------
Private Sub txtC1_KeyPress(KeyAscii As Integer)
'---------------------------------------------
   If (Not Chr$(KeyAscii) Like "[0-9]") _
   And (Chr$(KeyAscii) <> vbBack) _
   And (Chr$(KeyAscii) <> GetSep()) Then
      Beep
      KeyAscii = 0
   End If
End Sub

'---------------------------------------------
Private Sub txtC2_KeyPress(KeyAscii As Integer)
'---------------------------------------------
   If (Not Chr$(KeyAscii) Like "[0-9]") _
   And (Chr$(KeyAscii) <> vbBack) _
   And (Chr$(KeyAscii) <> GetSep()) Then
      Beep
      KeyAscii = 0
   End If
End Sub

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.

 

Télécharger le corrigé final du projet

Prévu pour se décompacter dans "C:\Mes documents\PForms"

Retour Début du TD1