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.
Mise en oeuvre :
Le contrôle Toolbar se construit traditionnellement avec la fonction
CreateWindow ou CreateWindowEx.
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.
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.
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.
Code complet :
resource.h :
#define IDM_QUIT 1
#define IDM_NEW 2
#define IDM_ABOUT 3
#define IDM_PARAM 4
#define IDE_EDIT1 101
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 "&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
winmain.c :
#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) :
htb = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE | 0x0800,
0, 0, 0, 0, hwnd, NULL, hinst, NULL);
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.
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.
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.
#define TB_SETIMAGELIST (WM_USER + 48)
A vos PC.
CGi
|