I have modified all the functions to create an icon or a bitmap. It defaults to icon, but there are two optional parameters imageType (IMAGE_ICON or IMAGE_BITMAP) and clrBackground )the background color of the bitmap). The names of the functions now begin with AfxImage instead of AfxIcon.
This is the new include file so far:
' ########################################################################################
' Microsoft Windows
' File: AfxGdiplus.bas
' Content: Gdi Plus wrapper functions
' Compiler: Free Basic
' Freeware. Use at your own risk.
' Copyright (c) 2016 Jose Roca. All Rights Reserved.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#pragma once
#include once "windows.bi"
#ifdef __FB_64BIT__
#inclib "gdiplus"
#include "win/gdiplus-c.bi"
#else
#include once "win/gdiplus.bi"
using gdiplus
#endif
NAMESPACE Afx.Gdiplus
UNION GDIP_BGRA
color AS DWORD
TYPE
blue AS UBYTE
green AS UBYTE
red AS UBYTE
alpha AS UBYTE
END TYPE
END UNION
' ========================================================================================
' Returns an ARGB color value initialized with the specified values for the alpha, red,
' green, and blue components.
' ========================================================================================
FUNCTION GDIP_ARGB (BYVAL a AS UBYTE, BYVAL r AS UBYTE, BYVAL g AS UBYTE, BYVAL b AS UBYTE) AS DWORD
DIM clr AS GDIP_BGRA
clr.alpha = a : clr.red = r : clr.green = g : clr.blue = b
FUNCTION = clr.color
END FUNCTION
' ========================================================================================
' ========================================================================================
' Returns an XRGB color value initialized with the specified values for the red, green,
' and blue components.
' ========================================================================================
FUNCTION GDIP_XRGB (BYVAL r AS UBYTE, BYVAL g AS UBYTE, BYVAL b AS UBYTE) AS DWORD
FUNCTION = GDIP_ARGB(&HFF, r, g, b)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Returns a BGRA color value initialized with the specified values for the blue, green,
' red and alpha components.
' ========================================================================================
FUNCTION GDIP_BGRA (BYVAL b AS UBYTE, BYVAL g AS UBYTE, BYVAL r AS UBYTE, BYVAL a AS UBYTE) AS DWORD
DIM clr AS GDIP_BGRA
clr.blue = b : clr.green = g : clr.red = r : clr.alpha = a
FUNCTION = clr.color
END FUNCTION
' ========================================================================================
' ========================================================================================
' Returns an RGBA color value initialized with the specified values for the red, green,
' blue and alpha components.
' ========================================================================================
FUNCTION GDIP_RGBA (BYVAL r AS UBYTE, BYVAL g AS UBYTE, BYVAL b AS UBYTE, BYVAL a AS UBYTE) AS DWORD
FUNCTION = GDIP_ARGB(a, r, g, b)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Returns the version of Gdiplus.dll, e.g. 601 for version 6.01.
' ========================================================================================
FUNCTION AfxGdipDllVersion () AS LONG
DIM pvsffi AS VS_FIXEDFILEINFO PTR
DIM pVerInfo AS HANDLE, dwHandle AS DWORD, dwVersion AS DWORD
DIM cbLen AS DWORD, wMajor AS WORD, wMinor AS WORD
cbLen = GetFileVersionInfoSizeW("GDIPLUS.DLL", @dwHandle)
IF cbLen = 0 THEN RETURN NULL
pVerInfo = HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, cbLen)
IF pVerInfo = NULL THEN RETURN NULL
IF GetFileVersionInfoW("GDIPLUS.DLL", dwHandle, cbLen, pVerInfo) THEN
IF VerQueryValueW(pVerInfo, "\", @pvsffi, @cbLen) THEN
wMajor = HIWORD(pvsffi->dwFileVersionMS)
wMinor = LOWORD(pvsffi->dwFileVersionMS)
END IF
END IF
HeapFree GetProcessHeap, 0, pVerInfo
FUNCTION = (wMajor + wMinor / 100) * 100
END FUNCTION
' ========================================================================================
' ========================================================================================
' Initilizes GDI+
' Returns a token. Pass the token to GdiplusShutdown when you have finished using GDI+.
' ========================================================================================
FUNCTION AfxGdipInit (BYVAL version AS UINT32 = 1) AS ULONG_PTR
DIM hStatus AS GpStatus, token AS ULONG_PTR, StartupInput AS GdiplusStartupInput
StartupInput.GdiplusVersion = version
hStatus = GdiplusStartup(@token, @StartupInput, NULL)
FUNCTION = token
END FUNCTION
' ========================================================================================
' ========================================================================================
' Loads an image from a file using GDI+, converts it to an icon or bitmap and returns the handle.
' Parameters:
' - wszFileName = [in] Path of the image to load and convert.
' - dimPercent = Percent of dimming (1-99)
' - bGrayScale = TRUE or FALSE. Convert to gray scale.
' - imageType = IMAGE_ICON or IMAGE_BITMAP.
' - clrBackground = [in] The background color. This parameter is ignored if the image type
' is IMAGE_ICON or the bitmap is totally opaque.
' Return Value:
' If the function succeeds, the return value is the handle of the created icon or bitmap.
' If the function fails, the return value is NULL.
' ========================================================================================
FUNCTION AfxGdipImageFromFileEx (BYREF wszFileName AS WSTRING, _
BYVAL dimPercent AS LONG = 0, BYVAL bGrayScale AS LONG = FALSE, _
BYVAL imageType AS LONG = IMAGE_ICON, BYVAL clrBackground AS ARGB = 0) AS HANDLE
DIM token AS ULONG_PTR, pImage AS GpImage PTR, hImage AS HANDLE
DIM ImageWidth AS LONG, ImageHeight AS LONG, x AS LONG, y AS LONG
DIM pixColor AS GDIP_BGRA, iColor AS LONG, rFactor AS SINGLE
' // Initialize Gdiplus
token = AfxGdipInit
IF token = NULL THEN EXIT FUNCTION
' // Load the image from file
GdipLoadImageFromFile(wszFileName, @pImage)
IF pImage = NULL THEN EXIT FUNCTION
' // Get the image width and height
GdipGetImageWidth(pImage, @ImageWidth)
GdipGetImageHeight(pImage, @ImageHeight)
' // Dim or/and gray the image
IF dimPercent > 0 AND dimPercent < 100 THEN rFactor = dimPercent / 100
IF rFactor <> 0 OR bGrayScale <> 0 THEN
FOR y = 0 TO ImageWidth - 1
FOR x = 0 TO ImageHeight - 1
' // Get the pixel color
GdipBitmapGetPixel(CAST(GpBitmap PTR, pImage), x, y, @pixColor.color)
IF dimPercent > 0 THEN
pixColor.red = (255 - pixColor.red) * rFactor + pixColor.red
pixColor.green = (255 - pixColor.green) * rFactor + pixColor.green
pixColor.blue = (255 - pixColor.blue) * rFactor + pixColor.blue
END IF
IF bGrayScale THEN
' Note: The sum of the percentages for the three colors should add tp up 1
iColor = 0.299 * pixColor.red + 0.587 * pixColor.green + 0.114 * pixColor.blue
pixColor.Color = GDIP_BGRA (iColor, iColor, iColor, pixColor.alpha)
ELSE
pixColor.color = GDIP_ARGB(pixColor.alpha, pixColor.red, pixColor.green, pixColor.Blue)
END IF
' // Set the modified pixel color
GdipBitmapSetPixel(CAST(GpBitmap PTR, pImage), x, y, pixColor.color)
NEXT
NEXT
END IF
' // Crete icon from image
IF imageType = IMAGE_ICON THEN
GdipCreateHICONFromBitmap(CAST(GpBitmap PTR, pImage), @hImage)
ELSE
GdipCreateHBITMAPFromBitmap(CAST(GpBitmap PTR, pImage), @hImage, clrBackground)
END IF
' // Free the image
IF pImage THEN GdipDisposeImage pImage
' // Shut down Gdiplus
GdiplusShutdown token
' // Return the handle of the icon
FUNCTION = hImage
END FUNCTION
' ========================================================================================
' ========================================================================================
' Converts an image stored in a buffer into an icon or bitmap and returns the handle.
' Parameters:
' - pBuffer = [in] Pointer to the buffer
' - bufferSize = Size of the buffer
' - imageType = IMAGE_ICON or IMAGE_BITMAP.
' - clrBackground = [in] The background color. This parameter is ignored if the image type
' is IMAGE_ICON or the bitmap is totally opaque.
' Return Value:
' If the function succeeds, the return value is the handle of the created icon or bitmap.
' If the function fails, the return value is NULL.
' Usage example:
' DIM wszFileName AS WSTRING * MAX_PATH
' wszFileName = ExePath & "\arrow_left_256.png"
' DIM bufferSize AS SIZE_T_
' DIM nFile AS LONG
' nFile = FREEFILE
' OPEN wszFileName FOR BINARY AS nFile
' IF ERR THEN EXIT FUNCTION
' bufferSize = LOF(nFile)
' DIM pBuffer AS UBYTE PTR
' pBuffer = CAllocate(1, bufferSize)
' GET #nFile, , *pBuffer, bufferSize
' CLOSE nFile
' IF pBuffer THEN
' ImageList_ReplaceIcon(hImageList, -1, AfxGdipImageFromBuffer(pBuffer, ImageSize))
' DeAllocate(pBuffer)
' END IF
' ========================================================================================
FUNCTION AfxGdipImageFromBuffer (BYVAL pBuffer AS ANY PTR, BYVAL bufferSize AS SIZE_T_, _
BYVAL imageType AS LONG = IMAGE_ICON, BYVAL clrBackground AS ARGB = 0) AS HANDLE
DIM token AS ULONG_PTR, pImage AS GpImage PTR, hImage AS HANDLE
DIM ImageWidth AS LONG, ImageHeight AS LONG, x AS LONG, y AS LONG
DIM pixColor AS GDIP_BGRA, iColor AS LONG, rFactor AS SINGLE
DIM pImageStream AS IStream PTR, hGlobal AS HGLOBAL, pGlobalBuffer AS LPVOID
' // Initialize Gdiplus
token = AfxGdipInit
IF token = NULL THEN EXIT FUNCTION
' // Allocate memory to hold the image
hGlobal = GlobalAlloc(GMEM_MOVEABLE, bufferSize)
IF hGlobal THEN
' // Lock the memory
pGlobalBuffer = GlobalLock(hGlobal)
IF pGlobalBuffer THEN
' // Copy the image from the binary string file to global memory
CopyMemory(pGlobalBuffer, pBuffer, bufferSize)
' // Create an stream in global memory
IF CreateStreamOnHGlobal(hGlobal, FALSE, @pImageStream) = S_OK THEN
IF pImageStream THEN
' // Create a bitmap from the data contained in the stream
GdipCreateBitmapFromStream(pImageStream, CAST(GpBitmap PTR PTR, @pImage))
' // Crete icon from image
IF imageType = IMAGE_ICON THEN
GdipCreateHICONFromBitmap(CAST(GpBitmap PTR, pImage), @hImage)
ELSE
GdipCreateHBITMAPFromBitmap(CAST(GpBitmap PTR, pImage), @hImage, clrBackground)
END IF
' // Free the image
IF pImage THEN GdipDisposeImage pImage
pImageStream->lpVtbl->Release(pImageStream)
END IF
END IF
' // Unlock the memory
GlobalUnlock pGlobalBuffer
END IF
' // Free the memory
GlobalFree hGlobal
END IF
' // Shut down Gdiplus
GdiplusShutdown token
' // Return the handle of the icon
FUNCTION = hImage
END FUNCTION
' ========================================================================================
' ========================================================================================
' Loads an image from a file, converts it to an icon or bitmap and returns the handle.
' Parameters:
' - wszFileName = [in] Path of the image to load and convert.
' - imageType = IMAGE_ICON or IMAGE_BITMAP.
' - clrBackground = [in] The background color. This parameter is ignored if the image type
' is IMAGE_ICON or the bitmap is totally opaque.
' Return Value:
' If the function succeeds, the return value is the handle of the created icon or bitmap.
' If the function fails, the return value is NULL.
' ========================================================================================
FUNCTION AfxGdipImageFromFile (BYREF wszFileName AS WSTRING, _
BYVAL imageType AS LONG = IMAGE_ICON, BYVAL clrBackground AS ARGB = 0) AS HICON
DIM fd AS WIN32_FIND_DATAW
DIM hFind AS HANDLE
' // Check for the existence of the file
IF LEN(wszFileName) = 0 THEN EXIT FUNCTION
hFind = FindFirstFileW(@wszFileName, @fd)
IF hFind = INVALID_HANDLE_VALUE THEN EXIT FUNCTION
FindClose hFind
' // Make sure that is not a directory or a temporary file
IF (fd.dwFileAttributes AND FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY OR _
(fd.dwFileAttributes AND FILE_ATTRIBUTE_TEMPORARY) = FILE_ATTRIBUTE_TEMPORARY THEN
EXIT FUNCTION
END IF
' // Open the file and store its contents into a buffer
DIM nFile AS LONG, bufferSize AS SIZE_T_
nFile = FREEFILE
OPEN wszFileName FOR BINARY AS nFile
IF ERR THEN EXIT FUNCTION
bufferSize = LOF(nFile)
DIM pBuffer AS UBYTE PTR
pBuffer = CAllocate(1, bufferSize)
GET #nFile, , *pBuffer, bufferSize
CLOSE nFile
IF pBuffer THEN
FUNCTION = AfxGdipImageFromBuffer(pBuffer, bufferSize, imageType, clrBackground)
DeAllocate(pBuffer)
END IF
END FUNCTION
' ========================================================================================
' ========================================================================================
' Loads an image from a resource, converts it to an icon or bitmap and returns the handle.
' Parameter:
' - hInstance = [in] A handle to the module whose portable executable file or an accompanying
' MUI file contains the resource. If this parameter is NULL, the function searches
' the module used to create the current process.
' - wszImage = [in] Name of the image in the resource file (.RES). If the image resource uses
' an integral identifier, wszImage should begin with a number symbol (#)
' followed by the identifier in an ASCII format, e.g., "#998". Otherwise,
' use the text identifier name for the image. Only images embedded as raw data
' (type RCDATA) are valid. These must be icons in format .png, .jpg, .gif, .tiff.
' - imageType = IMAGE_ICON or IMAGE_BITMAP.
' - clrBackground = [in] The background color. This parameter is ignored if the image type
' is IMAGE_ICON or the bitmap is totally opaque.
' Return Value:
' If the function succeeds, the return value is the handle of the created icon or bitmap.
' If the function fails, the return value is NULL.
' ========================================================================================
FUNCTION AfxGdipImageFromRes (BYVAL hInstance AS HINSTANCE, BYREF wszImage AS WSTRING, _
BYVAL imageType AS LONG = IMAGE_ICON, BYVAL clrBackground AS ARGB = 0) AS HANDLE
DIM token AS ULONG_PTR, pImage AS GpImage PTR, hImage AS HANDLE
DIM hRes AS HRSRC, pResData AS HRSRC, wID AS WORD, dwID AS DWORD, imageSize AS DWORD
DIM pImageStream AS IStream PTR, hGlobal AS HGLOBAL, pGlobalBuffer AS LPVOID
' // Initialize Gdiplus
token = AfxGdipInit
IF token = NULL THEN EXIT FUNCTION
' // Find the resource
IF LEFT(wszImage, 1) = "#" THEN
wID = VAL(MID(wszImage, 2))
dwID = MAKELONG(wID, 0)
hRes = FindResourceW(hInstance, MAKEINTRESOURCEW(dwID), CAST(LPCWSTR, RT_RCDATA))
ELSE
hRes = FindResourceW(hInstance, wszImage, CAST(LPCWSTR, RT_RCDATA))
END IF
IF hRes THEN
' // Retrieve the size of the image
imageSize = SizeofResource(hInstance, hRes)
IF imageSize THEN
' // Load the resource and get a pointer to the resource data.
' // Note: LockResource does not actually lock memory; it is just used
' // to obtain a pointer to the memory containing the resource data.
pResData = LockResource(LoadResource(hInstance, hRes))
IF pResData THEN
' // Allocate memory to hold the image
hGlobal = GlobalAlloc(GMEM_MOVEABLE, imageSize)
IF hGlobal THEN
' // Lock the memory
pGlobalBuffer = GlobalLock(hGlobal)
IF pGlobalBuffer THEN
' // Copy the image from the binary string file to global memory
CopyMemory(pGlobalBuffer, pResData, imageSize)
' // Create an stream in global memory
IF CreateStreamOnHGlobal(hGlobal, FALSE, @pImageStream) = S_OK THEN
IF pImageStream THEN
' // Create a bitmap from the data contained in the stream
GdipCreateBitmapFromStream(pImageStream, CAST(GpBitmap PTR PTR, @pImage))
' // Crete icon from image
IF imageType = IMAGE_ICON THEN
GdipCreateHICONFromBitmap(CAST(GpBitmap PTR, pImage), @hImage)
ELSE
GdipCreateHBITMAPFromBitmap(CAST(GpBitmap PTR, pImage), @hImage, clrBackground)
END IF
' // Free the image
IF pImage THEN GdipDisposeImage pImage
pImageStream->lpVtbl->Release(pImageStream)
END IF
END IF
' // Unlock the memory
GlobalUnlock pGlobalBuffer
END IF
' // Free the memory
GlobalFree hGlobal
END IF
END IF
END IF
END IF
' // Shut down Gdiplus
GdiplusShutdown token
' // Return the handle of the icon
FUNCTION = hImage
END FUNCTION
' ========================================================================================
END NAMESPACE