I have a number of third party controls in my application. Some of them support 32bpp icons and some don't. So, wanting it to look as good as it is able to, I thought I'd used 32bpp icons where I could, but include lower bit depths in the icon file for use where they weren't supported. All I'd need is a way to extract a particular icon from my icon resource. Simple, eh?
Well, depleting my Google-fu quite considerably, told me no, it isn't simple. It is in fact, absurdly complicated. Nevertheless, after a few hours of trial-and-error, I came up with a function that gave me what I needed:
HICON LoadResourceIcon(UINT nResID, BYTE nWidth, BYTE nHeight, SHORT nBitDepth)
{
HICON hIconRet = NULL;
#pragma pack(2)
struct IcoMemEntry {
byte Width; byte Height; byte ColorCount; byte Reserved; short Planes; short BitCount; int BytesInRes; short ID; };
struct IcoHeader
{
short Reserved; short Type; short Count; IcoMemEntry Entries; };
#pragma pack()
HMODULE hModule = AfxGetInstanceHandle();
HRSRC hRes = ::FindResource(hModule, MAKEINTRESOURCE(nResID), RT_GROUP_ICON);
HGLOBAL hGlobal = ::LoadResource(hModule, hRes);
IcoHeader* pHead = (IcoHeader*)::LockResource(hGlobal);
if (pHead->Count != 0)
{
IcoMemEntry* pEntries = NULL;
pEntries = new IcoMemEntry[pHead->Count];
IcoMemEntry* pEntry = &(pHead->Entries);
CopyMemory(pEntries, pEntry, sizeof(IcoMemEntry) * pHead->Count);
for (int i = 0; i < pHead->Count; i++)
{
if (pEntries[i].Width == nWidth && pEntries[i].Height == nHeight &&
pEntries[i].BitCount == nBitDepth)
{
HRSRC hIconInfo = ::FindResource(hModule, MAKEINTRESOURCE(pEntry[i].ID),
MAKEINTRESOURCE(RT_ICON));
HGLOBAL hIconRes = ::LoadResource(hModule, hIconInfo);
BYTE* dibBits = (BYTE*)::LockResource(hIconRes);
long szLength = ::SizeofResource(hModule, hIconInfo);
hIconRet = CreateIconFromResourceEx((PBYTE) dibBits, szLength, TRUE, 0x00030000,
nWidth, nHeight, LR_DEFAULTCOLOR);
::DestroyIcon((HICON)dibBits);
break;
}
}
if (pEntries != NULL)
{
delete[] pEntries;
}
}
::DestroyIcon((HICON)pHead);
return hIconRet;
}