Sous classement de fenêtres.

Sous classement de fenêtres.

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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 messages de notification qui leurs sont associés. 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 ne nous ne désirons pas (pour l'exemple).

Image non disponible

II. Préparation de l'exemple:

Après avoir créé le contrôle d'édition nous changerons son curseur par celui en forme de flèche. Ceci juste pour montrer visuellement que l'on ne peut pas l'éditer.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    static HWND hEdit;

    switch (uMsg)
    {
        case WM_CREATE:
            hEdit =CreateWindow("edit", "Texte non modifiable.\r\nVous ne pouvez \
que le lire.\r\nMais 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 le 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 oeuvre:

Accéder à la procédure de fenêtre du contrôle ne sera pas suffisant. On ne pourra en obtenir que seulement un pointeur. Il ne pourra donc servir qu'à l'appeler. Nous devons donc en créer une nouvelle.

 
Sélectionnez
1.
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.

 
Sélectionnez
1.
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 veux implémenter se font bien sûr dans la nouvelle procédure de fenêtre du contrôle :

 
Sélectionnez
1.
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 :

 
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.
#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\nVous ne pouvez \
que le lire.\r\nMais 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++.

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.