I recently had to find a way to load an image from resources without using LoadImage as that function is not available in Win9x using the LOAD_LIBRARY_AS_DATAFILE flag of LoadLibraryEx. Here is the code, it requires a module handle (obtained from LoadLibraryEx) a resource identifier, a resource type (RT_BITMAP always) and a pointer to a DWORD buffer to receive the number of colors. It returns a valid DDB bitmap handle:
LoadResourceImage proc hModule:DWORD, pResName:DWORD, ResTypeNumber:DWORD, pcColors:DWORD

LOCAL hFindRes :DWORD
LOCAL hResData :DWORD
LOCAL pResData :DWORD
LOCAL hDC :DWORD
LOCAL cbBits :DWORD

invoke FindResource, hModule, pResName, ResTypeNumber
mov hFindRes,eax
invoke LoadResource,hModule,hFindRes
mov hResData,eax
invoke LockResource,hResData
mov pResData,eax

mov edi,pResData
movzx ecx,[edi].BITMAPINFO.bmiHeader.biBitCount
mov cbBits,ecx
.IF pcColors
mov eax,pcColors
mov [eax],ecx
.ENDIF

invoke GetDC,hDlg
mov hDC,eax

mov ecx,cbBits
mov eax,1
shl eax,cl
mov edx,SIZEOF RGBQUAD
imul edx
.IF cbBits >= 24 ; There is no RGBQUAD array for 24 bit
mov eax,0
.ENDIF
add eax,SIZEOF BITMAPINFOHEADER
add eax,pResData

invoke CreateDIBitmap, hDC, edi, CBM_INIT, eax, edi, DIB_RGB_COLORS
push eax
invoke ReleaseDC,hDlg,hDC
pop eax
ret
LoadResourceImage endp
EDIT put in some spaces to have the formatting correct.
Posted on 2003-09-02 14:45:11 by donkey
To continue, you also have to be able to load an icon or a cursor as well. To do this without LoadImage is actually easier than the bitmap method, it requires the same parameters as the bitmap version but uses either RT_CURSOR or RT_ICON as the resource types
LoadResourceIcon proc hModule:DWORD, pResName:DWORD, ResTypeNumber:DWORD

LOCAL hFindRes :DWORD
LOCAL hResData :DWORD
LOCAL pResData :DWORD
LOCAL ResSize :DWORD

invoke FindResource, hModule, pResName, ResTypeNumber
mov hFindRes,eax
invoke SizeofResource,hModule,hFindRes
mov ResSize,eax
invoke LoadResource,hModule,hFindRes
mov hResData,eax
invoke LockResource,hResData
mov pResData,eax

.IF ResTypeNumber == RT_ICON
invoke CreateIconFromResource, pResData, ResSize, TRUE, 030000h
.ELSEIF ResTypeNumber == RT_CURSOR
invoke CreateIconFromResource, pResData, ResSize, FALSE, 030000h
.ELSE
mov eax,INVALID_HANDLE_VALUE
.ENDIF
push eax
invoke FreeResource, hResData
pop eax
ret
LoadResourceIcon endp
Posted on 2003-09-02 20:29:01 by donkey
To continue on this subject, this routine will save the resource icon to a previously opened file specified by hFile. You must pass it the identifier to an RT_GROUP_ICON resource.
SaveIconResource proc uses edi esi hModule:DWORD, hFile:DWORD, pResName:DWORD

LOCAL hFindRes :DWORD
LOCAL hResData :DWORD
LOCAL pResData :DWORD
LOCAL ResSize :DWORD
LOCAL iCount :DWORD
LOCAL pOutput :DWORD
LOCAL cbWritten :DWORD
LOCAL cbWrite :DWORD
LOCAL iResName[16] :BYTE
LOCAL StrOffset :DWORD

.IF hFile == INVALID_HANDLE_VALUE
ret
.endif
mov al,"#"
mov iResName,al
invoke FindResource,hModule,pResName,RT_GROUP_ICON
mov hFindRes,eax
invoke SizeofResource,hModule,hFindRes
mov ResSize,eax
invoke LoadResource,hModule,hFindRes
mov hResData,eax
invoke LockResource,hResData
mov pResData,eax
.IF pResData == NULL
ret
.endif

; Calculte the size of the file
mov edi,pResData
xor ecx,ecx
mov cx,[edi].GRPICONDIR.idCount
mov iCount,ecx
add edi,SIZEOF GRPICONDIR
mov eax,SIZEOF GRPICONDIR
.REPEAT
add eax,[edi].GRPICONDIRENTRY.dwBytesInRes
add eax,SIZEOF GRPICONDIRENTRY
add edi,SIZEOF GRPICONDIRENTRY
.UNTILCXZ
mov ecx,iCount
shl ecx,1
add eax,ecx
mov cbWrite,eax
invoke GlobalAlloc,GMEM_FIXED,eax
mov pOutput,eax

