I. Introduction▲
Dans une application, vous traitez les messages des fenêtres ordinaires ou des boîtes de dialogue. Les contrôles leur envoient des messages de notification pour signaler un événement propre à eux-mêmes. Malheureusement, tous les événements de ces contrôles n'ont pas de message de notification qui leur est associé. Si vous voulez tout de même traiter un de ces événements, une seule solution, accéder à la procédure de fenêtre du contrôle.
Pour cet exemple, nous reprendrons l'exemple du chapitre 2 « Contrôles et Messages ». Nous mettrons le contrôle d'édition en lecture seule, mais pas en lui donnant le style « lecture seule » qui lui donnerait un fond gris. Ce que nous ne désirons pas (pour l'exemple).
II. Préparation de l'exemple:▲
Après avoir créé le contrôle d'édition, nous changerons son curseur contre celui en forme de flèche. Ceci juste pour montrer que l'on ne peut pas l'éditer.
2.
3.
4.
5.
6.
7.
8.
9.
10.
static
HWND hEdit;
switch
(
uMsg)
{
case
WM_CREATE:
hEdit =
CreateWindow
(
"
edit
"
, "
Texte non modifiable.
\r\n
Vous ne pouvez \
que le lire.
\r\n
Mais il garde la couleur du fond d'un contrôle d'édition actif.
"
,
WS_CHILD |
WS_VISIBLE |
ES_MULTILINE |
ES_WANTRETURN |
WS_VSCROLL,
0
, 0
, 0
, 0
, hwnd, NULL
, hinst, NULL
);
SetClassLong
(
hEdit, GCL_HCURSOR, (
LONG)LoadCursor
(
NULL
, IDC_ARROW));
Cette action étant réalisée en la changeant dans la classe de fenêtre du contrôle. Ceci sera réalisé à l'aide de la fonction SetClassLong. Elle permet de modifier des éléments d'une classe de fenêtre déjà créée.
III. Mise en œuvre▲
Accéder à la procédure de fenêtre du contrôle ne sera pas suffisant. On ne pourra en obtenir qu’un pointeur. Il ne pourra donc servir qu'à l'appeler. Nous devons donc en créer une nouvelle.
LRESULT APIENTRY EditProc
(
HWND, UINT, WPARAM, LPARAM);
Ensuite, on affectera la nouvelle procédure de fenêtre au contrôle d'édition avec la fonction SetWindowLong, qui de plus nous retourne l'adresse de l'ancienne procédure de fenêtre.
2.
3.
4.
5.
6.
7.
8.
9.
#ifdef STRICT
WNDPROC wpOrigEditProc ;
#else
FARPROC wpOrigEditProc ;
#endif
/*...
... */
wpOrigEditProc =
(
PVOID)SetWindowLong
(
hEdit,
GWL_WNDPROC, (
LONG)EditProc);
SetWindowLong permet de modifier les propriétés d'une fenêtre comme son style par exemple.
Le pointeur sur l'ancienne procédure de fenêtre nous est nécessaire pour traiter les messages par défaut du contrôle. Les traitements que l'on veut implémenter se font bien sûr dans la nouvelle procédure de fenêtre du contrôle :
2.
3.
4.
5.
6.
7.
LRESULT APIENTRY EditProc
(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if
(
uMsg ==
WM_SETFOCUS ||
uMsg ==
WM_CONTEXTMENU ||
uMsg ==
WM_CHAR ||
uMsg ==
WM_KEYDOWN)
return
0
;
return
CallWindowProc
(
wpOrigEditProc, hwnd, uMsg, wParam, lParam);
}
Dans cette nouvelle procédure, on doit comme déjà dit, appeler l'ancienne procédure afin d'effectuer les actions par défaut du contrôle, ne serait-ce que de se dessiner par exemple. C'est le rôle de la fonction CallWindowProc qui reçoit bien sûr le pointeur sur l'ancienne procédure de fenêtre et les paramètres du message.
Dans notre exemple on bloquera les messages, WM_SETFOCUS (pour qu'il ne puisse pas prendre le focus), WM_CONTEXTMENU (pour ne pas ouvrir son menu contextuel), WM_KEYDOWN et WM_CHAR (pour qu'il ne puisse pas recevoir des commandes ou des caractères depuis le clavier). Ces messages ne seront donc pas envoyés à la procédure de fenêtre d'origine. Ceci afin d'en faire un contrôle d'édition en lecture seule qui n'est pas gris.
IV. Code complet▲
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.
#include <windows.h>
#ifdef STRICT
WNDPROC wpOrigEditProc ;
#else
FARPROC wpOrigEditProc ;
#endif
LRESULT CALLBACK MainWndProc
(
HWND, UINT, WPARAM, LPARAM);
LRESULT APIENTRY EditProc
(
HWND, UINT, WPARAM, LPARAM);
HINSTANCE hinst;
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 =
NULL
;
wc.hCursor =
LoadCursor
(
NULL
, IDC_ARROW);
wc.hbrBackground =
NULL
;
wc.lpszMenuName =
NULL
;
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;
switch
(
uMsg)
{
case
WM_CREATE:
hEdit =
CreateWindow
(
"
edit
"
, "
Texte non modifiable.
\r\n
Vous ne pouvez \
que le lire.
\r\n
Mais il garde la couleur du fond d'un contrôle d'édition actif.
"
,
WS_CHILD |
WS_VISIBLE |
ES_MULTILINE |
ES_WANTRETURN |
WS_VSCROLL,
0
, 0
, 0
, 0
, hwnd, NULL
, hinst, NULL
);
SetClassLong
(
hEdit, GCL_HCURSOR, (
LONG)LoadCursor
(
NULL
, IDC_ARROW));
wpOrigEditProc =
(
PVOID)SetWindowLong
(
hEdit,
GWL_WNDPROC, (
LONG)EditProc);
return
0
;
case
WM_SIZE:
MoveWindow
(
hEdit, 0
, 0
, LOWORD
(
lParam), HIWORD
(
lParam), TRUE);
return
0
;
case
WM_DESTROY:
SetWindowLong
(
hEdit, GWL_WNDPROC, (
LONG)wpOrigEditProc);
PostQuitMessage
(
0
);
return
0
;
default
:
return
DefWindowProc
(
hwnd, uMsg, wParam, lParam);
}
}
/**
***************************************************************************
*/
LRESULT APIENTRY EditProc
(
HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if
(
uMsg ==
WM_SETFOCUS ||
uMsg ==
WM_CONTEXTMENU ||
uMsg ==
WM_CHAR ||
uMsg ==
WM_KEYDOWN)
return
0
;
return
CallWindowProc
(
wpOrigEditProc, hwnd, uMsg, wParam, lParam);
}
J'ai testé les compilations avec C++ Builder et DevC++.
À vos PC.