Dans le vocabulaire specifique a Windows, un élement constitutif d'une boite de dialogue
(bouton, champ de texte, ...) est appelé un controle.
Ces controles sont ajoutés en general a la boite de dialogue a partir de l'editeur de VC++
mais ils peuvent aussi l'etre de maniere dynamique durant le runtime.
Si vous essayez de cliquer sur un controle, il apparaitra une boite de dialogue permettant
de configurer les caractéristiques du controle : son apparence, le texte qu'il contient, ...
On y trouve notamment un champ tres tres important puisqu'il va nous permettre d'identifier
et designer notre controle parmi les autres : son ID. Il est a noter que chaque boite de dialogue
possede aussi une ID lui permettant de se distinguer des autres.
Nous allons creer une boite de dialogue et l'afficher a l'ecran. Pour cela, il nous faut ... une boite de dialogue :). Nous allons donc prendre, pour commencer, celle proposée par defaut par l'editeur de resource de VC++. Nous avons donc 2 boutons simple : un CANCEL et un OK. Ces boutons ont des ID specifiques, respectivement : IDCANCEL et IDOK. Maintenant que nous avons une boite de dialogue, nous allons l'ajouter au projet. Pour cela, sauvez le fichier de ressource (fichier ".rc" ascii simple contenant la description des ressources utilisees par l'application) avec un petit Ctrl^S. VC++ a normalement du generer un header specifique associe a notre fichier ressource et contenant tous les #defines specifiques aux ID de controle et permettant donc de les utiliser directement dans nos fichier sources. Il faut rajouter ces fichiers au projet, pour cela, faites un Project>Add to project>Files ... et selectionnez le fichier ".rc" et le header (resource.h). Et voila, nous sommes pres a utiliser notre boite de dialogue. Vous pouvez editer le fichier "resource.h" pour voir ce qu'il contient effectivement.
Nous allons maintenant afficher notre boite de dialogue grace a la fonction DialogBox().
Voici un petit programme qui affiche une boite de dialogue, il ne contient rien de bien
compliqué qui n'a pas deja ete explique :
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
HINSTANCE g_hInst;
#include "resource.h"
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
g_hInst = hInstance;
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,NULL);
return(0);
}
Premiere chose qu'on remarque c'est qu'il n'y a pas de boucle de recuperation des messages
a mettre en place avec cette fonction. Cette fonction est en effet bloquante (c'est a dire
en tres gros qu'elle va attendre qu'on lui demande explicitement de sortir grace a un message
adéquat ) et dispose en interne de sa propre boucle de récupération et répartition des messages.
En lancant ce programme, vous allez obtenir une boite de dialogue qui ne fait rien, rien du tout, et qui, en plus,
ne peut pas etre quittée. La raison en est simple n'avons rien specifié quant aux actions
a prendre lorsque l'utilisateur interagit avec la boite de dialogue. Juste une petite remarque
concernant la macro MAKEINTRESOURCE() : dans un grand nombre de fonctions du SDK Win32,
les ressources sont designées a travers une chaine de caracteres. Ainsi la fonction DialogBox
prend en deuxieme parametre une variable de type LPCSTR, ce qui correspond (si on se rappel de
la notation hongroise du chapitre 1) a un pointeur sur une chaine de caracteres, or l'editeur de
VC++ ne nous permet de designer une resource que par une ID qui correspond au niveau code
a un #define présent dans le header "resource.h" cree par VC++, il faut donc un outil nous
permettant de faire une correspondance "bijective" :), entre une ID de type numérique et une
chaine de caractere qui réfere directement au controle/a la resource. Cette correspondance
est faite grace a la macro MAKEINTRESOURCE() qui prend un "parametre" de type entier et qui
renvoi une chaine de caractere. Voila, voila.
La maniere de spécifier a Windows la maniere de réagir dans le cas d'une action réalisée
par l'utilisateur qui soit en relation avec notre boite de dialogue est du meme type que
pour une fenetre toute simple en ce sens qu'elle fait intervenir une fonction de callback
encore appelé "Dialog Procedure" (DlgProc). Une fois que cette fonction est correctement
formatté, il nous suffit de passer un pointeur dessus grace au dernier parametre
de la fonction DialogBox (que nous avons precedement mis a NULL). Le prototype de la fonction
de callback doit etre le suivant :
BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
La fonction recoit donc en parametre :
BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) { switch(uMsg) { case WM_COMMAND: { switch(LOWORD(wParam)) { case IDC_CANCEL: { EndDialog(hwndDlg, 0); return TRUE; break; } case IDC_OK: { EndDialog(hwndDlg,0); return TRUE; break; } } } default: break; } return FALSE; }Attention !!!! Il faut bien respecter les "return FALSE" et "return TRUE". Lorsqu'un message est traité par la DialogProc, elle doit renvoyer TRUE et FALSE dans le cas contraire. De plus, vous pouvez remarquer que pour une boite de dialogue, il n'y a pas d'appel a la fonction DefWindowProc() comme pour une fenetre, ceci est du au fait que chaque boite de dialogue dispose automatiquement en interne de sa propre DlgProc par defaut pour une certain nombre de messages (du type WM_MOVE (dans le cas ou la dlg box bouge), ...). Vous pouvez facilement le constater en revenant a la version précedente de l'appel a la fonction DialogBox :
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,NULL);De plus, il va vous falloir modifier les proprieter de la boite de dialogue dans l'editeur de resource de VC++, pour y rajouter les caracteristiques MinimizeBox/MaximizeBox et Border->Resizing comme suit :
Bon ben vous voila pres a tripoter un peu les controles et les boites de dialogues.
3.4. Les controles.
Maintenant que nous avons vu un peu la maniere dont nous pouvons afficher/appeler une boite de dialogue,
nous allons regarder un peu quelques controle parmi les plus evident a apprehender.
Les boutons sont un des types de controle les plus courant et les plus facile a manipuler dans un
premier temps. Nous avons deja vu comment savoir si l'utilisateur avait appuye sur un bouton.
J'aimerais preciser deux petites choses et vous en saurez suffisament pour les utiliser. La premiere
concerne le texte qui est affiche dans le controle et qui est cense informer l'utilisateur de
la fonctionnalite du bouton, vous pouvez aisement le changer grace a la fonction SetWindowText().
Et oui, une boite de dialogue n'est qu'une fenetre spécialisée et il en va de meme pour
ses controles. Voici le prototype de la fonction en question :
BOOL SetWindowText(HWND hwnd, LPCTSTR lpString);
Le premier argument est le handle de la fenetre dont on veut changer le texte. On peut recuperer
ce handle grace a un autre fonction GetDlgItem() qui renvoi une valeur de type HWND si on lui
donne le handle de la boite de dialogue ainsi que l'ID du controle en question. Voici un exemple
d'utilisation de ces deux fonctions :
SetWindowText( GetDlgItem(hMaDlg, IDOK), "Mon nouveau texte");
Une edit box est un controle contenant du texte pouvant etre modifie par l'utilisateur (dans
la plupart du cas). En voici un exemple :
LRESULT SendMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT PostMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);Je crois que la je dois pouvoir me passer d'expliquer les differents parametres des deux fonctions vu qu'on les a deja rencontrés precedement. Revenons a nos moutons. Pour lire le message contenu dans une edit box il faut lui envoyer un message de type WM_GETTEXT en lui fournissant dans lParam un pointeur sur un buffer ou Windows va placer le texte contenu dans l'edit box et dans wParam le nombre de bytes maximum que le message peut avoir (= le nombre de bytes du tableau ). Voici un exemple d'utilisation :
BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) { switch(uMsg) { case WM_INITDIALOG: SetWindowText(GetDlgItem(hwndDlg, IDOK), "Test"); return TRUE; break; case WM_COMMAND: { switch(LOWORD(wParam)) { case IDC_CANCEL: { EndDialog(hwndDlg, 0); return TRUE; break; } case IDC_OK: { EndDialog(hwndDlg,0); return TRUE; break; } } } default: break; } return FALSE; }Dans cet exemple, nous ecrivons le texte "Test" dans le bouton dont l'ID correspond a IDOK. Si ce bouton contenait un texte "OK", il contient maintenant un texte "Test" sans que l'utilisateur n'en voit rien.
Voila pour cette premiere partie sur les boites de dialogue. La prochaine fois, dans la deuxieme
partie, j'ai decidé de passer en revu un certain nombre de controles/trucs plus ou moins abordables
qui pourront etre utile pour grandement ameliorer vos boites de dialogue, en vrac : les ToolTips,
les ComboBox/ListBox, les SplitterBar, les barres de progression, les check box, les TreeView,
les menus.
Je donnerais les informations de maniere brute sans trop d'exemple. La raison en est simple,
je prevois de faire une derniere partie sur les boites de dialogue uniquement concernant la
programmation d'un petit utilitaire a nous mettant en pratique tous ces controles et toutes
nos connaissances sur la programmation Windows. Ca vous permettra d'avoir un exemple de la maniere dont
toutes ces choses peuvent marcher en pratique et de voir quelques nouvelles choses.
En attendant, jouez avec l'exemple et matez un peu MSDN car c'est la qu'on apprend !
N'hesitez pas a m'envoyer quelques emails pour me dire ce que vous pensez de ces tutoriaux pour
me donner des idées de sujets ou pour n'importe quoi d'autre.
A++.
Deuxieme_Projet_Chap3.zip
--
Document ecrit par ABREU Alexandre : wiss1976@yahoo.fr
Libre reproduction et diffusion autorisée - modifications interdites sans autorisation de l'auteur.
Précédent Suivant