Developpez.com - C
X

Choisissez d'abord la catégorieensuite la rubrique :



API Windows en C

Afficher des images.

Par CGi

Le 15 mai 2006




Introduction :

Le traitement d'images dans Windows est un sujet très vaste. Dans ce petit article nous allons voir comment afficher simplement une image dans une fenêtre. Nous avons déjà vu l'affichage d'une image dans une boîte de dialogue à l'aide du contrôle static. Nous allons faire de même, mais dans une fenêtre standard. Nous parlerons bien sûr que d'images de type Bitmap (celle dont les fichiers ont l'extention bmp).




Image sur contrôle static :

Nous le créons comme tout contrôle à l'aide de la fonction CreateWindow avec comme nom de classe de fenêtre "STATIC" suivi du nom de la ressource image (le contrôle static ne peut afficher que des images provenant des ressources du programme). Il devra bien sûr avoir le style SS_BITMAP. Les paramètres de dimensions n'ont aucun effet en ce cas, ils peuvent donc être mit à zéro.

        case WM_CREATE :
            {
             HWND hstatic = CreateWindow("STATIC", "MyPicture",
                                    WS_CHILD | WS_VISIBLE| SS_BITMAP,
                                         10, 10, 0, 0, hwnd, NULL, hinst, NULL);
             return 0;
            }

Le fichier ressource :

MyPicture BITMAP "image.bmp"       

Cette façon de faire et plus lourde en terme de ressources systèmes, mais à l'avantage que le contrôle peut gérer les messages de notifications. Si l'on a pas besoin de gérer ces messages, il est préférable de dessiner l'image sur un contexe de périférique.


Dessiner une image avec DrawState :

