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 "A propos..."
par une boîte de dialogue personnalisée contenant un bouton, une icône et
un texte.
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), suivie
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 pixel, mais
dépendent de la police de caractères utilisée).
L'icône et le le contrôle texte ont un identificateur à -1 car il 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.
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);
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 soit 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'elle soit visible. 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.
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\nEtes 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\nEtes 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.
A vos PC.
CGi
Avec la contribution de nico-pyright(c) et pharaonix pour la relecture.
|