Le contrôle Toolbar.

Le contrôle Toolbar.

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction :

Nous allons aborder un autre contrôle de la "Common control library" : Le contrôle Toolbar.

Pour cet exemple on reprendra l'exemple "Communiquer avec les boîtes de dialogue". On lui ajoutera une Toolbar avec 3 boutons. Dans cet exemple les boutons auront des grandes images et un texte, la Toolbar aura le style flat.

Image non disponible

I-A. Mise en oeuvre :

Le contrôle Toolbar se construit traditionnellement avec la fonction CreateWindow ou CreateWindowEx.

 
Sélectionnez
1.
2.
3.
             htb = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
                                  WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT,
                                           0, 0, 0, 0, hwnd, NULL, hinst, NULL);

La Toolbar possède sa propre liste d'images. Nous devons juste la remplir. Pour cela on utilise une structure TBADDBITMAP avec son champ hInst initialisé avec le handle d'instance du fichier contenant les images et son champ nID avec l'identificateur de la ressource image. Dans notre exemple nous nous faciliterons la tâche en prenant des images standard de Windows (champ hInst à HINST_COMMCTRL et champ nID à IDB_STD_LARGE_COLOR pour de grande images). Ensuite on envoie le message TB_ADDBITMAP à la Toolbar avec l'adresse de la structure comme paramètre.

 
Sélectionnez
1.
2.
3.
4.
5.
             TBADDBITMAP tbab;
          
             tbab.hInst =  HINST_COMMCTRL ;
             tbab.nID   =  IDB_STD_LARGE_COLOR;
             SendMessage(htb, TB_ADDBITMAP, 1, (WPARAM)&tbab);

