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 et l'affichons
avec la fonction DrawState. Cette solution est moins gourmande en ressources système.
Le fichier ressources étant le même que précédement.
case WM_PAINT:
{
HBITMAP hBmp;
HDC hdc;
PAINTSTRUCT ps;
hBmp=LoadBitmap(hInst,"MyPicture");
hdc = BeginPaint(hwnd, &ps);
DrawState(hdc,NULL,NULL,(long)hBmp,NULL,10,10,0,0,DST_BITMAP);
EndPaint(hwnd, &ps);
DeleteObject(hBmp);
return 0;
}
Sous les plateformes Windows 95 et Windows XP 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.
case WM_PAINT :
{
HBITMAP hBmp;
HDC hdc;
PAINTSTRUCT ps;
hBmp=LoadImage(NULL,"image.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
hdc = BeginPaint(hwnd, &ps);
DrawState(hdc,NULL,NULL,(long)hBmp,NULL,10,10,0,0,DST_BITMAP);
EndPaint(hwnd, &ps);
DeleteObject(hBmp);
return 0;
}
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.
LONG APIENTRY WndProc(HWND hwnd, UINT uMsg, UINT wParam, LONG lParam)
{
static HBITMAP hBmp;
switch ( uMsg ) {
case WM_CREATE:
{
hBmp=LoadBitmap(hInst,"MyPicture");
return 0;
}
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
HBITMAP hbmTmp;
BITMAP bmpi;
HDC hdcMem;
hdcMem = CreateCompatibleDC(NULL);
hbmTmp = SelectObject(hdcMem,hBmp);
GetObject(hBmp,sizeof(bmpi),&bmpi);
hdc = BeginPaint(hwnd, &ps);
BitBlt(hdc,10,10,bmpi.bmWidth,bmpi.bmHeight,hdcMem,0,0,SRCCOPY);
EndPaint(hwnd, &ps);
SelectObject(hdcMem,hbmTmp);
DeleteDC(hdcMem);
return 0;
}
case WM_DESTROY:
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)
{
switch (uMsg)
{
case WM_PAINT:
{
HBITMAP hBmp;
HDC hdc;
PAINTSTRUCT ps;
hBmp=LoadBitmap(hInst,"MyPicture");
hdc = BeginPaint(hwnd, &ps);
DrawState(hdc,NULL,NULL,(long)hBmp,NULL,10,10,0,0,DST_BITMAP);
EndPaint(hwnd, &ps);
DeleteObject(hBmp);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
resources.rc :
#include
MyPicture BITMAP "image.bmp"
J'ai testé les compilations avec C++ Builder 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
|