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 9

Toujours des contrôles

Continuons à fouiller la boîte à outils. Nous sommes encore loin d'avoir fait le tour de tous les couteaux à huit lames, des équerres courbes, des tire-bouchons à ressort et autres limes à épaissir proposées par C#. Voilà donc un chapitre bric-à-brac, dans lequel on va découvrir quelques ustensiles dont l'utilisation posera rarement de gros problèmes, et qui pourront très agréablement enrichir notre interface.

1. La classe TabControl

Il s'agit d'un contrôle qui permet de doter un formulaire d'onglets, un ingrédient aussi connu pour améliorer le pot-au-feu que l'ergonomie d'une application.

Lorsqu'on le pose sur la Form, le TabControl prend l'aspect d'un rectangle qui délimite la partie de cette Form qui fonctionnera avec le système des onglets. Il est donc possible de laisser une zone (contenant des contrôles) qui sera visible quel que soit l'onglet sélectionné :

Pour ajouter des onglets en mode design, on peut passer soit par la propriété Tabpages, soit par Ajouter un onglet (accessible via un clic droit). Plusieurs propriétés, sur lesquelles je ne m'étendrai pas, règlent l'apparence de ces onglets. Au total, chacun est représenté par un objet Tabpage et le nombre d'onglets est donné par la propriété TabCount. Le texte affiché sur chaque onglet est donné par sa propriété Text, avec la possibilité éventuelle de lui associer une image via un contrôle ImageList.

L'événement majeur pour un contrôle TabControl est SelectedIndexChanged qui indique bien évidemment que l'utilisateur a changé d'onglet. L'onglet actif est donné par la propriété SelectedIndex.

Bref, vraiment rien de méchant, et c'est encore un beau joujou supplémentaire.

2. Les classes HScrollBar, VScrollBar et TrackBar

Ces trois classes permettent à l'utilisateur de déterminer une valeur en maniant un curseur, qu'il s'agisse d'une barre de défilement horizontale (HScrollBar), verticale (VScrollBar), ou de cette barre de réglage un peu particulière (Trackbar) :

