I. 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 ne parlerons bien sûr que d'images de type Bitmap (celles dont les fichiers ont l'extension BMP).
II. 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 mis à 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 termes de ressources système, mais a l'avantage que le contrôle peut gérer les messages de notification. Si l'on n'a pas besoin de gérer ces messages, il est préférable de dessiner l'image sur un contexte de périphérique.
III. 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'afficherons avec la fonction DrawState. Cette solution est moins gourmande en ressources système. Le fichier ressources étant le même que précédemment.
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 méthode 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
;
}
IV. 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 fonctionGetObject qui les affecte à 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 6e étant le handle du contexte de périphérique de la source. Le 7e et le 8e la position de départ (haut, gauche) sur la source. Le dernier étant une constante déterminant le traitement à effectuer. 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 traitements pouvant être appliqués.
V. 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 <windows.h>
MyPicture BITMAP "
image.bmp
"
J'ai testé les compilations avec C++ Builder et DevC++.
À vos PC.
CGi