La programmation de l'interface utilisateur
Date de publication : 22 mai 2008. Date de mise à jour : 23 mars 2009.
II. Les boîtes de dialogue
II-A. Introduction
II-B. Deux types de boîte de dialogue
II-C. Traitement
II-D. Création
II-E. Une boîte de dialogue comme fenêtre principale
II-F. Les boîtes de dialogue communes
II. Les boîtes de dialogue
II-A. Introduction
Une boîte de dialogue est une fenêtre, généralement temporaire, qui contient normalement un
ou plusieurs contrôles permettant à l'utilisateur d'entrer des informations pour le programme.
Cependant, au niveau de la programmation, les boîtes de dialogue ne s'utilisent pas tout à fait
de la même façon que les fenêtres « normales » (bien qu'elles soient également des fenêtres)
en raison justement de leur caractère temporaire (mais bien entendu, rien ne vous empêche
d'avoir une boîte de dialogue comme fenêtre principale).
II-B. Deux types de boîte de dialogue
Une boîte de dialogue peut être créée avec DialogBox ou CreateDialog (qui sont en fait des
macros qui utilisent CreateWindowEx en passant bien sûr les bons paramètres). La première
crée une boîte de dialogue modale et la seconde une boîte de dialogue non modale. Une boîte
de dialogue modale suspend le travail de sa fenêtre parent jusqu'à ce que l'utilisateur en a
terminé avec. Une boîte de dialogue non modale est une fenêtre qui attend des informations
venant de l'utilisateur sans suspendre le travail des autres fenêtres. Je ne vous apprends donc
rien, puisque vous l'avez certainement deviné, en affirmant que DialogBox attend que
l'utilisateur en ait fini avec la fenêtre (la boîte de dialogue) avant de retourner tandis que CreateDialog retourne
immédiatement après l'appel.
Il faut également savoir qu'une boîte de dialogue modale sera toujours affichée par Windows
que le style WS_VISIBLE ait été spécifié ou non. Par contre Windows n'affiche pas
automatiquement une boîte de dialogue non modale (il faut donc avoir spécifié ou alors
appeler la fonction ShowWindow).
La plupart du temps, une boîte de dialogue possède une fenêtre parent. Sauf dans le cas où la
elle est utilisée comme fenêtre principale de l'application, il est en fortement conseillé de
toujours spécifier une fenêtre parent lors de sa création. En effet, lorsqu'on ne spécifie aucun
parent, la boîte de dialogue devient complètement autonome ce qui va évidemment compliquer sa gestion.
II-C. Traitement
La boîte de dialogue doit tout d'abord être décrite (par exemple en ressource) puis créée à
l'aide de DialogBox ou CreateDialog.
INT_PTR DialogBox (HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWnd, DLGPROC lpDialogProc);
|
Où lpTemplate est le nom de la boîte de dialogue qu'on veut afficher et lpDialogProc
l'adresse d'une fonction qui sera la procédure de traitement des messages.
INT_PTR CALLBACK DialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
Cette procédure doit retourner TRUE si le message a été traité, FALSE dans le cas contraire
(sachez également que, dans les anciennes versions du SDK Windows, cette fonction ne
retournait pas un INT_PTR mais BOOL). Donc si FALSE est retourné, Windows va effectuer
le traitement par défaut. On n'a donc plus besoin de DefWindowProc. Et enfin, sachez
qu'avec les boîtes de dialogue, le message WM_CREATE est remplacé par le message
WM_INITDIALOG. Si l'on souhaite passer des paramètres à travers ce message, On
utilisera DialogBoxParam ou CreateDialogParam à la place de DialogBox ou CreateDialog.
INT_PTR DialogBoxParam ( HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWnd,
DLGPROC lpDialogProc, LPARAM dwInitParam );
|
II-D. Création
Nous allons maintenant voir comment créer un modèle (ou template) de boîte de dialogue
(autrement dit : une boîte de dialogue !) en ressource. Là encore, comme vous pouvez le
constater, les éditeurs de ressources sont plus que jamais d'une aide précieuse mais ici nous
allons quand même taper le code nous-mêmes.
# include <windows.h>
MyDialog DIALOGEX 0 , 0 , 100 , 50
STYLE DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION " Ma boîte de dialogue "
{
CTEXT " Hello, world ! " , - 1 , 0 , 8 , 100 , 12
DEFPUSHBUTTON " OK " , IDOK, 25 , 24 , 50 , 14
}
|
DIALOGEX est une amélioration de DIALOG (que pouvez toutefois continuer
à utiliser, mais cela est-il justifié ?)
_name DIALOGEX _x, _y, _width, _height
STYLE _style
CAPTION _caption
FONT _pointsize, _facename, _weight, _italic, _charset
MENU _idmenu
{
_content
}
|
Pour les contrôles, la syntaxe est :
< TYPE DU CONTROLE> _text, _id, _x, _y, _width, _height, _style, _exstyle
|
Où le type du contrôle peut être LTEXT, RTEXT, CTEXT (contrôles Static), PUSHBUTTON,
DEFPUSHBUTTON, RADIOBUTTON, AUTORADIOBUTTON, CHECKBOX, AUTOCHECKBOX, STATE3, AUTO3STATE,
PUSHBOX, GROUPBOX, EDITTEXT, LISTBOX, COMBOXBOX ou SCROLLBAR. Bien entendu, ces contrôles
s'utilisent de la même façon que les contrôles créés dynamiquement.
On peut également créer un contrôle avec le mot-clé générique CONTROL :
CONTROL _text, _id, _classname, _x, _y, _width, _height, _style, _exstyle
|
Attention ! L'unité utilisée dans les boîtes de dialogue n'est pas le pixel mais les Dialog
Template Units. Ce ne sont pas des unités fixes. L'interêt d'utiliser de telles unités est de
pouvoir créer des boîtes de dialogue ayant la même proportion indépendamment de la résolution
de l'écran. Alors juste pour info, on appelle Dialog Base Units d'une boîte de dialogue
la largeur et la hauteur moyennes des caractères dans la police utilisée. Si la boîte de dialogue
utilise la police système, on peut récupérer leurs équivalents en pixels à l'aide de la fonction
GetDialogBaseUnits. Sinon, un autre moyen très simple de les récupérer est d'utiliser la
fonction GetTextEntentPoint32 sachant qu'on appelle largeur moyenne des caractères dans une
police donnée la largeur du caractère x. Si on connaît les Dialog Base Units, on peut directement
convertir les Dialog Template Units en pixels sachant que :
1 XDialogTemplateUnit = 1 / 4 (XDialogBaseUnit)
1 YDialogTemplateUnit = 1 / 8 (YDialogBaseUnit)
|
En réalité, pour convertir les Dialog Template Units en pixels, on utilisera tout simplement
la fonction MapDialogRect.
II-E. Une boîte de dialogue comme fenêtre principale
Nous allons enfin voir un exemple qui affiche une boîte de dialogue comme fenêtre
principale. Voici donc le code :
include < windows.h>
INT_PTR CALLBACK DialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
DialogBox (hInstance, " MyDialog " , NULL , DialogProc);
return 0 ;
}
INT_PTR CALLBACK DialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
break ;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDOK:
SendMessage (hwnd, WM_CLOSE, 0 , 0 );
break ;
}
break ;
case WM_CLOSE:
EndDialog (hwnd, 0 );
break ;
default :
return FALSE;
}
return TRUE;
}
|
La fonction EndDialog permet de détruire une boîte de dialogue modale. La valeur passée en
dernier paramètre sera utilisée par DialogBox comme valeur de retour. Dans le cas d'une
boîte de dialogue non modale, on utilise plutôt la fonction DestroyWindow (en fait, EndDialog utilise
en interne DestroyWindow mais après avoir recupéré la valeur que DialogBox doit retourner).
II-F. Les boîtes de dialogue communes
Dans les paragraphes précédents nous avons appris à utiliser des boîtes de dialogue que nous
avons nous-mêmes créées. Ici ce qui nous intéressera ce sont les boîtes de dialogue
communes, c'est-à-dire celles qui sont fournies par Windows. Il s'agit des boîtes de dialogue
Ouvrir, Enregistrer (Enregistrer sous), Imprimer, etc. En particulier, sachez que le boîtes de
dialogue Ouvrir et Enregistrer sous sont en fait les mêmes (ou presque) ! Pour afficher la boîte
de dialogue (Ouvrir ou Enregistrer sous), on initialise une structure de type OPENFILENAME
qui décrit la boîte que l'on veut afficher ensuite on appelle GetOpenFileName pour afficher
la boîte de dialogue Ouvrir et GetSaveFileName pour afficher la boîte de dialogue Enregistrer
sous (ces boîtes de dialogue ont la même apparence, la seule véritable différence vient du texte du bouton
par défaut qui est Ouvrir pour la boîte de dialogue Ouvrir et Enregistrer pour la boîte de dialogue
Enregistrer sous), et c'est aussi simple que cela ! Par exemple :
OPENFILENAME ofn;
char lpszFile[MAX_PATH] = " " ;
char lpszFileTitle[MAX_PATH] = " " ;
ZeroMemory (& ofn, sizeof (ofn));
ofn.lStructSize = sizeof (OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = " Texte (*.txt)\0*.txt\0Tous (*.*)\0*.*\0 " ;
ofn.lpstrFile = lpszFile;
ofn.nMaxFile = sizeof (lpszFile) / sizeof (lpszFile[0 ]);
ofn.lpstrFileTitle = lpszFileTitle;
ofn.nMaxFileTitle = sizeof (lpszFileTitle) / sizeof (lpszFileTitle[0 ]);
ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_CREATEPROMPT;
if (GetOpenFileName (& ofn))
MessageBox (hwnd, lpszFile, lpszFileTitle, MB_OK);
else
MessageBox (hwnd, " Opération annulée " , " GetOpenFileName " , MB_OK);
|
Sachez cependant que OPENFILENAME est une structure particulièrement riche et que nous
n'avons ici utilisé que quelques uns de ses champs seulement. Elle est définie dans commdlg.h
(inclus par windows.h) de la manière suivante :
typedef struct tagOFN {
DWORD lStructSize;
HWND hwndOwner;
HINSTANCE hInstance;
LPCTSTR lpstrFilter;
LPTSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPTSTR lpstrFile;
DWORD nMaxFile;
LPTSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCTSTR lpstrInitialDir;
LPCTSTR lpstrTitle;
DWORD Flags;
WORD nFileOffset;
WORD nFileExtension;
LPCTSTR lpstrDefExt;
LPARAM lCustData;
LPOFNHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
# if ( _WIN32_WINNT > = 0x0500 )
void * pvReserved;
DWORD dwReserved;
DWORD FlagsEx;
# endif
} OPENFILENAME, * LPOPENFILENAME;
|
Voici une liste des flags les plus courants :
OFN_ALLOWMULTISELECT : Autorise la sélection multiple.
OFN_CREATEPROMPT : Indique que l'utilisateur peut entrer un nom de fichier qui
n'existe pas et dans ce cas il sera invité à confirmer son choix.
OFN_EXPLORER : Impose le style Explorer. En fait ce style est appliqué par défaut
mais il est parfois annulé par certains flags. Ce flag permet de toujours utiliser le style
Explorer.
OFN_FILEMUSTEXIST : Utilisable uniquement dans une boîte de dialogue Ouvrir. Permet de
spécifier que l'utilisateur doit entrer un nom de fichier existant. Inclut le flag
OFN_PATHMUSTEXIST.
OFN_FORCESHOWHIDDEN : Windows 2000 et plus récents uniquement. Affiche les dossiers et
fichiers cachés et/ou systèmes, indépendamment des préférences de l'utilisateur.
OFN_HIDEREADONLY : N'a de sens que dans une boîte de dialogue Ouvrir. Cache l'option
« ouvrir en lecture seulement ».
OFN_NODEREFERENCELINKS : Par défaut, si l'utilisateur sélectionne un raccourci (.lnk),
le champ lpstrFile contient le chemin vers le fichier pointé par le lien. Le flag
OFN_NODEREFERENCELINKS permet de spécifier que l'on désire dans un tel cas avoir le nom du lien
et non celui du fichier pointé.
OFN_OVERWRITEPROMPT : Dans une boîte de dialogue Enregistrer sous, provoque une demande de
confirmation si l'utilisateur sélectionne un nom de fichier existant.
OFN_PATHMUSTEXIST : Spécifie que l'utilisateur doit utiliser des caractères valides uniquement.
OFN_READONLY : N'a de sens que dans une boîte de dialogue Ouvrir. Coche l'option « ouvrir en
lecture seulement ». Au retour de la fonction, ce flag indique l'état de ladite option.
Les sources présentées sur cette page sont libres de droits
et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation
constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ©
2008 Melem. Aucune reproduction, même partielle, ne peut être faite
de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et
jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.