De ces contrôles très faciles à manipuler, il y a bien peu à dire :

  • deux propriétés, Minimum et Maximum, déterminent la valeur associée à chaque extrémité.
  • deux autres, SmallChange et LargeChange, règlent la valeur de l'incrément lorsqu'on déplace le curseur (selon qu'on clique sur la flèche qui se trouve au bout de la barre ou dans la barre elle-même)
  • une propriété, Value, correspond à la valeur associée à la position actuelle du curseur.

A noter qu'il est possible d'afficher verticalement un contrôle Trackbar, en changeant sa propriété Orientation. Celui-ci possède de surcroît une propriété TickStyle, qui permet de modifier la trombine des graduations, et TickFrequency, qui règle leur intervalle.

L'événement privilégié associé à ces trois contrôles est le ValueChanged.

Et une fois qu'on a dit cela, on a fait le tour de la question.

3. La classe ProgressBar

Il s'agit de cette jolie chose censée faire patienter l'utilisateur, en lui indiquant grosso modo où on en est au cours d'une opération un peu longuette :

Là, c'est encore plus simple que précédemment, puisque l'utilisateur ne peut absolument pas agir sur ce contrôle. On retrouve donc les propriétés Minimum, Maximum et Value, mais guère plus, et pas d'événement particulier.

Circulez, y a rien, ou pas grand chose, à voir.

4. Les classes ToolTip et HelpProvider

Ces deux classes sont là pour donner une aide plus ou moins détaillée à l'utilisateur. Le ToolTip, c'est ce petit rectangle beige qui apparaît lorsqu'on stationne la souris pendant un certain temps au-dessus d'un contrôle :

En fait, il ne faut créer qu'un seul contrôle ToolTip par Form ; cet unique contrôle pourra servir ensuite pour l'ensemble des contrôles de cette Form. Les propriétés principales du contrôle tournent autour de la question du Delay : le temps au bout duquel le rectangle apparaît, le temps durant lequel il reste affiché, etc. Je ne détaille pas , parce que franchement, ça ne pose aucune difficulté. La seule astuce à connaître est le code qui permet d'associer un message à un contrôle donné. Il faudra pour cela écrire...

NomDuToolTip.SetToolTip(NomDuContrôle, Message)

Cette ligne devra naturellement être exécutée de préférence avant qu'il se passe quoi que ce soit d'autre, donc dans la procédure associée à l'événement Form.Load.

Quant au Helpprovider, que je ne cite ici que par acquit de conscience, il sert à "brancher" l'appui de la touche F1 d'un contrôle directement sur un fichier d'aide (*.chm ou *.htm), à la bonne page.

5. Les classes DomainUpDown et NumericUpDown

Ces deux contrôles ont un comportement très voisin de celui d'une liste qui aurait un look un peu particulier. Le premier, DomainUpDown, oblige l'utilisateur à choisir parmi une collection de Strings, et le second, NumericUpDown, parmi une série de nombres (simplement définis par un minimum et un maximum) :

Les propriétés et les méthodes de ces deux contrôles sont très voisines de celles des listes, pour ne pas dire qu'elles leur ressemblent comme deux couteaux (comme on dit en Alsace).

6. Les classes DateTimePicker et MonthCalendar

Il s'agit de deux contrôles spécialisés dans la saisie d'une date. Le premier des deux, DateTimePicker, est le plus polyvalent. Il se présente comme une liste déroulante déployant un calendrier :

Ce contrôle peut largement être paramétré :

  • fixation d'une date minimum et/ou maximum par les propriétés MinDate et MaxDate
  • empêchement de l'affichage du calendrier par ShowUpDown
  • changement de la valeur par défaut de la date, par DateTime
  • modification du format d'affichage de la date, par Format
  • modification de l'apparence du calendrier, par les six propriétés Calendar...

La date saisie est quant à elle stockée dans la propriété Value. Et le principal événement lié à ce contrôle est ValueChanged, provoqué par un changement de la valeur de la date.

Quant à MonthCalendar, c'est un DateTimePicker sans la zone de saisie, autrement dit un simple calendrier. L'avantage est que l'utilisateur pourra y sélectionner plusieurs dates (ce qui modifiera la valeur des propriétés SelectionStart, SelectionEnd et SelectionRange).

Bon, allez, on passe.

7. La classe Timer

Ce petit contrôle recouvre un outil un peu déroutant au début, mais qui se révèle indispensable dans certaines situations :

En effet, jusque là, tous les événements que nous avons gérés étaient, d'une manière directe ou indirecte, provoqués par une action de l'utilisateur : un clic, une frappe au clavier, etc. Même lorsque l'événement était causé par l'exécution d'une ligne de code, celle-ci se trouvait dans une procédure elle-même déclenchée par une action de l'utilisateur (ou alors elle se trouvait dans une procédure elle-même appelée par une action de l'utilisateur, mais quelle que soit la longueur de la chaîne des causalités, au bout du bout du bout, il y avait un geste de l'utilisateur).

Or, dans certains cas, on peut souhaiter que que certaines lignes de code soient exécutées indépendamment de toute action de l'utilisateur. Cela veut dire que ces lignes de code devront être stockées dans une procédure non liée à un événement causé par celui ou celle qui se servira du programme.

Par exemple, imaginons que nous programmions un QCM en temps limité. Nous souhaitons que l'application se termine automatiquement au bout d'un délai donné, par exemple 30 minutes. Il va donc falloir, chaque minute (ou toutes les dix secondes, ou toutes les secondes), vérifier le temps écoulé depuis le début et en cas de besoin, prendre les mesures qui s'imposent en coupant le sifflet de l'utilisateur. Eh bien, c'est très exactement à cela que sert le Timer.

Ce contrôle est capable d'une chose (et une seule) : générer un événement Tick à intervalle régulier. Cet événement Tick surviendra donc automatiquement toutes les secondes, ou toutes les demi-secondes, ou toutes les douze secondes (c'est évidemment le programmeur qui décide, via la valeur de la propriété Interval) quoi que fasse l'utilisateur... et même s'il ne fait rien du tout ! Précisons que le Timer est déclenché ou arrêté par la valeur de sa propriété booléenne Enabled.