Une seconde solution est de dessiner l'image dans la fenêtre en utilisant un contexte de périphérique. Nous chargerons l'image depuis les ressources avec la fonction LoadBitmap sur le traitement du message WM_CREATE et l'affichons avec la fonction DrawState sur le traitement du message WM_PAINT. Et destruction de l'objet quand on n'en a plus besoin avec la fonction DeleteObject. Cette solution est moins gourmande en ressources système. Le fichier ressources étant le même que précédement.

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  static HBITMAP hBmp;

  switch (uMsg)
    {
        case WM_CREATE :

            hBmp=LoadBitmap(hinst,"MyPicture");
			
            return 0;

        case WM_PAINT :
          {

            HDC hdc;
            PAINTSTRUCT ps;

            hdc = BeginPaint(hwnd, &ps);

            DrawState(hdc,NULL,NULL,(long)hBmp,0,10,10,0,0,DST_BITMAP);

            EndPaint(hwnd, &ps);

            return 0;
          }

        case WM_DESTROY :
            DeleteObject(hBmp);
            PostQuitMessage(0);
            return 0;

        default :
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

Sous les plateformes Windows 95 et Windows XP et suivante nous pouvons par la même methode afficher une image provenant d'un fichier (Voir note en bas de page pour Windows NT). Pour cela nous chargeons l'image avec la fonction LoadImage.

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  static HBITMAP hBmp;

  switch (uMsg)
    {
        case WM_CREATE :

            hBmp=LoadImage(NULL,"image.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
			
            return 0;

        case WM_PAINT :
          {

            HDC hdc;
            PAINTSTRUCT ps;

            hdc = BeginPaint(hwnd, &ps);

            DrawState(hdc,NULL,NULL,(long)hBmp,0,10,10,0,0,DST_BITMAP);

            EndPaint(hwnd, &ps);

            return 0;
          }

        case WM_DESTROY :
            DeleteObject(hBmp);
            PostQuitMessage(0);
            return 0;

        default :
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}


Dessiner une image avec BitBlt :

Une troisième solution est de sélectionner l'image sur un contexte de périphérique en mémoire, puis d'en faire la copie sur le contexte de périphérique d'affichage à l'aide de la fonction BitBlt. Cette solution permet de n'afficher qu'une partie du bitmap d'origine.

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 static HBITMAP hBmp;
 static HBITMAP hbmTmp;
 static BITMAP bmpi;
 static HDC hdcMem;

 switch ( uMsg ) {

   case WM_CREATE:
     {
       hBmp=LoadBitmap(hinst,"MyPicture");
       hdcMem = CreateCompatibleDC(NULL);
       hbmTmp = SelectObject(hdcMem,hBmp);
       GetObject(hBmp,sizeof(bmpi),&bmpi);
       return 0;
     }

   case WM_PAINT:
     {
       HDC hdc;
       PAINTSTRUCT ps;

       hdc = BeginPaint(hwnd, &ps);
       BitBlt(hdc,10,10,bmpi.bmWidth,bmpi.bmHeight,hdcMem,0,0,SRCCOPY);
       EndPaint(hwnd, &ps);
       return 0;
     }

   case WM_DESTROY:

       SelectObject(hdcMem,hbmTmp);
       DeleteDC(hdcMem);
       DeleteObject(hBmp);
       PostQuitMessage(0);
       return 0;
   }
 return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Dans cet exemple on a chargé l'image dès la création de l'application. Le contexte de périphérique en mémoire est obtenu avec la fonction CreateCompatibleDC. Son unique paramètre est un contexte de périphérique compatible avec celui avec lequel on travaille. Dans l'exemple il est à NULL, ce qui le rend compatible avec l'écran. On sélectionne le bitmap sur ce contexte de périphérique avec la fonction SelectObject. La fonction BitBlt ayant besoin des dimensions de l'image, nous les obtenons à l'aide de la fonction GetObject qui les affectes à une structure BITMAP.
La fonction BitBlt reçoit en son premier paramètre le handle du contexte de périphérique de destination. Les deux paramètres suivants sont la position sur la destination. Les deux suivants sont la largeur et la hauteur de la copie. Le 6ème étant le handle du contexte de périphérique de la source. le 7ème et le 8ème la position de départ (haut, gauche) sur la source. Le dernier étant une constante déterminant le traitement à éffectuer. Dans l'exemple c'est une simple copie de la source vers la destination (SRCCOPY). Voir l'aide sur API Win32 pour les différents traitement pouvant être appliqué.



Code complet :

Code complet de la deuxième méthode.
winmain.c :

#include <windows.h>

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;

    hinst = hinstance;

    wc.style = 0;
    wc.lpfnWndProc = MainWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hinstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
    wc.lpszMenuName =  NULL;
    wc.lpszClassName = "MaWinClass";

    if(!RegisterClass(&wc)) return FALSE;

    hwnd = CreateWindow("MaWinClass", "Dessiner", WS_OVERLAPPEDWINDOW,
                                   CW_USEDEFAULT, CW_USEDEFAULT, 280, 240,
                                                   NULL, NULL, hinstance, NULL);
    if (!hwnd) return FALSE;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);


    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 HBITMAP hBmp;

  switch (uMsg)
    {
        case WM_CREATE :

            hBmp=LoadBitmap(hinst,"MyPicture");

        case WM_PAINT :
          {

            HDC hdc;
            PAINTSTRUCT ps;

            hdc = BeginPaint(hwnd, &ps);

            DrawState(hdc,NULL,NULL,(long)hBmp,0,10,10,0,0,DST_BITMAP);

            EndPaint(hwnd, &ps);

            return 0;
          }

        case WM_DESTROY :
            DeleteObject(hBmp);
            PostQuitMessage(0);
            return 0;

        default :
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

resources.rc :

#include <windows.h>

MyPicture BITMAP "image.bmp" 

J'ai testé les compilations avec C++ Builder, Visual C++, Code::Blocks avec MinGW et DevC++.
Sous Windows NT LoadImage ne permet pas de charger un bitmap depuis un fichier. Je vous met un exemple qui permet de le faire.

A vos PC.

CGi



Sommaire



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.

Assembleur
  Assembleur sous Visual C++.

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.

Java
  Applet java.





Copyright 2002-2016 CGi - Tous droits réservés CGi. Toutes reproduction, utilisation ou diffusion de ce document par quelque moyen que ce soit autre que pour un usage personnel doit faire l'objet d'une autorisation écrite de la part de l'auteur, propriétaire des droits intellectuels.
Les codes sources de ce document sont fournis en l'état. L'utilisateur les utilise à ses risques et périls, sans garantie d'aucune sorte de la part de l'auteur. L'auteur n'est responsable d'aucun dommage subi par l'utilisateur pouvant résulter de l'utilisation ou de la distribution des codes sources de ce document.
De la même façon, l'auteur n'est en aucun cas responsable d'une quelconque perte de revenus ou de profits, ou de données, ou de tous dommages directs ou indirects, susceptibles de survenir du fait de l'utilisation des codes sources de ce document, quand bien même l'auteur aurait été averti de la possibilité de tels dommages. L'utilisation des codes sources de ce document vaut acceptation par l'utilisateur des termes de la licence ci-dessus.

Contacter le responsable de la rubrique C