Koro_das_Master
asked on
Loading icons of a specific color depth
Hi,
I'm currently programming an application which shows an icon in the tray. The problem, however, is that any versions of Windows older than ME don't support hi-color icons in the tray, so Windows reduces the color depth of my icon in an ugly fashion (instead of just taking the 4bpp image present in the icon). I'm using LoadImage to load the icon's 16x16 image, however, this function (and LoadIcon neither) does not let me specify the color depth of the icon I want to load.
I've found a temporary solution by defining two icon resources: the original one (which has images of 16x16,32x32,48x48 of 16, 256, and Windows XP alpha-blended colors each) and a copy of the original one containing only the 16-color images, but that's certainly not the best solution.
I'm using Microsoft Visual C++ 6.0 Enterprise on Windows 2000 with the latest Platform SDK
The app must run on Windows 98, Windows NT 4.0 with IE4 + Desktop Update
I'm currently programming an application which shows an icon in the tray. The problem, however, is that any versions of Windows older than ME don't support hi-color icons in the tray, so Windows reduces the color depth of my icon in an ugly fashion (instead of just taking the 4bpp image present in the icon). I'm using LoadImage to load the icon's 16x16 image, however, this function (and LoadIcon neither) does not let me specify the color depth of the icon I want to load.
I've found a temporary solution by defining two icon resources: the original one (which has images of 16x16,32x32,48x48 of 16, 256, and Windows XP alpha-blended colors each) and a copy of the original one containing only the 16-color images, but that's certainly not the best solution.
I'm using Microsoft Visual C++ 6.0 Enterprise on Windows 2000 with the latest Platform SDK
The app must run on Windows 98, Windows NT 4.0 with IE4 + Desktop Update
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi,
I found a solution myself. I have not tested it yet, but I'm pretty sure it should work.
I post it here so it might help other people who might have the same problem.
I've coded a LoadIconEx() function that allows specifying the color depth of the icon to be loaded
-- iconex.h --
#pragma pack( push )
#pragma pack( 2 )
typedef struct
{
BYTE bWidth; // Width, in pixels, of the image
BYTE bHeight; // Height, in pixels, of the image
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
BYTE bReserved; // Reserved
WORD wPlanes; // Color Planes
WORD wBitCount; // Bits per pixel
DWORD dwBytesInRes; // how many bytes in this resource?
WORD nID; // the ID
} GRPICONDIRENTRY, *LPGRPICONDIRENTRY;
typedef struct
{
WORD idReserved; // Reserved (must be 0)
WORD idType; // Resource type (1 for icons)
WORD idCount; // How many images?
GRPICONDIRENTRY idEntries[1]; // The entries for each image
} GRPICONDIR, *LPGRPICONDIR;
#pragma pack( pop )
HICON LoadIconEx(HINSTANCE, LPCTSTR, int, int, int);
-- iconex.cpp --
#include <windows.h>
#include <math.h> // For the pow() function
#include "iconex.h"
// LoadIconEx: Loads an icon with a specific size and color depth. This function
// will NOT try to strech or take an icon of another color depth if none is
// present.
HICON LoadIconEx(HINSTANCE hInstance, LPCTSTR lpszName, int cx, int cy, int uColors)
{
HRSRC hRsrcIconGroup;
// Load the icon group of the desired icon
if (!(hRsrcIconGroup=FindReso urce(hInst ance,lpszN ame,RT_GRO UP_ICON)))
return NULL;
// Look for the specified color depth
// Load the resource
GRPICONDIR* pGrpIconDir;
HRSRC hGlobalIconDir;
if (!(hGlobalIconDir=LoadReso urce(hInst ance,hRsrc IconGroup) ))
return NULL;
// Lock the resource
if (!(pGrpIconDir=(GRPICONDIR *) LockResource(hGlobalIconDi r)))
return NULL;
// Cycle through all icon images trying to find the one we're looking for
int i;
BOOL bFound=FALSE;
// In case of 8ppp or higher, the bColorCount of the structure is 0, and we
// must find our icon with the wPlanes and wBitCount. So if the requested
// number of colors is >=256, we calculate using those fields
if (uColors>=256)
{
for (i=0;i<pGrpIconDir->idCoun t;i++)
{
// Color depth is always (bit count)*(plane count)
// So color count is always (2^(color depth))
if (uColors==pow(2,(pGrpIconD ir->idEntr ies[i].wPl anes*
pGrpIconDir->idEntries[i]. wBitCount) ))
{
if ((pGrpIconDir->idEntries[i ].bWidth== cx)&&
(pGrpIconDir->idEntries[i] .bHeight== cy)) // Do the size match?
{
bFound=TRUE; // Yes, it matches
break;
}
}
}
}
else
{
for (i=0;i<pGrpIconDir->idCoun t;i++)
{
if (pGrpIconDir->idEntries[i] .bColorCou nt==uColor s) // Do the color count match?
{
if ((pGrpIconDir->idEntries[i ].bWidth== cx)&&
(pGrpIconDir->idEntries[i] .bHeight== cy)) // Do the size match?
{
bFound=TRUE; // Yes, it matches
break;
}
}
}
}
if (!bFound)
return NULL; // No icon was found matching the specs
// Icon was found! i contains the index to the GRPICONDIR structure in the
// icon group. Find the ID of the icon
int nID;
nID=pGrpIconDir->idEntries [i].nID;
// Now, find the actual icon resource
HRSRC hRsrcIcon;
HRSRC hGlobalIcon;
void* pIconBits;
if (!(hRsrcIcon=FindResource( hInstance, MAKEINTRES OURCE(nID) ,RT_ICON)) )
return NULL;
if (!(hGlobalIcon=LoadResourc e(hInstanc e,hRsrcIco n)))
return NULL;
if (!(pIconBits=LockResource( hGlobalIco n)))
return NULL;
// Now, use CreateIconFromResourceEx to create the actual HICON
return CreateIconFromResourceEx(
(unsigned char*) pIconBits, // Pointer to icon data
pGrpIconDir->idEntries[i]. dwBytesInR es, // Size of icon data
TRUE, // TRUE to create an icon, not a cursor
0x00030000, // Version number. MSDN says to put that number
cx, cy, // Width and height
0); // Flags (none)
}
-- end --
As for the points, DanRollins, even if your answer was not the one I was looking for, I liked a lot the links you've given me, so if you want them, just ask me, else I'll get them refunded.
I found a solution myself. I have not tested it yet, but I'm pretty sure it should work.
I post it here so it might help other people who might have the same problem.
I've coded a LoadIconEx() function that allows specifying the color depth of the icon to be loaded
-- iconex.h --
#pragma pack( push )
#pragma pack( 2 )
typedef struct
{
BYTE bWidth; // Width, in pixels, of the image
BYTE bHeight; // Height, in pixels, of the image
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
BYTE bReserved; // Reserved
WORD wPlanes; // Color Planes
WORD wBitCount; // Bits per pixel
DWORD dwBytesInRes; // how many bytes in this resource?
WORD nID; // the ID
} GRPICONDIRENTRY, *LPGRPICONDIRENTRY;
typedef struct
{
WORD idReserved; // Reserved (must be 0)
WORD idType; // Resource type (1 for icons)
WORD idCount; // How many images?
GRPICONDIRENTRY idEntries[1]; // The entries for each image
} GRPICONDIR, *LPGRPICONDIR;
#pragma pack( pop )
HICON LoadIconEx(HINSTANCE, LPCTSTR, int, int, int);
-- iconex.cpp --
#include <windows.h>
#include <math.h> // For the pow() function
#include "iconex.h"
// LoadIconEx: Loads an icon with a specific size and color depth. This function
// will NOT try to strech or take an icon of another color depth if none is
// present.
HICON LoadIconEx(HINSTANCE hInstance, LPCTSTR lpszName, int cx, int cy, int uColors)
{
HRSRC hRsrcIconGroup;
// Load the icon group of the desired icon
if (!(hRsrcIconGroup=FindReso
return NULL;
// Look for the specified color depth
// Load the resource
GRPICONDIR* pGrpIconDir;
HRSRC hGlobalIconDir;
if (!(hGlobalIconDir=LoadReso
return NULL;
// Lock the resource
if (!(pGrpIconDir=(GRPICONDIR
return NULL;
// Cycle through all icon images trying to find the one we're looking for
int i;
BOOL bFound=FALSE;
// In case of 8ppp or higher, the bColorCount of the structure is 0, and we
// must find our icon with the wPlanes and wBitCount. So if the requested
// number of colors is >=256, we calculate using those fields
if (uColors>=256)
{
for (i=0;i<pGrpIconDir->idCoun
{
// Color depth is always (bit count)*(plane count)
// So color count is always (2^(color depth))
if (uColors==pow(2,(pGrpIconD
pGrpIconDir->idEntries[i].
{
if ((pGrpIconDir->idEntries[i
(pGrpIconDir->idEntries[i]
{
bFound=TRUE; // Yes, it matches
break;
}
}
}
}
else
{
for (i=0;i<pGrpIconDir->idCoun
{
if (pGrpIconDir->idEntries[i]
{
if ((pGrpIconDir->idEntries[i
(pGrpIconDir->idEntries[i]
{
bFound=TRUE; // Yes, it matches
break;
}
}
}
}
if (!bFound)
return NULL; // No icon was found matching the specs
// Icon was found! i contains the index to the GRPICONDIR structure in the
// icon group. Find the ID of the icon
int nID;
nID=pGrpIconDir->idEntries
// Now, find the actual icon resource
HRSRC hRsrcIcon;
HRSRC hGlobalIcon;
void* pIconBits;
if (!(hRsrcIcon=FindResource(
return NULL;
if (!(hGlobalIcon=LoadResourc
return NULL;
if (!(pIconBits=LockResource(
return NULL;
// Now, use CreateIconFromResourceEx to create the actual HICON
return CreateIconFromResourceEx(
(unsigned char*) pIconBits, // Pointer to icon data
pGrpIconDir->idEntries[i].
TRUE, // TRUE to create an icon, not a cursor
0x00030000, // Version number. MSDN says to put that number
cx, cy, // Width and height
0); // Flags (none)
}
-- end --
As for the points, DanRollins, even if your answer was not the one I was looking for, I liked a lot the links you've given me, so if you want them, just ask me, else I'll get them refunded.
Yes, I would like the points. Thanks.
- Dan
- Dan
ASKER
Thanks for the comment, however, I'm not trying to circumvent this limitation, I'm looking for a way to load an icon image of a specific color depth, because even if LoadImage lets me specify the size I want to load, there's no API I know of which lets me specify the color depth.
p.s. Thanks for the LoadImage tip, I shall be careful about that.