I. Introduction▲
Dans ce chapitre nous allons voir comment créer et appeler une boîte de dialogue personnalisée. Nous continuerons avec l'exemple du chapitre précédent. Nous remplacerons la boîte de message appelée par le menu "À propos…" par une boîte de dialogue personnalisée contenant un bouton, une icône et un texte.
II. Le script de ressources▲
Les boîtes de dialogue personnalisées sont créées à partir de ressources :
DIALOG1 DIALOG
60
, 60
, 160
, 80
STYLE WS_POPUP |
WS_VISIBLE |
WS_CAPTION |
WS_SYSMENU
CAPTION "
A propos
"
BEGIN
DEFPUSHBUTTON "
Ok
"
, IDOK, 56
, 50
, 42
, 12
ICON 2
, -
1
, 20
, 15
, 32
, 32
LTEXT "
Mon beau programme !
"
, -
1
, 60
, 18
, 80
, 10
END
La ressource est composée de son identificateur littéral, suivi de son type (DIALOG), suivi de ses propriétés (position, dimensions, style et titre), suivi de son contenu balisé par les mots BEGIN et END. Il est en général constitué de contrôles. Chaque contrôle est décrit par son type, suivi de son identification visuelle (texte pour le bouton et le contrôle texte, identificateur de ressource pour l'icône), suivi de sa constante numérique d'identification, puis de sa position dans la boîte de dialogue et enfin de ses dimensions (les largeurs et hauteurs des contrôles ne sont pas en pixels, mais dépendent de la police de caractères utilisée). L'icône et le contrôle texte ont un identificateur à -1 car ils ne sont là que pour la décoration, mais il faut tout de même leur mettre un identificateur. Celui du bouton est à IDOK que nous n'avons pourtant pas défini. IDOK est défini dans Windows, il est envoyé à la procédure de fenêtre de la boîte de dialogue quand on appuie sur la touche "Entrée". Est défini aussi l'identificateur IDCANCEL qui lui est envoyé quand on appuie sur la touche "Echap" ou que l'on tente de fermer la boîte de dialogue.
III. Appel de la boîte de dialogue▲
La boîte de dialogue étant maintenant dans les ressources, nous pouvons l'appeler afin de l'ouvrir. C'est le rôle de la fonction DialogBox. Son premier paramètre est le handle d'instance de l'application, le second, un pointeur sur la chaîne de caractères identifiant la ressource, le troisième est le handle de la fenêtre parent et le dernier un pointeur sur sa procédure de fenêtre.
switch
(
uMsg)
{
case
WM_COMMAND :
if
(
LOWORD
(
wParam) ==
IDM_ABOUT)
DialogBox
(
hinst, "
DIALOG1
"
, hwnd, (
DLGPROC)Dialog1Proc);
IV. Procédure de fenêtre de la boîte de dialogue▲
Comme pour la procédure de fenêtre de la fenêtre principale c'est à vous de la définir. C'est Windows qui l'appellera quand elle aura un message.
LRESULT CALLBACK Dialog1Proc
(
HWND, UINT, WPARAM, LPARAM);
BOOL APIENTRY Dialog1Proc
(
HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch
(
uMsg)
{
case
WM_INITDIALOG:
return
TRUE;
case
WM_COMMAND :
if
(
LOWORD
(
wParam) ==
IDCANCEL ||
LOWORD
(
wParam) ==
IDOK)
{
EndDialog
(
hDlg,0
);
return
TRUE;
}
default
:
return
FALSE;
}
}
Comme vous pouvez le constater, elle est fort semblable à celle de la fenêtre principale. Si le message est traité, elle doit renvoyer TRUE, sinon elle doit renvoyer FALSE. WM_INITDIALOG doit être intercepté et renvoyer TRUE afin que les commandes IDOK et IDCANCEL soient envoyées lors des appuis sur les touches correspondantes. Le message WM_INITDIALOG est envoyé par Windows après la création de la boîte de dialogue, mais avant qu'elles soient visibles. Ceci afin de permettre d'initialiser les contrôles qu'elle contient.
Dans l'exemple nous interceptons seulement les commandes IDOK et IDCANCEL afin de la fermer par l'appel de la fonction EndDialog.
V. Code complet▲
resource.h :
#define IDM_QUIT 1
#define IDM_NEW 2
#define IDM_ABOUT 3
resource.rc :
#include <windows.h>
#include "resource.h"
1
ICON icone.ico
2
ICON autre.ico
LEMENU MENU
BEGIN
POPUP "
Fichier
"
BEGIN
MENUITEM "
Nouveau
"
, IDM_NEW
MENUITEM SEPARATOR
MENUITEM "
Quitter
"
, IDM_QUIT
END
POPUP "
Aide
"
BEGIN
MENUITEM "
A propos...
"
, IDM_ABOUT
END
END
DIALOG1 DIALOG
60
, 60
, 160
, 80
STYLE WS_POPUP |
WS_VISIBLE |
WS_CAPTION |
WS_SYSMENU
CAPTION "
A propos
"
BEGIN
DEFPUSHBUTTON "
Ok
"
, IDOK, 56
, 50
, 42
, 12
ICON 2
, -
1
, 20
, 15
, 32
, 32
LTEXT "
Mon beau programme !
"
, -
1
, 60
, 18
, 80
, 10
END
winmain.c :
#include <windows.h>
#include "resource.h"
HINSTANCE hinst;
LRESULT CALLBACK MainWndProc
(
HWND, UINT, WPARAM, LPARAM);
BOOL APIENTRY Dialog1Proc
(
HWND, UINT, WPARAM, LPARAM);
int
WINAPI WinMain
(
HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int
nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS wc;
hinst =
hinstance;
wc.style =
0
;
wc.lpfnWndProc =
MainWndProc;
wc.cbClsExtra =
0
;
wc.cbWndExtra =
0
;
wc.hInstance =
hinstance;
wc.hIcon =
LoadIcon
(
hinstance,MAKEINTRESOURCE
(
2
));
wc.hCursor =
LoadCursor
(
NULL
, IDC_ARROW);
wc.hbrBackground =
NULL
;
wc.lpszMenuName =
"
LEMENU
"
;
wc.lpszClassName =
"
MaWinClass
"
;
if
(!
RegisterClass
(&
wc)) return
FALSE;
hwnd =
CreateWindow
(
"
MaWinClass
"
, "
Titre
"
, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400
, 300
,
NULL
, NULL
, hinstance, NULL
);
if
(!
hwnd) return
FALSE;
ShowWindow
(
hwnd, nCmdShow);
while
(
GetMessage
(&
msg, NULL
, 0
, 0
))
{
TranslateMessage
(&
msg);
DispatchMessage
(&
msg);
}
return
msg.wParam;
}
/**
***************************************************************************
*/
LRESULT CALLBACK MainWndProc
(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static
HWND hEdit;
static
BOOL EditNotChg =
TRUE;
switch
(
uMsg)
{
case
WM_CREATE:
{
HFONT hFont;
hEdit =
CreateWindow
(
"
edit
"
, "
Texte
"
,
WS_CHILD |
WS_VISIBLE |
ES_MULTILINE |
ES_WANTRETURN |
WS_VSCROLL,
0
, 0
, 0
, 0
, hwnd, NULL
, hinst, NULL
);
hFont =
(
HFONT)GetStockObject
(
ANSI_FIXED_FONT);
SendMessage
(
hEdit,WM_SETFONT,(
UINT)hFont,TRUE);
SendMessage
(
hEdit, EM_SETMARGINS, EC_LEFTMARGIN |
EC_RIGHTMARGIN,
MAKELONG
(
5
, 5
));
return
0
;
}
case
WM_CLOSE :
if
(
EditNotChg ||
MessageBox
(
hwnd,"
Le texte a été modifié.
\r\n
Êtes-vous sûr de \
vouloir fermer l'application ?
"
,"
Question ?
"
,MB_YESNO |
MB_ICONQUESTION ) ==
IDYES)
DestroyWindow
(
hwnd);
return
0
;
case
WM_COMMAND :
if
(
LOWORD
(
wParam) ==
IDM_QUIT) PostMessage
(
hwnd, WM_CLOSE,0
,0
);
if
(
LOWORD
(
wParam) ==
IDM_NEW)
if
(
EditNotChg ||
MessageBox
(
hwnd,"
Le texte a été modifié.
\r\n
Êtes-vous sûr de \
vouloir fermer votre travail ?
"
,"
Question ?
"
,MB_YESNO |
MB_ICONQUESTION ) ==
IDYES)
{
SendMessage
(
hEdit,WM_SETTEXT,0
,(
long
)""
);
EditNotChg =
TRUE;
}
if
(
LOWORD
(
wParam) ==
IDM_ABOUT)
DialogBox
(
hinst, "
DIALOG1
"
, hwnd, (
DLGPROC)Dialog1Proc);
if
(
HIWORD
(
wParam) ==
EN_CHANGE) EditNotChg =
FALSE;
return
0
;
case
WM_SIZE :
MoveWindow
(
hEdit, 0
, 0
, LOWORD
(
lParam), HIWORD
(
lParam), TRUE);
return
0
;
case
WM_DESTROY :
PostQuitMessage
(
0
);
return
0
;
default
:
return
DefWindowProc
(
hwnd, uMsg, wParam, lParam);
}
}
/**
***************************************************************************
*/
BOOL APIENTRY Dialog1Proc
(
HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch
(
uMsg)
{
case
WM_INITDIALOG:
return
TRUE;
case
WM_COMMAND :
if
(
LOWORD
(
wParam) ==
IDCANCEL ||
LOWORD
(
wParam) ==
IDOK)
{
EndDialog
(
hDlg,0
);
return
TRUE;
}
default
:
return
FALSE;
}
}
J'ai testé les compilations avec C++ Builder et DevC++. Le compilateur de ressources de DevC++ a été défaillant pour l'affichage de l'icône dans la boîte de dialogue.
À vos PC.
CGi