Programmer en C++
Ajout d'un bouton dans une fenêtre

Avant d'aborder cette partie, vous devez savoir créer une fenêtre windows de base, et savoir ajouter des fichiers vides à votre projet (voir cours précédent). On supposera d'ailleur réutiliser la fenêtre du chapître 2 : "Séparation des fichiers et ajout d'icones"

1. Construction d'un bouton

Pour des raisons de clartés nous allons écrire le code dans deux fichiers que nous allons créer maintenant. Le premier se nommera : "MesControls.h", et le deuxième : "MesControls.cpp".
Une fois ces fichiers créés, l'arborescence de notre projet ressemble à ceci :

Dans le fichier "MesControls.h" nous déclarons le prototype de la nouvelle fonction créatrice de notre bouton.

void MonBouton(HWND);

Le choix du nom de la fonction "MonBouton" est bien sur tout à fait arbitraire (J'aurais pu l'appeler "truc" ou "machin"). Comme on peut l'appercevoir cette fonction recevra un "handle" (HWND), mais ne retournera rien (void). C'est cet "handle" qui assurera le lien entre notre bouton et la fenêtre.

Puis dans le fichier "MesControls.cpp" dont le code complet est donné ici, nous allons définir la fonction "MonBouton".

#include <windows.h>
#include "resource.h"
#include "MesControls.h"


HINSTANCE hInstBouton;

void MonBouton(HWND hwnd)
{
    HWND hBouton;
    hBouton = CreateWindow (
        "BUTTON",
        "OK",
        WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
        10, 10,
        100, 25,
        hwnd,
        (HMENU) ID_BOUTON,
        hInstBouton,
        NULL);
}

On remarque aussitôt que la création d'un bouton nécessite une fonction de création de fenêtre : CreateWindow(). Que contient cette fonction ?

#define MABELLEICONE  100   // icône principale
#define MAPETITEICONE 101   // icône pour la barre de titre

#define ID_BOUTON 200   // Identificateur du bouton "OK"

Vite compilons pour admirer notre oeuvre.

Pourquoi notre bouton ne s'affiche pas dans ma fenêtre ?
Pas de panique, notre bouton est prêt, mais il faut encore dire au programme de le dessiner. Vous vous souvenez de la procédure de fenêtre dans laquelle se trouvait le message WM_DESTROY ?
C'est dans cette procédure que nous allons maintenant demander l'affichage du bouton.
A quel moment ? Hé bien au moment de sa création. Voici ce que nous allons ajouter :

case WM_CREATE:
    // Fonction de dessin du bouton
    MonBouton(hwnd);
    break;

La procédure de fenêtre devrait maintenant avoir cette allure :

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_CREATE:
            // Fonction de dessin du bouton
            MonBouton(hwnd);
            break;
        case WM_DESTROY:
            PostQuitMessage (0);     // Déclenche la fermeture de la fenêtre
            break;
        default:
            return DefWindowProc (hwnd, message, wParam, lParam) ;
    }
    return 0;
}

C'est bien joli tout ça, mais notre bouton ne fait pas grand chose !

2. Comment rendre notre bouton réactif ?

Nous allons créer une deuxième fonction qui va chercher à indentifier le numéro du bouton sur lequel l'utilisateur à cliqué. Ici le cas est simple, il n'y a qu'un bouton défini en début de prgramme par "ID_BOUTON". C'est naturellement dans le fichier "MesControls.h" que nous allons ajouter la déclaration de notre nouvelle fonction. Appelons là "TestBouton" :

void MonBouton(HWND);
void TestBouton(HWND, WPARAM);

Ah un paramètre de plus ! A quoi sert-il ?
Pour comprendre, écrivons la définition de la fonction dans le fichier "MesControls.cpp". Nous placerons "TestBouton(...) à la suite de la fonction déjà existante "MonBouton(...)".

void TestBouton (HWND hwnd, WPARAM wParam)
{
    if (ID_BOUTON == LOWORD(wParam))
   {
        MessageBox(hwnd, "Vous avez cliqué sur le bouton", "Test du bouton", MB_OK);
   }
}

En fait c'est dans les octets de poids faibles de la variable wParam que Window nous transmet l'identifiant du bouton sur lequel on a cliqué. LOWORD permet d'extraire ces octets. Si la valeur correspond à l'identifiant de notre bouton, alors un message est envoyé par l'intermédiaire d'une boîte de dialogue.
Intéressons nous maintenant à la fontion "MessageBox(...)".

Encore une fois, nous allons utiliser la procédure de fenêtre. Lorsque l'utilisateur clic sur le bouton poussoir, cette fenêtre nous envoit le message WM_COMMAND. A la reception de ce message, nous activons donc notre nouvelle fonction.

case WM_COMMAND:
    TestBouton(hwnd, wParam);
    break;

Nous pouvons maintenant compiler et exécuter notre programme. On obtient ceci :