Pour finir, le Timer est par définition invisible pour l'utilisateur. À l'instar du ToolTipText ou de l'ImageList, Il ne se pose pas sur la Form, mais à côté.

Bon, assez bavardé, amusons-nous un peu :
 

Exercice

Exécutable

Sources

Final Countdown


8. Les classes de boîtes de dialogue communes

Vous aurez sans doute remarqué que sous Windows, quel que soit le logiciel utilisé, ou presque, certaines commandes possèdent un très fort air de famille. Par exemple, lorsque vous faites Fichier - Ouvrir, Fichier - Enregistrer, Fichier - Imprimer, et quelques autres encore, non seulement les fonctionnalités proposées sont les mêmes, mais encore la présentation de la boîte de dialogue est rigoureusement identique d'une application à l'autre, au poil de nez près.

Cela ne peut signifier que deux choses. Soit les développeurs des différents logiciels prennent un soin maniaque à recopier leurs interfaces au millimètre près pour obtenir des copies conformes. Soit tous ces braves gens n'écrivent en fait rien du tout, et se content d'appeler un code, toujours le même, déjà programmé au sein de Windows. Eh bien devinez quoi ? C'est la deuxième proposition qui est la bonne.

De sorte que vous me voyez venir avec mes gros sabots : lorsque nous devrons insérer une de ces « boîtes de dialogues communes » dans notre application, nul besoin de la programmer nous-mêmes : Windows, via Visual Studio, nous offre la possibilité d'utiliser directement son code, au travers d'une série de classes. Les voici :

  • OpenFileDialog : correspond à la boîte de dialogue Fichier - Ouvrir
  • SaveFileDialog : correspond aux boîtes de dialogue Fichier - Enregistrer et Fichier - Enregistrer Sous
  • FolderBrowserDialog : correspond à un explorateur de répertoires (qui repère automatiquement la structure des répertoires de la machine sur laquelle tourne l'application)
  • FontDialog : correspond à la boîte de dialogue Police
  • ColorDialog : correspond à une boîte de dialogue donnant accès aux couleurs personnalisées
  • PrintDialog : correspond à la boîte de dialogue Fichier - Imprimer
  • PrintPreviewDialog : correspond à la boîte de dialogue Fichier - Aperçu avant impression
  • PrintPreviewControl : zone permettant d'afficher un Aperçu avant impression
  • PrintDocument : correspond à la boîte de dialogue Fichier - Imprimer
  • PageSetupDialog : correspond à la boîte de dialogue Fichier - Mise en page

Tous ces contrôles, hormis PrintPreviewControl, ne se positionnent pas sur la Form, mais en-dehors. Pour en déclencher l'apparition, il suffit de leur appliquer dans le code la méthode ShowDialog. Naturellement, les propriétés de ces contrôles permettent tout à la fois de paramétrer ces boîtes de dialogue et d'en récupérer les résultats. Je ne m'étendrai pas sur les détails techniques de leur utilisation, qui ne présentent pas grand intérêt pour la compréhension du langage, et dont la mise en oeuvre ne pose aucune difficulté majeure pour leur mise en oeuvre... quand on a sous la main une bonne documentation.

Mais cela signifie encore une fois (je me permets d'insister), qu'avec C#, toutes les tâches banales et courantes d'une application telles que Ouvrir, Enregistrer, Imprimer, et tutti quanti, se programment en un tournemain, vu que d'autres ont déjà fait le travail à votre place.