Programmer en C++
Win32 - Les images Bitmaps

Nous allons découvrir ici comment afficher une image de type "Bitmap" dans une fenêtre.

1. Insertion d'une image dans un "static"

Commençons par déclarer deux handles dans l'en-tête de notre programme. Lorsqu'ils sont omis, ce sont les principales causes de non fonctionnement d'un programme que rencontrent les débutants (et moi aussi car je découvre). Le premier handle sera pour l'instance de notre programme, et le deuxième pour un controle "static" qui contiendra notre image.

HINSTANCE hInstance;
HWND hStatic;

Il nous faut initialiser notre handle d'instance dans la fonction "WinMain()", mais juste avant la fonction de création de la fenêtre principale "CreateWindowEx()", sinon l'image n'apparaît pas. Nous ajoutons donc la ligne :

hInstance = hThisInstance;

Nous allons placer ici l'image dans les ressources. L'avantage est que nous n'aurons pas besoin de fournir l'image avec le programme fini (L'image sera incluse dans le programme). L'inconvénient est que notre programme sera un peu plus lourd en nombre d'octets. Ce n'est pas gênant pour un petit programme comme le notre.
Nous créons donc un fichier "Ressources.rc" (Voir le cours sur la création de menu). Dans ce fichier nous entrons le code suivant :

#include <windows.h>

MonImage BITMAP "image.bmp"

Le nom "MonImage" sera notre identifiant pour manipuler notre image dans "main.cpp" tandis que l'image dont le nom est "image.cpp" devra être placée dans le dossier du projet.

Revenons maintenant à notre programme principal "main.cpp", et découvrons la partie qui nous affichera l'image de type "Bitmap". Nous l'insérons dans la boucle de fenêtre "WindowProcedure()" :

case WM_CREATE:
    // Creation d'un controle static et insertion de l'image
    hStatic = CreateWindow("STATIC", "MonImage",
                WS_CHILD | WS_VISIBLE | SS_BITMAP,
                200, 10, 0, 0,
                hwnd,
                NULL,
                hInstance,
                NULL);
    break;

Voilà c'est déjà terminé, nous compilons le programme est voilà le résultat après son exécution :

Voici le code complet du fichier "main.cpp" avec juste une modification de couleur pour le fond de la fenêtre :

#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif


#include <tchar.h>
#include <windows.h>

HINSTANCE hInstance;     // Déclaration d'un "handle" d'instance
HWND hStatic;     // Déclaration d'un "handle" pour notre contrôle "Static"

// Déclaration de la procédure de fenêtre
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

// Un gris identique au fond de mon image
HBRUSH CouleurFond = CreateSolidBrush(RGB(214, 214,214));

// Création d'une variable globale contenant le nom de la classe de fenêtre
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
    HWND hwnd;     // "handle" de la fenêtre
    MSG messages;     // variable de sauvegarde des messages provenant de la fenêtre
    WNDCLASSEX wincl;     // Création d'une structure de classe de fenêtre

    /* Structure de la classe de fenêtre */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Choix par défaut des icones et du pointeur de souris */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;     // Aucun menu
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    /* On charge ici notre jolie couleur pour le fond de la fenêtre */
    wincl.hbrBackground = CouleurFond;

    /* Enregistrement de la classe de fenêtre. Si échec, on quitte le programme */
    if (!RegisterClassEx (&wincl))
        return 0;

    hInstance = hThisInstance;

    /* Création de la fenêtre */
    hwnd = CreateWindowEx (
        0,
        szClassName,
        _T("Ma jolie fenêtre"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        500,
        400,
        HWND_DESKTOP,
        NULL,
        hThisInstance,
        NULL
       );

    /* Affichage de la fenêtre à l'écran */
    ShowWindow (hwnd, nCmdShow);

    /* Boucle de lecture des messages */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Convertit les codes messages en caractères */
        TranslateMessage(&messages);
        /* Envoie des messages à la fonction WindowProcedure */
        DispatchMessage(&messages);
    }

    /* Valeur de retour */
    return messages.wParam;
}

/* Procédure de fenêtre (action à réaliser) */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_CREATE:
            // Creation d'un controle static et insertion de l'image
            hStatic = CreateWindow("STATIC", "MonImage",
                        WS_CHILD | WS_VISIBLE | SS_BITMAP,
                        200, 10, 0, 0,
                        hwnd,
                        NULL,
                        hInstance,
                        NULL);
            break;
        case WM_DESTROY:
            PostQuitMessage (0);     // Déclenche la fermeture de la fenêtre
            break;
        default:
            return DefWindowProc (hwnd, message, wParam, lParam) ;
    }
    return 0;
}

Voilà c'est terminé pour ce chapître.