Une remarque pertinente ?
Une critique impertinente ? Un lynchage en règle ? Une invitation sous les tropiques ? Ecrivez-moi ! |
||||||||||||||||||||||
Conçu et enseigné tel qu'en lui même, avec
pertes, fracas et humour de qualité
supérieure
par Christophe Darmangeat dans le M2 PISE du Master MECI (Université Paris 7) |
||||||||||||||||||||||
Partie 4
Dialoguer avec l'utilisateurSi vous êtes fins observateurs, vous avez sans doute remarqué une petite différence entre l'environnement de C# et celui des langages procéduraux traditionnels tels que le C. Finie en effet l'austère « console » de texte, avec son vilain curseur tout moche qui signalait à l'utilisateur que le programme attendait la saisie d'une valeur au clavier. Maintenant, on a des forms, des boutons, des trucs et des bidules à n'en savoir que faire, et en plus, on peut cliquer partout quand on veut. C'est quand même drôlement plus rigolo. Dans les langages « à console », pour envoyer une information du programme vers l'utilisateur, on utilisait l'instruction Écrire ou son équivalent. Pour que le programme demande une valeur à l'utilisateur, on utilisait l'instruction Lire ou son équivalent. Et la vie suivait son cours. Les choses étaient peut-être monotones, mais au moins on savait à quoi s'en tenir. Oui mais voilà, fini tout çà. Loin de se dérouler en suivant un fil linéaire, le dialogue (de sourds ?) entre l'homme et la machine va maintenant passer par de multiples canaux, qui sont autant de possibilités en plus de rendre la vie de l'homme plus joyeuse. Mais un peu plus compliquée, parfois, aussi. 1. La classe TextBox1.1 PrésentationDorénavant, donc, finie l'instruction Lire qui interrompait le déroulement du programme. La plupart, si ce n'est la totalité, des informations saisies par l'utilisateur le seront au travers d'objets créés à partir de classes spécialisées pour cela. Cela vous paraît obscur ? En fait, je ne fais que traduire en mots savants ce que vous savez tous par expérience ; car qui peut lire ces lignes sans avoir jamais saisi une information dans un programme fonctionnant sous Windows (ou MacOS, ou Android, c'est pareil) ? Nous savons donc qu'il existe dans toute application informatique moderne des zones de l'écran dédiées pour que l'utilisateur puisse entrer du texte (ou des nombres). Cette zone dans le Framework .Net, c'est avant tout la « boîte à texte », ou TextBox. Il s'agit de la classe de prédilection pour permettre à l'utilisateur de passer des informations au programme — mais c'est loin d'être la seule, comme vous vous en doutez. 1.2 PropriétésIl n'y a pas grand chose de particulier à dire de cette classe, qui possède la plupart des propriétés standard que nous avons déjà rencontrées. Toutefois, un point essentiel est que dans une TextBox, la propriété Text ne sert plus à désigner ce qui est écrit sur le contrôle (et donc fixé par le programmeur), mais ce qui se trouve à l'intérieur de la TextBox. Autrement dit, comme l'utilisateur a directement accès au contenu de la TextBox (sauf si on le lui interdit par une manoeuvre spéciale), il peut à loisir en modifier la propriété Text . Et c'est ainsi, au travers de cette propriété Text, qu'on récupère, dans le programme, ce qu'il aura saisi. Une conséquence de ce qui précède est que tout ce que saisit l'utilisateur via une TextBox, même lorsqu'il s'agit de nombres, est traité par C# comme une chaîne de caractères, ce qui nous imposera parfois des conversions de types, autrement dit des « cast ». Vite fait, bien fait, signalons quelques propriétés typiques de la classe TextBox :
1.3 ÉvénementsIl est assez rare qu'on ait à gérer un événement sur un objet de la classe TextBox : la plupart du temps, on laisse l'utilisateur y écrire tranquillement ce qu'il souhaite, et ce n'est que dans un second temps, suite par exemple à un clic sur un bouton, que l'application en récupère le contenu. Si toutefois on avait besoin de faire réagir celle-ci en temps réel à toute modification survenue dans une Textbox (pour interdire la frappe de certains caractères, ou que sais-je encore), on dispose de l'événement TextChanged. On pourra ainsi programmer une procédure associée à cet événement, qui se déclenchera lors de toute modification de la propriété Text. Ainsi, si une telle procédure existe, taper « bonjour » dans une TextBox la déclenchera successivement sept fois (et même davantage si on a fait des fautes de frappe et des corrections !). Tout ceci est plus que suffisant pour que vous vous dérouilliez les neurones avec quelques exercices :
2. La classe « Boîte à Messages » (MessageBox)2.1 Customiser et afficher une boîteDu côté des possibles alternatives à l'instruction Écrire, nous avons déjà vu qu'il était possible de modifier par du code le texte associé à un contrôle (barre de titre de la Form, bouton, label, etc.). Dans bien des situations, c'est tout à fait satisfaisant. Mais on peut aussi souhaiter dégainer une arme bien connue de tout utilisateur de Windows : celle de la MessageBox, la « boîte à message », sorte de mini-form préfabriquée avec quelques options, telle que celle-ci :
Ces options des MessageBox, ce sont :
Pour mettre en oeuvre tout cela, quelques informations sont bien utiles :
2.2 Parenthèse indispensable : qu'est ce qu'une énumération ?Une énumération est une association entre des mots-clés du langage et des nombres entiers. C'est donc, en quelque sorte, une table à deux colonnes, avec dans l'une des nombres entiers et dans l'autre des intitulés reconnus par le langage. Une énumération peut avoir été créée par les concepteurs du langage eux-mêmes (c'est le cas ici) ; elle peut aussi être créée par le programmeur. Dans les deux cas, l'objectif est d'aider le programmeur, en lui épargnant d'avoir à entrer, donc à connaître, les codes en question. Une fois l'énumération créée, le programmeur disposera en effet d'une liste d'intitulés relativement explicites qu'il utilisera dans son code. Lors de la compilation, ces intitulés seront remplacés par les entiers auxquels ils sont associés dans l'énumération. Dans le cas des MessageBox interviennent deux énumérations d'ores et déjà prévues par le langage :
Reprenons l'exemple affiché plus haut :
Pour l'afficher, on entrera donc le code : string a =
"Missile thermonucléaire armé.
Voulez-vous continuer ?"; Ce n'est pas si compliqué, hein ? Allez, une dernière petite couche. 2.3 Récupérer le résultat d'une MessageBoxQuelle drôle d'idée ! Comment un bidule pareil pourrait-il produire un résultat qu'on puisse, ou doive, récupérer ? En fait, c'est très simple : si une MessageBox propose plus d'un bouton, c'est qu'elle donne un choix à l'utilisateur... et que ce choix a une certaine importance pour la suite du programme (ou alors, le programmeur est vraiment un petit plaisantin). En fait, le résultat d'une MessageBox, c'est le bouton sur lequel l'utilisateur clique pour la faire disparaître. Pour récupérer convenablement ledit résultat, il suffit de savoir deux choses :
Pour tester le résultat d'une MessageBox, on pourra donc stocker son résultat dans une variable de type DialogResult, avant d'interroger le contenu de cette variable : string a ="Missile thermonucléaire armé.
Voulez-vous continuer ?"; Assez ri. Il est grand temps de vous dégourdir avec
quelques petits exercices.
3. Autres éléments d'interfaceVous le savez bien, entre l'utilisateur et les applications, un environnement graphique tel que Windows a mis en place moult autres voies de dialogue que le texte. Je pense en particulier aux cases, carrées ou rondes, dont il est toujours dommage qu'il en manque une. Tour d'horizon. 3.1 La classe CheckboxLa Checkbox, c'est cette charmante petite case carrée bien connue : 3.1.1 PropriétésPassons rapidement sur les propriétés que les Checkbox partagent avec la plupart des autres classes, pour en venir à celle qui nous intéresse au premier chef : celle qui nous permet de savoir si une Checkbox est cochée ou non (si nous l'utilisons en lecture), ou de faire en sorte que Checkbox soit cochée ou non (si nous l'utilisons en écriture). Il s'agit de Checked : propriété booléenne, qui vaut naturellement True lorsque la case est cochée et False lorsqu'elle ne l'est pas. Remarque anticipatrice
(mais de peu) :
Les Checkbox sont souvent rassemblées dans un conteneur, qui les présente comme faisant partie d'un même groupe. Cette présentation est purement visuelle, pour ne pas dire décorative : elle n'exerce aucune espèce d'effet sur le fonctionnement de la Checkbox. Celle-ci est toujours individuelle et indépendante de ses éventuelles congénères. 3.1.2 ÉvènementsLe principal événement spécifique des CheckBox est CheckChanged. Il se déclenche chaque fois que la case est cochée ou décochée. On remarquera la différence subtile, mais réelle, entre les événements CheckChanged et Click, appliqués à une Checkbox :
Il faut donc bien réfléchir avant de choisir l'événement que l'on souhaite gérer, en sachant tout de même que dans l'immense majorité des cas, il s'agira logiquement de CheckChanged. Remarque fine : On notera avec intérêt que lorsqu'une case Checkbox déclenche un événement CheckChanged, cela signifie que l'état de la case a changé. Mais rien n'indique donc si c'est parce qu'elle vient d'être cochée ou décochée... Si on a besoin de le savoir, on n'échappera pas à un test sur la propriété Checked. 3.1.3. Un raffinement suprêmeEt maintenant, un petit tour de vice (non, ce n'est pas une faute d'orthographe). Dans 99,99% des cas, ce qui précède suffira à notre bonheur. Oui, mais voilà, j'ai décidé de vous embêter et de pousser le contrôle dans ses retranchements. On peut en effet obtenir d'une CheckBox qu'elle fonctionne non sur deux, mais sur trois jambes, et qu'en plus des états « cochée » et « décochée », la case puisse aussi être « à moitié cochée » — cette situation est généralement censée indiquée que certains sous-élements correspondant à la Checkbox sont actifs, et d'autres non : Pour pouvoir gérer cette situation nouvelle, il faut recourir à deux autres propriétés supplémentaires :
Remarque
« utilisons notre science toute
fraîche » :
Vous n'aurez bien sûr pas manqué d'en déduire que Checked, Unchecked et Indeterminate étaient des membres d'énumération, et donc qu'ils dissimulaient en réalité trois nombres entiers. 3.2 Les classes Radiobutton, GroupBox et PanelTrois d'un coup, vous vous rendez compte ? Mais ce ne sont pas les plus pénibles. Voilà tout de suite une illustration de notre propos : 3.2.1 La question des conteneursLe RadioButton, dans sa forme classique, n'est donc autre que la célèbre petite case ronde. Par définition, cette case ne fonctionne qu'en groupe, conjointement avec d'autres, puisque par principe, une seule des cases d'un même groupe peut être cochée à la fois. Autrement dit, cocher une case d'un groupe décoche automatiquement les autres cases du groupe. Ce groupe est défini par ce qu'on appelle un conteneur. Un conteneur est un objet qui en contient d'autres. Nous en connaissons déjà un : la Form, par définition, est le conteneur suprême de toute application. Les RadioButton, elles, seront regroupées au choix dans un GroupBox ou dans un Panel. La différence entre les deux n'est pas très grande, et surtout, elle est purement visuelle : le GroupBox est le conteneur standard, avec une bordure et un titre, comme dans l'exemple ci-dessus. Le Panel est un conteneur sans texte et sans bordure, donc invisible (mais néanmoins indispensable pour que les cases fonctionnent correctement en groupe). Un RadioButton appartient donc au même groupe qu'un autre Radiobutton s'il est placé dans le même conteneur (généralement, un GroupBox). Ce simple fait suffit à faire marcher les Radiobutton les uns avec les autres. Il n'y a pas une seule ligne de code à écrire pour cela. 3.2.2 PropriétésLa propriété la plus utilisée du Radiobutton est Checked. C'est la même que pour les CheckBox : une propriété booléenne qui renvoie (ou définit) si un bouton radio est coché ou non. Au passage, je signale une petite astuce pas chère qui peut éventuellement s'avérer utile dans certaines circonstances. Les RadioButton peuvent en effet parfois prendre une drôle de tête, comme dans cet exemple : Ici, nous avons un poste de radio (c'est de circonstance), où nous pouvons, via deux boutons, choisir une gamme de fréquences ou une autre. Sur l'image ci-dessus, c'est la FM qui est enclenchée. Eh bien, ce look un peu inattendu est obtenu simplement à partir de RadioButton ! Mais leur propriété Appearance a pour valeur Button au lieu de Normal. 3.2.3 EvénementsLe changement d'état d'un bouton radio peut être provoqué par beaucoup de choses. Un clic, bien sûr. Mais aussi, la frappe de certaines touches du clavier. Donc, le même raisonnement que pour les CheckBox s'applique : si l'on doit gérer le changement d'état en temps réel, il faut utiliser l'événement CheckChanged. Bon, si on se faisait trois petits exos ? En ce qui concerne Options
onéreuses, vous avez toutes les
connaissances pour reproduire l'exécutable.
Vos premières tenatives risquent fort
d'aboutir à un code lourdingue et répétitif.
Mais si vous utilisez judicieusement certaines
connaissances mentionnées dans ce cours, vous
pourrez l'alléger considérablement. En
revanche, pour aboutir aux simplifications
ultimes, il vous faut disposer de quelques
outils supplémentaires... que nous
découvrirons au chapitre suivant, pas avant. |