I. Introduction▲
En annexe au chapitre : « Les boîtes de dialogue communes », voici une mise en application de la boîte de dialogue de choix de couleur.
II. Préparation de l'exemple▲
Sur la base du même exemple. Nous ajoutons une option avec le texte « Couleur du texte… » au sous-menu. L'option « Couleur du texte… » sera identifiée par la constante IDM_TEXTCOLOR :
#define IDM_QUIT 1
#define IDM_OPEN 2
#define IDM_TEXTCOLOR 3
/*... */
hSousMenu =
CreateMenu
(
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_OPEN, "
Ouvrir...
"
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_TEXTCOLOR, "
Couleur du texte...
"
);
AppendMenu
(
hSousMenu, MF_SEPARATOR, 0
, NULL
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_QUIT, "
Quitter
"
);
Nous nous en servirons pour changer la couleur du texte du contrôle d'édition multiligne.
Pour changer cette couleur, nous emploierons la fonction SetTextColor. Elle reçoit comme paramètre un handle de contexte de périphérique et une couleur.
Mais, comment obtenir un contexte de périphérique pour le contrôle d'édition ?
Windows avant d'effectuer le dessin des contrôles envoie un message à sa fenêtre parent : WM_CTLCOLOREDIT pour le contrôle d'édition et y joint son handle de contexte de périphérique (HDC) dans le paramètre wParam et son handle de fenêtre dans le paramètre lParam.
case
WM_CTLCOLOREDIT:
if
((
HWND)lParam ==
hEdit)
{
SetTextColor
((
HDC)wParam, TextColor);
SetBkColor
((
HDC)wParam, BkEditcolor);
return
EditBrush;
}
return
DefWindowProc
(
hwnd, uMsg, wParam, lParam);
Quand on traite ce message, on doit retourner un pinceau. Dans l'exemple si l'on est en train de traiter ce message pour notre contrôle d'édition, nous changeons la couleur de son texte, de son fond et retournons un pinceau de la même couleur que le fond. Ce pinceau ayant été initialisé à la création de la fenêtre principale :
static
HBRUSH EditBrush;
static
COLORREF BkEditcolor;
static
COLORREF TextColor =
0
;
/*... */
case
WM_CREATE:
{
BkEditcolor =
GetSysColor
(
COLOR_WINDOW);
EditBrush =
CreateSolidBrush
(
BkEditcolor);
Si nous ne traitons pas le message WM_CTLCOLOREDIT, c'est DefWindowProc qui met les valeurs par défaut pour le contrôle.
III. La boîte de dialogue de choix couleur▲
Comme toutes les boîtes de dialogue communes, on utilise une structure (CHOOSECOLOR) pour l'initialiser :
static
COLORREF TextColor =
0
;
/*... */
CHOOSECOLOR cc;
static
COLORREF acrCustClr[16
];
ZeroMemory
(&
cc, sizeof
(
CHOOSECOLOR));
cc.lStructSize =
sizeof
(
CHOOSECOLOR);
cc.hwndOwner =
hwnd;
cc.lpCustColors =
NULL
;
cc.lpCustColors =
(
LPDWORD) acrCustClr;
cc.rgbResult =
TextColor;
cc.Flags =
CC_FULLOPEN |
CC_RGBINIT;
Puis on appelle la fonction ChooseColor pour ouvrir la boîte de dialogue :
if
(
ChooseColor
(&
cc)==
TRUE)
{
TextColor =
cc.rgbResult;
PostMessage
(
hEdit,WM_SETREDRAW,TRUE,0
);
}
Elle retourne la couleur choisie dans le champ rgbResult de la variable de type CHOOSECOLOR qu'elle a reçue comme paramètre. Nous nous en servons pour affecter la variable TextColor. La même que l'on avait utilisée pour changer la couleur du contrôle précédemment.
IV. Code complet▲
#include <windows.h>
#define IDM_QUIT 1
#define IDM_OPEN 2
#define IDM_TEXTCOLOR 3
HINSTANCE hinst;
LRESULT CALLBACK MainWndProc
(
HWND, UINT, WPARAM, LPARAM);
int
WINAPI WinMain
(
HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int
nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS wc;
HMENU hMenu, hSousMenu;
hinst =
hinstance;
wc.style =
0
;
wc.lpfnWndProc =
MainWndProc;
wc.cbClsExtra =
0
;
wc.cbWndExtra =
0
;
wc.hInstance =
hinstance;
wc.hIcon =
NULL
;
wc.hCursor =
LoadCursor
(
NULL
, IDC_ARROW);
wc.hbrBackground =
NULL
;
wc.lpszMenuName =
NULL
;
wc.lpszClassName =
"
MaWinClass
"
;
if
(!
RegisterClass
(&
wc)) return
FALSE;
hSousMenu =
CreateMenu
(
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_OPEN, "
Ouvrir...
"
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_TEXTCOLOR, "
Couleur du texte...
"
);
AppendMenu
(
hSousMenu, MF_SEPARATOR, 0
, NULL
);
AppendMenu
(
hSousMenu, MF_STRING, IDM_QUIT, "
Quitter
"
);
hMenu =
CreateMenu
(
);
AppendMenu
(
hMenu,MF_POPUP,(
UINT)hSousMenu,"
Fichier
"
);
hwnd =
CreateWindow
(
"
MaWinClass
"
, "
Titre
"
, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 640
, 300
,
NULL
, hMenu, 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
HBRUSH EditBrush;
static
COLORREF BkEditcolor;
static
BOOL EditNotChg =
TRUE;
static
COLORREF TextColor =
0
;
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
);
BkEditcolor =
GetSysColor
(
COLOR_WINDOW);
EditBrush =
CreateSolidBrush
(
BkEditcolor);
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
Etes 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_OPEN)
{
OPENFILENAME ofn;
CHAR szFile[256
]={
0
}
;
ZeroMemory
(&
ofn, sizeof
(
OPENFILENAME));
ofn.lStructSize =
sizeof
(
OPENFILENAME);
ofn.hwndOwner =
hwnd;
ofn.lpstrFile =
szFile;
ofn.nMaxFile =
sizeof
(
szFile);
ofn.lpstrFilter =
"
Fichier source C
\0
*.c
\0
Fichier source CPP
\0
*.cpp
\0
"
;
ofn.nFilterIndex =
1
;
ofn.Flags =
OFN_PATHMUSTEXIST |
OFN_FILEMUSTEXIST |
OFN_HIDEREADONLY;
if
(
GetOpenFileName
(&
ofn)==
TRUE)
{
HANDLE hf;
DWORD FileSize,nbcharRead ;
char
*
buffer;
hf =
CreateFile
(
szFile, GENERIC_READ, 0
,NULL
,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
);
FileSize =
GetFileSize
(
hf, NULL
);
buffer =
(
char
*
)LocalAlloc
(
LMEM_FIXED, FileSize+
1
);
ReadFile
(
hf, buffer, FileSize, &
nbcharRead, NULL
) ;
buffer[FileSize] =
0
;
SendMessage
(
hEdit, WM_SETTEXT, 0
, (
LPARAM)buffer);
LocalFree
(
buffer);
CloseHandle
(
hf);
}
}
/*if IDM_OPEN*/
if
(
LOWORD
(
wParam) ==
IDM_TEXTCOLOR)
{
CHOOSECOLOR cc;
static
COLORREF acrCustClr[16
];
ZeroMemory
(&
cc, sizeof
(
CHOOSECOLOR));
cc.lStructSize =
sizeof
(
CHOOSECOLOR);
cc.hwndOwner =
hwnd;
cc.lpCustColors =
NULL
;
cc.lpCustColors =
(
LPDWORD) acrCustClr;
cc.rgbResult =
TextColor;
cc.Flags =
CC_FULLOPEN |
CC_RGBINIT;
if
(
ChooseColor
(&
cc)==
TRUE)
{
TextColor =
cc.rgbResult;
PostMessage
(
hEdit,WM_SETREDRAW,TRUE,0
);
}
}
/*if IDM_TEXTCOLOR*/
if
(
LOWORD
(
wParam) ==
IDM_QUIT) PostMessage
(
hwnd, WM_CLOSE,0
,0
);
if
(
HIWORD
(
wParam) ==
EN_CHANGE) EditNotChg =
FALSE;
return
0
;
case
WM_CTLCOLOREDIT:
if
((
HWND)lParam ==
hEdit)
{
SetTextColor
((
HDC)wParam, TextColor);
SetBkColor
((
HDC)wParam, BkEditcolor);
return
EditBrush;
}
break
;
case
WM_SIZE:
MoveWindow
(
hEdit, 0
, 0
, LOWORD
(
lParam), HIWORD
(
lParam), TRUE);
return
0
;
case
WM_DESTROY:
DeleteObject
(
EditBrush);
PostQuitMessage
(
0
);
return
0
;
}
return
DefWindowProc
(
hwnd, uMsg, wParam, lParam);
}
J'ai testé les compilations avec C++ Builder et DevC++.
À vos PC.