Ensuite il faut ajouter les boutons à la Toolbar. Pour cela nous devons tout d'abord remplir un tableau de structure TBBUTTON. Chaque élément du tableau correspond à un bouton. Le champ iBitmap de la structure reçoit l'indice de l'image, Le champ idCommand reçoit l'identificateur de la commande. Ce peut être la même que celle d'une option de menu. Ce sera d'ailleurs le cas dans l'exemple. Le champ fsState reçoit l'état du bouton. Le champ fsStyle reçoit le style du bouton. Le troisième bouton dans l'exemple à le style TBSTYLE_SEP car c'est un séparateur. Le champ iString reçoit l'indice de la chaîne de caractères qui correspond au bouton. Elle doit être préalablement chargée dans la liste de chaîne de la Toolbar en lui envoyant un message TB_ADDSTRING.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
             TBBUTTON tbb[4];

             tbb[0].iBitmap = STD_FILENEW;
             tbb[0].idCommand = IDM_NEW;
             tbb[0].fsState = TBSTATE_ENABLED;
             tbb[0].fsStyle = TBSTYLE_BUTTON;
             tbb[0].dwData = 0;
             tbb[0].iString = SendMessage(htb, TB_ADDSTRING, 0,
                                                             (LPARAM)"Nouveau");
             tbb[1].iBitmap = STD_PROPERTIES;
             tbb[1].idCommand = IDM_PARAM;
             tbb[1].fsState = TBSTATE_ENABLED;
             tbb[1].fsStyle = TBSTYLE_BUTTON;
             tbb[1].dwData = 0;
             tbb[1].iString = SendMessage(htb, TB_ADDSTRING, 0,
                                                           (LPARAM)"Paramètre");
             tbb[2].iBitmap = 0;
             tbb[2].idCommand = -1;
             tbb[2].fsState = 0;
             tbb[2].fsStyle = TBSTYLE_SEP;
             tbb[2].dwData = 0;
             tbb[2].iString = -1;             
             
             tbb[3].iBitmap = STD_HELP;
             tbb[3].idCommand = IDM_ABOUT;
             tbb[3].fsState = TBSTATE_ENABLED;
             tbb[3].fsStyle = TBSTYLE_BUTTON;
             tbb[3].dwData = 0;
             tbb[3].iString = SendMessage(htb, TB_ADDSTRING, 0,
                                                            (LPARAM)"A propos");
             SendMessage(htb, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
             SendMessage(htb, TB_ADDBUTTONS, 4, (LPARAM)&tbb);
             SendMessage(htb, TB_AUTOSIZE, 0, 0);

Quand le tableau est rempli, il faut ajouter les boutons à la Toolbar en lui envoyant un message TB_ADDBUTTONS avec l'adresse du tableau comme paramètre. Avant d'envoyer ce message il est important d'envoyer la taille de la structure TBBUTTON à la Toolbar en lui envoyant un message TB_BUTTONSTRUCTSIZE. Pour adapter la taille de la Toolbar à celle des boutons on lui envoie un message TB_AUTOSIZE. Pour voir toutes les possibilités de la Toolbar, je vous propose de consulter l'aide API Win32.

II. Code complet :

II-A. resource.h :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
#define IDM_QUIT  1
define IDM_NEW   2
#define IDM_ABOUT 3
#define IDM_PARAM 4

#define IDE_EDIT1 101

II-B. resource.rc :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
#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 "&Paramètres...", IDM_PARAM
       MENUITEM SEPARATOR
       MENUITEM "Quitter\tAlt+F4", IDM_QUIT
    END
  POPUP "Aide"
    BEGIN
       MENUITEM "A propos...", IDM_ABOUT
    END
END

DIALOG2 DIALOG
    60, 60, 182, 70
          STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
                                                         CAPTION "Paramètres"
BEGIN
    DEFPUSHBUTTON "OK", IDOK, 36, 42, 42, 12
    PUSHBUTTON "Cancel", IDCANCEL, 96, 42, 42, 12
    EDITTEXT IDE_EDIT1, 88, 15, 74, 12
    LTEXT "Titre de la fenêtre", -1, 24, 18, 60, 10
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

II-C. winmain.c :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
#include <windows.h>
#include <commctrl.h>   

#include "resource.h"

HINSTANCE hinst;

LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
BOOL APIENTRY Dialog1Proc(HWND, UINT, WPARAM, LPARAM);
BOOL APIENTRY Dialog2Proc(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 HWND htb;

    static BOOL EditNotChg = TRUE;
    switch (uMsg)
    {
        case WM_CREATE:
            {
             TBADDBITMAP tbab;
             TBBUTTON tbb[4];

             HFONT hFont;
             hEdit = CreateWindowEx(WS_EX_CLIENTEDGE ,"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));

             InitCommonControls();

             htb = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
                                  WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT,
                                           0, 0, 0, 0, hwnd, NULL, hinst, NULL);
          
             tbab.hInst =  HINST_COMMCTRL ;
             tbab.nID   =  IDB_STD_LARGE_COLOR;
             SendMessage(htb, TB_ADDBITMAP, 1, (WPARAM)&tbab);

             tbb[0].iBitmap = STD_FILENEW;
             tbb[0].idCommand = IDM_NEW;
             tbb[0].fsState = TBSTATE_ENABLED;
             tbb[0].fsStyle = TBSTYLE_BUTTON;
             tbb[0].dwData = 0;
             tbb[0].iString = SendMessage(htb, TB_ADDSTRING, 0,
                                                             (LPARAM)"Nouveau");
             tbb[1].iBitmap = STD_PROPERTIES;
             tbb[1].idCommand = IDM_PARAM;
             tbb[1].fsState = TBSTATE_ENABLED;
             tbb[1].fsStyle = TBSTYLE_BUTTON;
             tbb[1].dwData = 0;
             tbb[1].iString = SendMessage(htb, TB_ADDSTRING, 0,
                                                           (LPARAM)"Paramètre");
             tbb[2].iBitmap = 0;
             tbb[2].idCommand = -1;
             tbb[2].fsState = 0;
             tbb[2].fsStyle = TBSTYLE_SEP;
             tbb[2].dwData = 0;
             tbb[2].iString = -1;  
             
             tbb[3].iBitmap = STD_HELP;
             tbb[3].idCommand = IDM_ABOUT;
             tbb[3].fsState = TBSTATE_ENABLED;
             tbb[3].fsStyle = TBSTYLE_BUTTON;
             tbb[3].dwData = 0;
             tbb[3].iString = SendMessage(htb, TB_ADDSTRING, 0,
                                                            (LPARAM)"A propos");
             
             SendMessage(htb, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
             SendMessage(htb, TB_ADDBUTTONS, 4, (LPARAM)&tbb);
             SendMessage(htb, TB_AUTOSIZE, 0, 0);
             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,(LPARAM)"");
                              EditNotChg = TRUE;
                      }
            if(LOWORD(wParam) == IDM_ABOUT)
                       DialogBox(hinst, "DIALOG1" , hwnd, (DLGPROC)Dialog1Proc);
            if(LOWORD(wParam) == IDM_PARAM)
                       DialogBoxParam(hinst, "DIALOG2" , hwnd,
                                            (DLGPROC)Dialog2Proc, (LPARAM)hwnd);
            if(HIWORD(wParam) == EN_CHANGE) EditNotChg = FALSE;

            return 0;

        case WM_SIZE:
             {
              RECT sbRect;
              UINT  tbheight;
              GetWindowRect(htb, &sbRect);
              tbheight = sbRect.bottom - sbRect.top;
              MoveWindow(htb, 0, 0, LOWORD(lParam), tbheight, TRUE);
              MoveWindow(hEdit, 0, tbheight, LOWORD(lParam),
                                                 HIWORD(lParam)-tbheight, 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;
    }
}
/******************************************************************************/

BOOL APIENTRY Dialog2Proc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    static HWND hParent;
    switch (uMsg)
    {
      case WM_INITDIALOG:
          {
            int WindowTextLength;
            CHAR *buffer;
            hParent = (HWND)lParam;
            WindowTextLength = GetWindowTextLength(hParent);
            buffer = (CHAR*)LocalAlloc(LMEM_FIXED, WindowTextLength+1);
            GetWindowText(hParent, buffer, WindowTextLength+1);
            SetDlgItemText(hDlg, IDE_EDIT1, buffer);
            LocalFree(buffer);
          }
         return TRUE;

      case WM_COMMAND:
         if (LOWORD(wParam) == IDOK )
                {
                   CHAR st[128];
                   GetDlgItemText(hDlg, IDE_EDIT1, st, 128);
                   SetWindowText(hParent,st);
                   EndDialog(hDlg,0);
                   return TRUE;
                }
         if (LOWORD(wParam) == IDCANCEL )
                {
                   EndDialog(hDlg,0);
                   return TRUE;
                }
      default:
         return FALSE;
    }
}

J'ai testé les compilations avec C++ Builder et DevC++.
La constante de style flat (TBSTYLE_FLAT) de la Toolbar n'est pas défini dans le fichier commctrl.h avec la version de Dev-C++ en ma possession. J'ai donc du la remplacer par sa valeur (0x0800) :

 
Sélectionnez
1.
2.
3.
             htb = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
                                  WS_CHILD | WS_VISIBLE | 0x0800,
                                           0, 0, 0, 0, hwnd, NULL, hinst, NULL);

III. Utilisation d'images personnelles :

Dans l'exemple précédent nous avons utilisée des images du système. Nous allons brièvement voir comment utiliser des images personnelles. Il faut remplir une structure de type TBADDBITMAP : le champ hInst avec le handle d'instance du module contenant les images et le champ nID avec l'identificateur de la ressource image. Ensuite il suffit d'ajouter les images en envoyant le message TB_ADDBITMAP à la toolbar. Le champ iBitmap des structures TBBUTTON devra être rempli avec l'indice de l'image.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
             TBADDBITMAP tbab;

             /* ... */

             tbab.hInst = hinst;
             tbab.nID = IDB_IMG;
             SendMessage(htb, TB_ADDBITMAP, 4, (WPARAM)&tbab);      

             tbb[0].iBitmap = 5;
             /* ... */

Plus récement a été apporté une autre solution qui a l'avantage de pouvoir utiliser des images 32 bits. C'est d'utiliser une Listes d'images que l'on ajoutera à la toolbar.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
             HIMAGELIST himgList;

             /* ... */

             himgList = ImageList_Create(24, 24, ILC_MASK |ILC_COLOR32 , 0, 6);
             ImageList_AddMasked(himgList,
                        LoadBitmap(hinst,MAKEINTRESOURCE(IDB_IMG)), 0x00FF00FF);
             SendMessage(htb, TB_SETIMAGELIST , 0, (LPARAM)himgList);

             tbb[0].iBitmap = 5;
             /* ... */

Le message TB_SETIMAGELIST n'est pas défini dans le fichier commctrl.h avec la version de Dev-C++ en ma possession. J'ai donc du définir ce message pour l'utiliser.

 
Sélectionnez
1.
#define TB_SETIMAGELIST (WM_USER + 48)

A vos PC.

CGi

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

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.
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.
  

Copyright © 2005 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.