Ce petit prog montre comment dessiner un bitmap comportant des zones qui doivent être transparente. Cela necessite un masque du bitmap à recopier que l'on fournit dans les ressources ou que l'on calcule à l'exécution à partir du couleur de transparence.
Source / Exemple :
//***************************************************************************************
// TestBmp.cpp :
//
//***************************************************************************************
#include <windows.h>
#include "Resource.h"
//=======================================================================================
// Variables globales.
//=======================================================================================
HINSTANCE g_hAppInstance = NULL; // instance de l'application
HWND g_hWndMainFrame = NULL; // fenêtre principale
//=======================================================================================
// Variables du module.
//=======================================================================================
static HBITMAP s_hBmpSprite = NULL; // bitmap à afficher
static HBITMAP s_hBmpSpriteMask = NULL; // masque du bitmap à afficher
static HBITMAP s_hBmpBackground = NULL; // bitmap du fond
static HDC s_hDCSprite = NULL; // DC avec le bitmap à afficher
static HDC s_hDCSpriteMask = NULL; // DC avec le masque du bitmap à afficher
static HDC s_hDCBackground = NULL; // DC avec le bitmap du fond
static HBITMAP s_hOldBmpSprite = NULL; // ancien bitmap de s_hDCSprite
static HBITMAP s_hOldBmpSpriteMask = NULL; // ancien bitmap de s_hDCSpriteMask
static HBITMAP s_hOldBmpBackground = NULL; // ancien bitmap de s_hDCBackground
static SIZE s_SizeBmpSprite = {0, 0}; // taille de s_hBmpSprite
static SIZE s_SizeBmpBackground = {0, 0}; // taille de s_hBmpBackground
static POINT s_PtSprite = {0, 0}; // position où afficher le bitmap
//=======================================================================================
// Fonctions du module.
//=======================================================================================
static BOOL InitInstance(HINSTANCE hInstance, int nShowCmd);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static int OnCreate (HWND hWnd);
static void OnDestroy ();
static void OnPaint ();
static void OnMouseMove (WPARAM wParam, LPARAM lParam);
static HBITMAP CreateBmpMask(HBITMAP hBmp, COLORREF clrTransparent);
//***************************************************************************************
// WinMain :
//***************************************************************************************
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nShowCmd)
{
// initialisation de l'application
if(!InitInstance(hInstance, nShowCmd))
return 0;
// boucle de messages
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//***************************************************************************************
// InitInstance :
//***************************************************************************************
BOOL InitInstance(HINSTANCE hInstance, int nShowCmd)
{
// sauvegarde instance de l'application
g_hAppInstance = hInstance;
char szWndClass[] = "TestBmp_MainFrame";
char szWndTitle[] = "TestBmp";
// initialisation classe de fenêtre
WNDCLASS wc;
memset(&wc, 0, sizeof(WNDCLASS));
wc.hInstance = g_hAppInstance;
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpfnWndProc = WndProc;
wc.lpszClassName = szWndClass;
if(!RegisterClass(&wc)) return FALSE;
// création de la fenêtre
g_hWndMainFrame = CreateWindow(szWndClass, szWndTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, g_hAppInstance, NULL);
// position initiale du sprite (à l'emplacement de la souris)
GetCursorPos(&s_PtSprite);
ScreenToClient(g_hWndMainFrame, &s_PtSprite);
// affichage
ShowWindow(g_hWndMainFrame, nShowCmd);
UpdateWindow(g_hWndMainFrame);
return TRUE;
}
//***************************************************************************************
// WndProc :
//***************************************************************************************
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE : return OnCreate(hWnd);
case WM_DESTROY : OnDestroy(); return 0;
case WM_PAINT : OnPaint(); return 0;
case WM_MOUSEMOVE : OnMouseMove(wParam, lParam); return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//***************************************************************************************
// OnCreate :
//***************************************************************************************
int OnCreate(HWND hWnd)
{
// chargement des bitmaps
s_hBmpSprite = LoadBitmap(g_hAppInstance, MAKEINTRESOURCE(IDB_SPRITE));
s_hBmpBackground = LoadBitmap(g_hAppInstance, MAKEINTRESOURCE(IDB_BACKGROUND));
// le masque peut être choit chargé depuis les ressources soit créé lors de
// l'exécution en indiquant la couleur de transparence
// s_hBmpSpriteMask = LoadBitmap(g_hAppInstance, MAKEINTRESOURCE(IDB_SPRITEMASK));
s_hBmpSpriteMask=CreateBmpMask(s_hBmpSprite, RGB(0xFF, 0x00, 0xFF));
// création de DCs pour ces bitmap
HDC hdc = GetDC(hWnd);
s_hDCSprite = CreateCompatibleDC(hdc);
s_hDCSpriteMask = CreateCompatibleDC(hdc);
s_hDCBackground = CreateCompatibleDC(hdc);
ReleaseDC(hWnd, hdc);
// sélection des bitmaps dans les DCs et savegarde des anciens
s_hOldBmpSprite = (HBITMAP) SelectObject(s_hDCSprite, s_hBmpSprite);
s_hOldBmpSpriteMask = (HBITMAP) SelectObject(s_hDCSpriteMask, s_hBmpSpriteMask);
s_hOldBmpBackground = (HBITMAP) SelectObject(s_hDCBackground, s_hBmpBackground);
// récupération de la taille des bitmaps
BITMAP bmpInfo;
GetObject(s_hBmpSprite, sizeof(BITMAP), &bmpInfo);
s_SizeBmpSprite.cx = bmpInfo.bmWidth;
s_SizeBmpSprite.cy = bmpInfo.bmHeight;
GetObject(s_hBmpBackground, sizeof(BITMAP), &bmpInfo);
s_SizeBmpBackground.cx = bmpInfo.bmWidth;
s_SizeBmpBackground.cy = bmpInfo.bmHeight;
// création réussie
return 0;
}
//***************************************************************************************
// OnDestroy :
//***************************************************************************************
void OnDestroy()
{
// sélection des anciens bitmaps dans les DCs
SelectObject(s_hDCSprite, s_hOldBmpSprite);
SelectObject(s_hDCSpriteMask, s_hOldBmpSpriteMask);
SelectObject(s_hDCBackground, s_hOldBmpBackground);
// destruction des DCs
DeleteDC(s_hDCSprite);
DeleteDC(s_hDCSpriteMask);
DeleteDC(s_hDCBackground);
// destruction des bitmaps
DeleteObject(s_hBmpSprite);
DeleteObject(s_hBmpSpriteMask);
DeleteObject(s_hBmpBackground);
// fin de l'application
PostQuitMessage(0);
}
//***************************************************************************************
// OnPaint :
//***************************************************************************************
void OnPaint()
{
// début du dessin
PAINTSTRUCT ps;
HDC hdc = BeginPaint(g_hWndMainFrame, &ps);
// taille zone cliente
RECT rcClient;
GetClientRect(g_hWndMainFrame, &rcClient);
int cxClient = rcClient.right-rcClient.left;
int cyClient = rcClient.bottom-rcClient.top;
// création de bitmaps et DCs pour l'affichage final et les opérations
// intermédiaires
HDC hDCFinal = CreateCompatibleDC(hdc);
HDC hDCTemp = CreateCompatibleDC(hdc);
HBITMAP hBmpFinal = CreateCompatibleBitmap(hdc, cxClient, cyClient);
HBITMAP hBmpTemp = CreateCompatibleBitmap(hdc, s_SizeBmpSprite.cx, s_SizeBmpSprite.cy);
HBITMAP hOldBmpFinal = (HBITMAP) SelectObject(hDCFinal, hBmpFinal);
HBITMAP hOldBmpTemp = (HBITMAP) SelectObject(hDCTemp, hBmpTemp);
// effacement du fond du DC final
HBRUSH hWhiteBrush = CreateSolidBrush(RGB(0xFF, 0xFF, 0xFF));
FillRect(hDCFinal, &rcClient, hWhiteBrush);
DeleteObject(hWhiteBrush);
// Les 2 opération suivantes peuvant être réalisée une seule fois lors de
// l'initialisation de l'application
// temp = NOT mask
BitBlt(hDCTemp, 0, 0, s_SizeBmpSprite.cx, s_SizeBmpSprite.cy,
s_hDCSpriteMask, 0, 0, NOTSRCCOPY);
// temp = temp AND bitmap
BitBlt(hDCTemp, 0, 0, s_SizeBmpSprite.cx, s_SizeBmpSprite.cy,
s_hDCSprite, 0, 0, SRCAND);
// final = background
BitBlt(hDCFinal, 0, 0, s_SizeBmpBackground.cx, s_SizeBmpBackground.cy,
s_hDCBackground, 0, 0, SRCCOPY);
// final = final AND mask (à la position finale du sprite)
BitBlt(hDCFinal, s_PtSprite.x, s_PtSprite.y, s_SizeBmpSprite.cx, s_SizeBmpSprite.cy,
s_hDCSpriteMask, 0, 0, SRCAND);
// final = final OR temp (à la position finale du sprite)
BitBlt(hDCFinal, s_PtSprite.x, s_PtSprite.y, s_SizeBmpSprite.cx, s_SizeBmpSprite.cy,
hDCTemp, 0, 0, SRCPAINT);
// recopie à l'écran
BitBlt(hdc, 0, 0, cxClient, cyClient, hDCFinal, 0, 0, SRCCOPY);
// libération des ressources
SelectObject(hDCFinal, hOldBmpFinal);
SelectObject(hDCTemp, hOldBmpTemp);
DeleteDC(hDCFinal);
DeleteDC(hDCTemp);
DeleteObject(hBmpFinal);
DeleteObject(hBmpTemp);
// fin du dessin
EndPaint(g_hWndMainFrame, &ps);
}
//***************************************************************************************
// OnMouseMove :
//***************************************************************************************
void OnMouseMove(WPARAM wParam, LPARAM lParam)
{
// on dessine le bitmap à la position de la souris
s_PtSprite.x = (short)LOWORD(lParam);
s_PtSprite.y = (short)HIWORD(lParam);
InvalidateRect(g_hWndMainFrame, NULL, FALSE);
UpdateWindow(g_hWndMainFrame);
}
//***************************************************************************************
// CreateBmpMask :
//***************************************************************************************
HBITMAP CreateBmpMask(HBITMAP hBmp, COLORREF clrTransparent)
{
// information sur le bitmap (taille)
BITMAP bmpInfo;
GetObject(hBmp, sizeof(BITMAP), &bmpInfo);
// création bitmap monochrome pour le masque
HBITMAP hBmpMask = CreateBitmap(bmpInfo.bmWidth, bmpInfo.bmHeight, 1, 1, NULL);
// création de DCs pour y mettre les bitmaps
HDC hdc = GetDC(NULL);
HDC hDCBmp = CreateCompatibleDC(hdc);
HDC hDCBmpMask = CreateCompatibleDC(hdc);
ReleaseDC(NULL, hdc);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hDCBmp, hBmp);
HBITMAP hOldBmpMask = (HBITMAP)SelectObject(hDCBmpMask, hBmpMask);
// on mettant la couleur de fond du DC avec le bitmap initial à la couleur de
// tranparence et en le recopiant dans le DC avec le bitmap monochrome, on crée le
// masque voulu : les pixels de la couleur transparente seront mis au noir et les
// autres au blanc.
SetBkColor(hDCBmp, clrTransparent);
BitBlt(hDCBmpMask, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, hDCBmp, 0, 0, SRCCOPY);
// libération des ressources er retour
SelectObject(hDCBmp, hOldBmp);
SelectObject(hDCBmpMask, hOldBmpMask);
DeleteDC(hDCBmp);
DeleteDC(hDCBmpMask);
return hBmpMask;
}
Conclusion :
Outre les commentaires, un fichier .doc qui explique plus en détail les opérations intermédiaires et leur résultat.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.