API Windows en C

Les boîtes de dialogue personnalisées

CGI

♪

- Titre : API Windows en C

- Auteur : CGI

- Parution : 16 juin 2005

- Licence : 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 ® 2013 CGi. Aucune reproduction, même partielle, ne peut être faite de ce site et 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.

Sommaire

- I. Introduction

- II. Le script de ressources

- III. Appel de la boîte de dialogue

- IV. Procédure de fenêtre de la boîte de dialogue

- V. Code complet

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

Sommaire