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 trois boutons. Dans cet exemple les boutons auront des grandes images et un texte, la Toolbar aura le style flat.
I-A. Mise en œuvre▲
Le contrôle Toolbar se construit traditionnellement avec la fonction CreateWindow ou CreateWindowEx.
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 grandes images. Ensuite on envoie le message TB_ADDBITMAP à la Toolbar avec l'adresse de la structure comme paramètre.
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 a 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.
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)"
À 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▲
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▲
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
\t
Alt+F4
"
, IDM_QUIT
END
POPUP "
Aide
"
BEGIN
MENUITEM "
À 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 "
À 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▲
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)"
À 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\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 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éfinie dans le fichier commctrl.h avec la version de Dev-C++ en ma possession. J'ai donc dû la remplacer par sa valeur (0x0800) :
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é 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.
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écemment a été apportée une autre solution qui a l'avantage de pouvoir utiliser des images 32 bits. C'est d'utiliser une Liste d'images que l'on ajoutera à la toolbar.
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 dû définir ce message pour l'utiliser.
#define TB_SETIMAGELIST (WM_USER + 48)
À vos PC.