Quizás Microsoft a enfocado demasiado la interface del GDI+ hacia el C++, hasta el punto de que existe toda una librería de clases para este lenguaje. Pese a su comodidad de uso desde el mismo Builder, precisa descargar WSDK. No se si en las versiones mas recientes de delphi y Builder se incorpora de serie la librería de clases del GDI+, pero en las versiones que uso yo no se incluyen, es por eso que me he decidido a publicar este truco.
Propongo un código simple para crear un HBITMAP a partir de un archivo de los tipos arriba descritos, pero lo pondré de distintas formas según gustos y comodidades.
Usando La librería de clases GDI+:
cpp
#define STRICT #include <windows.h> #include <algorithm> using std::min; using std::max; #include "Gdiplus.h" #pragma link "Gdiplus.lib" HBITMAP CreateHBITMAPFromFile(CHAR *cFileName) { WCHAR *FileName = new WCHAR[strlen(cFileName)+1]; int size = strlen(cFileName)*sizeof(WCHAR)+1; MultiByteToWideChar(CP_ACP, 0, cFileName, -1, FileName, size); // Initialize GDI+. Gdiplus::GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); HBITMAP hBitmap; Gdiplus::Bitmap *GBitmap = new Gdiplus::Bitmap(FileName, 0); GBitmap->GetHBITMAP(0, &hBitmap); //shutdown GDI+ Gdiplus::GdiplusShutdown(gdiplusToken); delete GBitmap; delete FileName; return hBitmap; }
Si no tenemos o no queremos usar la WSDK, podemos optar por usar la GDI+ Flat API importando las API que necesitemos usar.
Usando GDI+ Flat API en C/C++:
cpp
HBITMAP CreateHBITMAPFromFile(CHAR *cFileName) { typedef DWORD (__stdcall *PGdiplusStartup)(ULONG_PTR *hToken, void *input, void *Output); typedef void (__stdcall *PGdiplusShutdown)(ULONG_PTR token); typedef DWORD (__stdcall *PGdipCreateBitmapFromFile)(WCHAR* filename, HANDLE* bitmap); typedef DWORD (__stdcall *PGdipCreateHBITMAPFromBitmap)(HANDLE bitmap, HBITMAP* hBitmap, DWORD BKColor); PGdiplusStartup GdiplusStartup = (PGdiplusStartup)GetProcAddress(LoadLibrary("gdiplus.dll"), "GdiplusStartup"); PGdipCreateBitmapFromFile GdipCreateBitmapFromFile = (PGdipCreateBitmapFromFile)GetProcAddress(LoadLibrary("gdiplus.dll"), "GdipCreateBitmapFromFile"); PGdipCreateHBITMAPFromBitmap GdipCreateHBITMAPFromBitmap = (PGdipCreateHBITMAPFromBitmap)GetProcAddress(LoadLibrary("gdiplus.dll"), "GdipCreateHBITMAPFromBitmap"); PGdiplusShutdown GdiplusShutdown = (PGdiplusShutdown)GetProcAddress(LoadLibrary("gdiplus.dll"), "GdiplusShutdown"); if(!GdiplusStartup || !GdiplusShutdown || !GdipCreateBitmapFromFile || !GdipCreateHBITMAPFromBitmap) return 0; // Pasamos a Unicode WCHAR *FileName = new WCHAR[strlen(cFileName)+1]; int size = strlen(cFileName)*sizeof(WCHAR)+1; MultiByteToWideChar(CP_ACP, 0, cFileName, -1, FileName, size); // Inicializamos GDI+. HBITMAP hBitmap = 0; ULONG_PTR gdiplusToken; char GdiPlusStartupInput[16] = {1,0}; if(!GdiplusStartup(&gdiplusToken, GdiPlusStartupInput, NULL)){ HANDLE GBitmap = 0; GdipCreateBitmapFromFile(FileName, &GBitmap); GdipCreateHBITMAPFromBitmap(GBitmap, &hBitmap, 0); GdipDisposeImage(GBitmap); // Cerramos GDI+ GdiplusShutdown(gdiplusToken); } delete FileName; return hBitmap; }
Y este segundo método con GDI+ Flat API en delphi:
delphi
function GdiplusStartup(var GdiToken: DWORD; Startup, Output: PBYTE): DWORD; stdcall external 'gdiplus'; function GdipCreateBitmapFromFile(lpFileName: PWCHAR; var GBitmap: THANDLE): DWORD; stdcall external 'gdiplus'; function GdipCreateHBITMAPFromBitmap(GBitmap: THANDLE; var hBitmap: HBITMAP; BKColor: DWORD): DWORD; stdcall external 'gdiplus'; procedure GdiplusShutdown(GdiToken: DWORD); stdcall external 'gdiplus'; function CreateHBITMAPFromFile(cFileName: PCHAR): HBITMAP; var FileName: array of WCHAR; size: integer; gdiplusToken: DWORD; GdiPlusStartupInput: array[0..2] of int64; GBitmap: THANDLE; begin Result:= 0; // Pasamos a Unicode SetLength(FileName, lstrlen(cFileName)+1); size:= lstrlen(cFileName)*sizeof(WCHAR)+1; MultiByteToWideChar(CP_ACP, 0, cFileName, -1, @FileName[0], size); // Inicializamos GDI+. GdiPlusStartupInput[0]:= 1; GdiPlusStartupInput[1]:= 0; if GdiplusStartup(gdiplusToken, @GdiPlusStartupInput, nil) = 0 then begin GdipCreateBitmapFromFile(PWCHAR(FileName), GBitmap); GdipCreateHBITMAPFromBitmap(GBitmap, Result, 0); GdipDisposeImage(GBitmap); // Cerramos GDI+ GdiplusShutdown(gdiplusToken); end; end;
Ejemplos de código:
cpp
Image1->Picture->Bitmap->Handle = CreateHBITMAPFromFile("Image.png");
cpp
Image1.Picture.Bitmap.Handle:= CreateHBITMAPFromFile('Image.png');
Espero que la información y el código os sea de utilidad.
Saludos.
Edito para cambiar etiquetas de código