mov esi,pResData
mov edi,pOutput
; Copy the header (MemCopy,Source,Dest,#Btyes
invoke MemCopy,pResData,pOutput,SIZEOF GRPICONDIR
; Move the pointers up
add esi,SIZEOF GRPICONDIR
add edi,SIZEOF GRPICONDIR
; Copy the array of Icon dir entries
mov ecx,0
.REPEAT
push ecx
; Copy the icon entry
invoke MemCopy,esi,edi,SIZEOF GRPICONDIRENTRY
; mov the pointers up
add esi,SIZEOF GRPICONDIRENTRY
add edi,SIZEOF GRPICONDIRENTRY
; An extra 2 for the destination index
add edi,2
pop ecx
inc ecx
.UNTIL ecx == iCount

mov ecx,0
; reset the source index to the first GRPICONDIRENTRY
mov esi,pResData
add esi,SIZEOF GRPICONDIR
; reset the Destination index to the first ICONDIRENTRY
mov eax,pOutput
add eax,SIZEOF GRPICONDIR
mov StrOffset,eax
.REPEAT
push ecx
; Get the id of the icon
lea ecx,iResName
inc ecx
movzx eax,[esi].GRPICONDIRENTRY.nID
invoke dwtoa,eax,ecx

; Get a copy of the icon resource
invoke FindResource,hModule,ADDR iResName,RT_ICON
mov hFindRes,eax
invoke SizeofResource,hModule,hFindRes
mov ResSize,eax
invoke LoadResource,hModule,hFindRes
mov hResData,eax
invoke LockResource,hResData
mov pResData,eax

; Copy the icon data to the buffer
invoke MemCopy,pResData,edi,[esi].GRPICONDIRENTRY.dwBytesInRes

; move the offset of this data to the array
mov ecx,edi
sub ecx,pOutput
mov eax,StrOffset
mov [eax].ICONDIRENTRY.dwImageOffset,ecx
add StrOffset,SIZEOF ICONDIRENTRY

; Increment the destination pointer
add edi,[esi].GRPICONDIRENTRY.dwBytesInRes

; Increment the source pointer
add esi,SIZEOF GRPICONDIRENTRY
pop ecx
inc ecx
.UNTIL ecx == iCount

invoke WriteFile,hFile,pOutput,cbWrite,ADDR cbWritten,NULL
invoke GlobalFree,pOutput
ret

SaveIconResource endp
Posted on 2003-09-04 15:26:52 by donkey
To use the icon saver you will require the following structures, they are buried deep at MSDN and rather hard to find:


GRPICONDIR Struct
idReserved WORD ?; Reserved (must be 0)
idType WORD ?; Resource type (1 for icons)
idCount WORD ?; How many images?
GRPICONDIR ends

GRPICONDIRENTRY struct
bWidth BYTE ?; Width, in pixels, of the image
bHeight BYTE ?; Height, in pixels, of the image
bColorCount BYTE ?; Number of colors in image (0 if >=8bpp)
bReserved BYTE ?; Reserved
wPlanes WORD ?; Color Planes
wBitCount WORD ?; Bits per pixel
dwBytesInRes DWORD ?; how many bytes in this resource?
nID WORD ?; the ID
GRPICONDIRENTRY ends

ICONDIR struct
idReserved WORD ? ; Reserved (must be 0)
idType WORD ? ;Resource Type (1 for icons)
idCount WORD ? ;How many images?
ICONDIR ENDS

ICONDIRENTRY struct
bWidth BYTE ? ;Width, in pixels, of the image
bHeight BYTE ? ;Height, in pixels, of the image
bColorCount BYTE ? ;Number of colors in image (0 if >=8bpp)
bReserved BYTE ? ;Reserved ( must be 0)
wPlanes WORD ? ;Color Planes
wBitCount WORD ? ;Bits per pixel
dwBytesInRes DWORD ? ;How many bytes in this resource?
dwImageOffset DWORD ? ;Where in the file is this image?
ICONDIRENTRY ENDS
Note the slight difference between GRPICONDIRENTRY and ICONDIRENTRY, the routine could have been much shorter if it wasn't for the missing WORD in GRPICONDIRENTRY (nID is shorter than dwImageOffset)
Posted on 2003-09-04 15:39:44 by donkey