Es posible que en nuestro archivo de recursos tengamos imágenes en formatos gráficos que no sean Bitmap (png, jpg...) y deseemos cargarlos como una imagen desde ese archivo.
Imaginemos que tenemos un archivo rc como este:
Imagen1 RCDATA "Imagen1.png" Imagen2 RCDATA "Imagen2.jpg"
Y lo compilamos como un archivo.res para incluir en nuestro ejecutable.
Para extraer las imágenes podemos crear los archivos correspondientes o cargarlas directamente de memoria sin necesidad de un archivo intermedio. La forma de actuar con al API sería así:
uses Winapi.Windows, Winapi.ActiveX; // GDI+ Flat API... function GdiplusStartup(var GdiToken: ULONG_PTR; Startup, Output: PBYTE): Cardinal; stdcall external 'gdiplus'; procedure GdiplusShutdown(GdiToken: ULONG_PTR); stdcall external 'gdiplus'; function GdipCreateHBITMAPFromBitmap(GBitmap: THANDLE; var hBitmap: HBITMAP; BKColor: DWORD): DWORD; stdcall external 'gdiplus'; function GdipCreateBitmapFromStream(stream: ISTREAM; var GBitmap: THANDLE): Cardinal; stdcall external 'gdiplus'; function GdipDisposeImage(image: THANDLE): Cardinal; stdcall external 'gdiplus'; type TGdiplusStartupInput = record GdiplusVersion: UINT32; DebugEventCallback: Pointer; SuppressBackgroundThread: BOOL; SuppressExternalCodecs: BOOL; end; implementation {$R MiArchivo.res} function CreateHBITMAPFromRCDATAResurce(FileName: PWCHAR):HBITMAP; const RT_RCDATAW: PWCHAR = MakeIntResourceW(10); var Res: HRSRC; Size: DWORD; hMem: HGLOBAL; pImage: Pointer; GBitmap: THANDLE; Stream: IStream; gdiplusToken: ULONG_PTR; GdiPlusStartupInput: TGdiplusStartupInput; begin // Inicializamos GDI+. GdiPlusStartupInput.GdiplusVersion:= 1; GdiPlusStartupInput.DebugEventCallback:= nil; GdiPlusStartupInput.SuppressBackgroundThread:= FALSE; GdiPlusStartupInput.SuppressExternalCodecs:= FALSE; GdiplusStartup(gdiplusToken, @GdiPlusStartupInput, nil); Result:= 0; Res:= FindResourceW(0, FileName, RT_RCDATAW);//MAKEINTRESOURCEW(10)); if Res <> 0 then begin Size:= SizeofResource(0, Res); hMem:= GlobalAlloc(GMEM_MOVEABLE, Size); pImage:= GlobalLock(hMem); CopyMemory(pImage, LockResource(LoadResource(0, Res)), Size); GlobalUnlock(hMem); CreateStreamOnHGlobal(hMem, true, Stream); GdipCreateBitmapFromStream(Stream, GBitmap); GdipCreateHBITMAPFromBitmap(GBitmap, Result, 0); GdipDisposeImage(GBitmap); GlobalFree(hMem); end; // Shutdown GDI+ GdiplusShutdown(gdiplusToken); end;
Y un ejemplo de uso:
begin Image1.Picture.Bitmap.Handle:= CreateHBITMAPFromRCDATAResurce('Imagen1'); end;
El ejemplo está desarrollado con Berlin pero funciona en delphi7
¿Por qué usar la API pura y GDI+ Flat? Para economizar recursos y tamaño del ejecutable cuando eso sea lo que prime.
Saludos.