La classe button
Rappel: La fenêtre enfant peut déterminer le handle de la fenêtre
parent en utilisant la fonction GetParent (hwnd) où hwnd est la handle
de la fenêtre enfant.
Il est alors possible d'envoyer un message au parent via SendMessage (Voir chapitre
sur les messages).
Il existe différents types de boutons sous Windows que nous allons étudier. Mais avant, quelques généralités:
Messages des enfants aux parents:
Chaque clique sur un bouton provoque un message WM_COMMAND qui sera traité dans le procédure de gestion des messages de la fenêtres parents. Comme tous messages, WM_COMMAND uilise wParam et lParam avec:
wParam qui reçoit alors l'Id de la fenêtre enfant,
LOWORD (lParam) qui reçoit le handle de la fenêtre enfant
HIWORD (lParam) Code de notification.
Si votre fenêtre
principale possède un menu, il faudra
bien contrôler LOWORD (lParam):
- il reçoit le handle de la fenêtre enfant (donc différent de 0)
ou
- (cette valeur est NULL) il s'agit d'une option/élément de menu sélectionné qui est envoyée et pas d'un id de contrôle !
En effet, rien n'empêche d'avoir dans wParam un Id ayant une valeur dans le menu identique à celui d'un Id de fenêtre enfant.
Code de notification prenant comme valeur:
- BN_CLICKED si l'utilisateur à cliqué sur le bouton
- BN_DOUBLECLICKED si l'utilisateur a double-cliqué sur le bouton.
(Il existe d'autres codes de notifications, ils servaient pour le style de bouton devenue obsolète depuis la version 3.1 de Windows appelé BS_USERBUTTON).
Messages des parents aux enfants :
La fenêtre parent pourra envoyer des messages aux fenêtres filles de la classe bouton: 5 principaux messages spécifiques aux boutons commençant par BM_ .
Ces messages sont :
BM_GETCHECK et BM_SETCHECK : Connaître ou fixer les repères
de selections (X ou rond) des cases de pointages et des boutons radio.
Pour le message BM_SETCHECK:
wParam va spécifier l'état coché ou non. Les valeurs étant:
Valeur | Désignation |
BST_CHECKED | Le bouton est coché |
BST_INDETERMINATE | Valeur indéterminé, le bouton est alors grisé mais modifiable (Ne marche qu'avec les styles BS_3STATE ou BS_AUTO3STATE vu un peu plus loin) |
BST_UNCHECKED | Le bouton est décoché |
lParam étant lui à NULL.
BM_GETCHECK :
wParam et lParam sont à NULL.
La fonction SendMessage retournera alors une des valeurs BST_CHECKED, BST_INDETERMINATE
ou BST_UNCHECKED.
BM_GETSTATE et BM_SETSTATE : Connaître ou fixer l'état normal
ou enfoncé d'un bouton poussoir.
Pour le message BM_SETCHECK:
wParam: Peut prendre TRUE ou FALSE
lParam: n'est pas utilisé.
BM_GETCHECK :
wParam et lParam sont à NULL.
La fonction SendMessage retournera alors TRUE ou FALSE.
BM_SETSTYLE qui permet de modifier le style du bouton après sa
création.
wParam doit recevoir le nouveau style du bouton (Voir chapitre suivant pour les styles possibles). La partie basse de lParam recevra TRUE pour forcer le bouton a se redessiner. FALSE pour ne pas le redessiner.
Les différents styles de la classe bouton:
- Les boutons poussoirs :
2 types : BS_PUSHBUTTON et BS_DEFPUSHBUTTON (pour bouton par défaut)
L'option par défaut (En fait, le bouton qui gagne le focus par défaut)
ne fonctionnant que dans des fenêtres de type dialogues. Sinon, il n'y
a pas de différence entre les deux boutons hormis le fait que le bouton
par défaut à une bordure plus épaisse.
On peut faire passer le bouton de normal à enfoncé en faisant
:
SendMessage (hwndButton, BM_SETSTATE, 1, 0L) ;
Et inversement:
SendMessage (hwndButton, BM_SETSTATE, 0, 0L) ;
On pourra aussi envoyer un message BM_GETSTATE pour connaître l'état d'un bouton, mais es-ce vraiment utile ? Non pour ce style, le bouton ne mémorise pas son état !
- Les cases à cocher :
Les styles sont : BS_CHECKBOX et BS_AUTOCHECKBOX
AUTO : Le dessin de le croix sera géré automatiquement. Sinon,
ce sera à vous de le faire.
Lors de la création d'un bouton de ce type, on pourra passez BS_LEFTTEXT
pour que le texte apparaisse à coche de la case à cocher. Sachant
que par défaut, il se trouve à droite
On pourra connaître l'état coché ou non des objets grace à BM_GETCHECK. Il suffit alors d'utiliser bCHECK = SendMessage (hwndButton, BM_GETCHECK, 0, 0L).
On pourra aussi le positionner via BM_SETCHECK (SendMessage (hwndButton, BM_SETCHECK,
1, 0L).
Concerant le style BS_CHECKBOX, on pourra alors gérer l'état coché ou non de notre objet lors du traitement du message WM_COMMAND, on pourra alors taper une ligne du type pour gérer l'affichage de le croix (cas d'un bouton non auto) : SendMessage (LOWORD (lParam), BM_SETCHECK, (WORD) !SendMessage (LOWORD (lPAram), BM_GETCHECK, 0, 0L), 0L);
Deux autres styles de boutons : BS_3STATE et BS_AUTO3STATE qui permet d'avoir un troisième état qui correspond en fait à l'état désactivé du bouton (BM_SETCHECK avec la valeur 2 dans wParam). Cependant, le bouton va continuer à envoyer les états lorsques les utilisateurs cliqueront dessus. Il sera donc préférable d'utiliser une autre méthode: Voyez le paragraphe Rendre un bouton actif ou non
- Bouton radio:
Les styles possible sont : BS_RADIOBUTTON ou BS_AUTORADIOBUTTON (Là aussi,
auto ne marchera que dans les boîtes de dialogue...)
Pour cocher la case:
SendMessage (hwndbutton, BM_SETCHECK, 1 ,0L);
En principe, on utilise plusieurs boutons radios ensemble et seul 1 des boutons
radios pourra être choisi. Dans ce cas, il faudra désactiver les
autres boutons radios associés (Hé non, cela ne se fait pas tout
seul !). Il faudra donc avoir du code du type:
SendMessage (hwndbutton, BM_SETCHECK, 0 ,0L);
- Boîte de groupe:
Un seul style: BS_GROUPBOX
Il s'agit d'une bizzarerie de la classe de boutons puisqu'elle ne traite rien
provenant du clavier ou de la souris, et ne fait d'ailleur rien (Même
pas de WM_COMMANDE).
Par contre, on utilise souvent cette classe pour permettre de regrouper "graphiquement" parlant des objets comme les boutons radios.
Cette objet affiche en effet un rectangle et un titre. On pourra alors dessiner n boutons radios dans ce rectangle.
Créer un objet de la classe button:
Nous utiliserons la fonction CreateWindow() ou mieux, CreateWindowEx(). Si vous ne connaissez pas (!?), voir le chapitre sur la création d'instance de fenêtre et peut-être même revoyez les bases intégralement !
Il faudra alors renseigner:
Nom de la classe " button " Texte dans la fenêtre Style de fenêtre WS_CHILD | WS_VISIBLE | style (BS_...) Position x Position y Largeur Hauteur Fenêtre parent hwnd ID de fenêtre enfant i (à mettre dans le champ correspondant au menu) Handle d'instance ((LPCREATESTRUCT) lparam) -> hInstance ou une variable Paramètres supplémentaires NULLCe qui donne:
hwndbutton=CreateWindowEx(0, "button", "Texte dans le bouton", WS_CHILD| WS_VISIBLE | style du bouton (BS_PUSHBUTTON, ...), coordonnée x, coordonnée y, largeur, hauteur, hwndParent, (HMENU) (int) (ID_CHILD), hInstance, NULL);
Voici un petit exemple avec un bouton de style BS_PUSHBUTTON:
Attention, le code dans WM_COMMANDE est trop simplifié.
Pour détruire un bouton:
Simplement par la fonction CloseWindow (hwndButton); ou DestroyWindow(hwndButton);
Pour modifier ou connaître le texte d'un bouton:
Il s'agit à l'origine de fenêtres. On utilisera alors des fonctions déjà étudiées pour lire ou modifier le texte d'un bouton:
Pour modifier un texte : SetWindowText (hwnd, lpszString);
Pour lire le texte : nLength = GetWindowText (hwnd, lpszBuffer, nMaxLength);
nMaxLength étant le nombre maxi de caractère à récupérer.
On pourra initialiser cette variable via la fonction:
nLength = GetWindowTextLength (hwnd);
(Voir le chapitre complément sur les fenêtres le sous chapitre Fonction permettant de modifier les paramètres d'une fenêtre pour plus de détail sur ces fonctions).
Rendre un bouton visible ou non:
Il y a deux occasions où l'on peut demander à rendre visible ou non un bouton:
Lors de sa création:
Dans ce cas, rien de plus simple, dans la fonction CreateWindow on indiquera ou non l'attribut WS_VISIBLE dans la classe de la fenêtre enfant...
Durant la période de vie du bouton:
Et là aussi, ce sera tout aussi simple, on pourra afficher le bouton
en utilisant la fonction ShowWindow (hwndChild, SW_SHOWNORMAL);
De même pour cacher un bouton, il suffira de faire ShowWindow (hwndChild,
SW_HIDE);
Il ne faut pas oublier que les boutons ne sont que de simples fenêtres...
Enfin, pour savoir si un bouton est visible: IsWindowVisible (hwndChild); (voir chapitre complément sur les fenêtres).
(Voir dans le chapitres les bases le sous chapitre afficher le contenu d'une fenêtre si vous n'avez pas compris ce paragraphe !)
Rendre un bouton actif ou non:
Pour rendre actif ou non un bouton:
EnableWindow (hwndChild, FALSE); désactive le bouton. Le bouton ne répondra
alors plus aux entrées souris ou clavier.
Cette méthode est donc à préférer au type de bouton
BS_3STATE qui se contente de griser l'objet, mais ne le désactive pas
par exemple !
Pour réactiver:
EnableWindow (hwndChild, TRUE);
Enfin, pour savoir si un bouton est actif: IsWindowEnable (hwndChild);
Afficher une image dans un bouton:
BM_GETIMAGE et BM_SETIMAGE : Pour traiter une image sur un bouton. L'image pouvant être un BMP ou une icône.
wParam contiendra IMAGE_BITMAP ou IMAGE_ICON suivant le type d'image.
lParam contiendra le handle de l'image pour BM_SETIMAGE, n'est pas utilisé pour BM_GETIMAGE
En sortie, la valeur est soit NULL signifiant "pas d'image précédement sur le bouton", soit le handle de l'image précédente.