Developpez.com - C
X

Choisissez d'abord la catégorieensuite la rubrique :



API Windows en C

8 - Les boîtes de dialogue personnalisées.

Par CGi

Le 16 juin 2005




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.



Sommaire



C/C++
  Les pointeurs du C/C++.   Les listes chaînées.             Liste simple.             Liste triée.             Liste double.   Les arbres.   Les tas.   Le C orienté objets ?

  1 - La fenêtre principale.   2 - Contrôles et messages.   3 - Les commandes.   4 - Dialogue std.   5 - Contexte de périph.   6 - Dessiner.   7 - Les ressources.   8 - Dialogue perso.   9 - Dialogue comm.   10 - Les accélérateurs.

Assembleur
  Assembleur sous Visual C++.

C++ BUILDER
  Trucs et astuces.   Composant.   TRichEdit.   TDrawGrid.   Application MDI.   TThread.   wxWidgets.   Style Win XP.

  Première application.   Construire un menu.   Dessiner.   Sisers, Timers...   Dialogues standards.   Dialogues perso.

DotNet
  Composant C# Builder.   Contrôle WinForm.   Application MDI.

Java
  Applet java.





Copyright 2002-2016 CGi - Tous droits réservés CGi. Toutes reproduction, utilisation ou diffusion de ce document par quelque moyen que ce soit autre que pour un usage personnel doit faire l'objet d'une autorisation écrite de la part de l'auteur, propriétaire des droits intellectuels.
Les codes sources de ce document sont fournis en l'état. L'utilisateur les utilise à ses risques et périls, sans garantie d'aucune sorte de la part de l'auteur. L'auteur n'est responsable d'aucun dommage subi par l'utilisateur pouvant résulter de l'utilisation ou de la distribution des codes sources de ce document.
De la même façon, l'auteur n'est en aucun cas responsable d'une quelconque perte de revenus ou de profits, ou de données, ou de tous dommages directs ou indirects, susceptibles de survenir du fait de l'utilisation des codes sources de ce document, quand bien même l'auteur aurait été averti de la possibilité de tels dommages. L'utilisation des codes sources de ce document vaut acceptation par l'utilisateur des termes de la licence ci-dessus.

Contacter le responsable de la rubrique C