IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)


API Windows en C

Afficher des images sous windows NT.

Par CGi

Le 15 mai 2006




Introduction :

Nous avons vu comment afficher des images bitmap tout en les chargeant avec la fonction LoadImage, hélas cette fonction ne permet pas de charger une image depuis un fichier sous Windows NT. Nous allons devoir charger le fichier et le traiter avant affichage.


Chargement du fichier :

L'ouverture du fichier ce fait avec la fonction CreateFile. Nous extrayons tout d'abord l'entête du fichier BITMAPFILEHEADER à l'aide de la fonction ReadFile. Ensuite nous chargeons le bitmap dans un buffer.

    static LPVOID buffer;   
    
    
    /* ... */    
    
             HANDLE hf;
             DWORD FileSize,nbcharRead;
             BITMAPFILEHEADER bfh;

             hf = CreateFile("image.bmp", GENERIC_READ, 0,NULL,
                                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

             FileSize = GetFileSize(hf, NULL);
             ReadFile(hf, &bfh, sizeof(bfh), &nbcharRead, NULL) ;

             buffer = GlobalAlloc(GMEM_FIXED, FileSize);
             ReadFile(hf, buffer, FileSize - sizeof(BITMAPFILEHEADER),
                                                             &nbcharRead, NULL);
                                                             
             
             /* ... */
             CloseHandle(hf);
             /* ... */
             GlobalFree(buffer);  


Création de la palette de couleur :

Si le bitmap à un nombre de couleurs inférieur ou égal à 256, il faut générer sa palette de couleur. Les bitmaps ayant plus de 256 couleurs n'ont pas de palette. Chaque pixel est représenté par la valeur réel de sa couleur. Le bitmap contient un entête BITMAPINFO donnant ces informations nous y extayons le nombre de couleurs et créons la palette si besoin. La palette sera ensuite accéssible via son handle de palette hpal de type HPALETTE.

    static LPVOID buffer;   
    static UINT nbColors; 
    static HPALETTE hpal;
    static BITMAPINFO *bmInfo;   
    
    /* ... */ 

             bmInfo = (BITMAPINFO*)buffer;
             nbColors = bmInfo->bmiHeader.biClrUsed ?
                                         bmInfo->bmiHeader.biClrUsed :
					      1 << bmInfo->bmiHeader.biBitCount;

             if( nbColors <= 256 )
               {
                UINT i;
		UINT nSize = sizeof(LOGPALETTE) +
                                              (sizeof(PALETTEENTRY) * nbColors);

		LOGPALETTE *pLPal = (LOGPALETTE*) GlobalAlloc(GMEM_FIXED,nSize);
		pLPal->palVersion = 0x300;
		pLPal->palNumEntries = nbColors;
		for( i=0; i < nbColors; i++)
		 {
		  pLPal->palPalEntry[i].peRed = bmInfo->bmiColors[i].rgbRed;
		  pLPal->palPalEntry[i].peGreen = bmInfo->bmiColors[i].rgbGreen;
		  pLPal->palPalEntry[i].peBlue = bmInfo->bmiColors[i].rgbBlue;
		  pLPal->palPalEntry[i].peFlags = 0;
		 }
                hpal = CreatePalette(pLPal);
		GlobalFree(pLPal);
               }

Affichage de l'image :

L'affichage de l'image ce fait avec la fonction SetDIBitsToDevice. Cette fonction reçois entre autre un pointeur sur l'entête du bitmap (bmInfo) mais aussi un pointeur sur les pixels (lpDIBBits) qu'il faut caluler en fonction des infos contenu dans l'entête du bitmap. Et s'il y a une palette il faut la sélectionner.

        
    static LPVOID buffer;   
    static UINT nbColors; 
    static HPALETTE hpal;
    static BITMAPINFO *bmInfo;  
    
    /* ... */        
        
        case WM_PAINT :
            {
              HDC hdc;
              PAINTSTRUCT ps;
              LPVOID lpDIBBits;

              if( bmInfo->bmiHeader.biBitCount > 8 )
		lpDIBBits = (bmInfo->bmiColors +
		  bmInfo->bmiHeader.biClrUsed) +
		    ((bmInfo->bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0);
              else
		lpDIBBits = bmInfo->bmiColors + nbColors;
		
	      hdc = BeginPaint(hwnd, &ps);	

              if( hpal && (GetDeviceCaps(hdc,RASTERCAPS) & RC_PALETTE) )
         	{
		 SelectPalette(hdc, hpal, FALSE);
		 RealizePalette(hdc);
        	}              

              SetDIBitsToDevice(hdc,10,10,bmInfo->bmiHeader.biWidth,
                              bmInfo->bmiHeader.biHeight, 0, 0, 0,
                                 bmInfo->bmiHeader.biHeight, lpDIBBits, bmInfo,
                                                                DIB_RGB_COLORS);

              EndPaint(hwnd, &ps);

              return 0;
            }



Code complet :

L'exemple pour rester simple n'éffectue aucun test de validité. Il va de soit que dans un cas réel il faudra éffectuer ces tests. winmain.c :

#include <windows.h>

LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
                                                LPSTR lpCmdLine, int nCmdShow)
{
    HWND hwnd;
    MSG msg;
    WNDCLASS wc;

    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 LPVOID buffer;
    static BITMAPINFO *bmInfo;
    static UINT nbColors;
    static HPALETTE hpal;

    switch (uMsg)
    {
       case WM_CREATE :
            {
             HANDLE hf;
             DWORD FileSize,nbcharRead;
             BITMAPFILEHEADER bfh;

             hf = CreateFile("image.bmp", GENERIC_READ, 0,NULL,
                                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

             FileSize = GetFileSize(hf, NULL);
             ReadFile(hf, &bfh, sizeof(bfh), &nbcharRead, NULL) ;

             buffer = GlobalAlloc(GMEM_FIXED, FileSize);
             ReadFile(hf, buffer, FileSize - sizeof(BITMAPFILEHEADER),
                                                             &nbcharRead, NULL);
             bmInfo = (BITMAPINFO*)buffer;
             nbColors = bmInfo->bmiHeader.biClrUsed ?
                                         bmInfo->bmiHeader.biClrUsed :
					      1 << bmInfo->bmiHeader.biBitCount;

             if( nbColors <= 256 )
               {
                UINT i;
		UINT nSize = sizeof(LOGPALETTE) +
                                              (sizeof(PALETTEENTRY) * nbColors);

		LOGPALETTE *pLPal = (LOGPALETTE*) GlobalAlloc(GMEM_FIXED,nSize);
		pLPal->palVersion = 0x300;
		pLPal->palNumEntries = nbColors;
		for( i=0; i < nbColors; i++)
		 {
		  pLPal->palPalEntry[i].peRed = bmInfo->bmiColors[i].rgbRed;
		  pLPal->palPalEntry[i].peGreen = bmInfo->bmiColors[i].rgbGreen;
		  pLPal->palPalEntry[i].peBlue = bmInfo->bmiColors[i].rgbBlue;
		  pLPal->palPalEntry[i].peFlags = 0;
		 }
                hpal = CreatePalette(pLPal);
		GlobalFree(pLPal);
               }

             CloseHandle(hf);
             return 0;
            }

        case WM_PAINT :
            {
              HDC hdc;
              PAINTSTRUCT ps;
              LPVOID lpDIBBits;

              if( bmInfo->bmiHeader.biBitCount > 8 )
		lpDIBBits = (bmInfo->bmiColors +
		  bmInfo->bmiHeader.biClrUsed) +
		    ((bmInfo->bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0);
              else
		lpDIBBits = bmInfo->bmiColors + nbColors;
		
	      hdc = BeginPaint(hwnd, &ps);	

              if( hpal && (GetDeviceCaps(hdc,RASTERCAPS) & RC_PALETTE) )
         	{
		SelectPalette(hdc, hpal, FALSE);
		RealizePalette(hdc);
        	}              

              SetDIBitsToDevice(hdc,10,10,bmInfo->bmiHeader.biWidth,
                              bmInfo->bmiHeader.biHeight, 0, 0, 0,
                                 bmInfo->bmiHeader.biHeight, lpDIBBits, bmInfo,
                                                                DIB_RGB_COLORS);

              EndPaint(hwnd, &ps);

              return 0;
            }

        case WM_DESTROY:
            GlobalFree(buffer);
            PostQuitMessage(0);
            return 0;

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

J'ai testé les compilations avec C++ Builder et DevC++.


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-2020 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.