?
Solved

Loading icons of a specific color depth

Posted on 2003-03-20
4
Medium Priority
?
1,045 Views
Last Modified: 2013-12-03
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
0
Comment
Question by:Koro_das_Master
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
4 Comments
 
LVL 49

Accepted Solution

by:
DanRollins earned 300 total points
ID: 8193771
In this google groups thread, the author tried various ways to get around this and then gave up:

     http://groups.google.com/groups?q=LR_DEFAULTCOLOR+and+XP&start=10&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=Xns93229993D9177sommerfee%40sommerfeldt.net&rnum=11

As his ultimate reason, he gave this link:
    http://www.dr-hoiby.com/TrayIconIn256Color/index.html
which show *how to patch Exploere.exe* (if you can imAGINE!) into order to show 256-color icons in the tray.  The point being, that if someone went to THAT much trouble, then one can assume that it is not feasible using other techniques.

It seems to me that checking OS versions and carrying two sets of icons is not a major hardship.

-- Dan

P.S.  A tip related to using LoadImage rather than LoadIcon:  Remember that if you call it again asking for the same RES ID, a new resource handle gets allocated (while LoadIcon does not have that problem).  I learned this becasue my tray icon changed to match my program status... ten times per second -- can you imagine the eventual chaos!!!?!?!
0
 
LVL 1

Author Comment

by:Koro_das_Master
ID: 8202792
Hi,

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.
0
 
LVL 1

Author Comment

by:Koro_das_Master
ID: 8225077
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=FindResource(hInstance,lpszName,RT_GROUP_ICON)))
        return NULL;

    // Look for the specified color depth

    // Load the resource

    GRPICONDIR* pGrpIconDir;
    HRSRC hGlobalIconDir;

    if (!(hGlobalIconDir=LoadResource(hInstance,hRsrcIconGroup)))
        return NULL;

    // Lock the resource

    if (!(pGrpIconDir=(GRPICONDIR*) LockResource(hGlobalIconDir)))
        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->idCount;i++)
        {
            // Color depth is always (bit count)*(plane count)
            // So color count is always (2^(color depth))
            if (uColors==pow(2,(pGrpIconDir->idEntries[i].wPlanes*
                     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->idCount;i++)
        {
            if (pGrpIconDir->idEntries[i].bColorCount==uColors) // 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,MAKEINTRESOURCE(nID),RT_ICON)))
        return NULL;

    if (!(hGlobalIcon=LoadResource(hInstance,hRsrcIcon)))
        return NULL;

    if (!(pIconBits=LockResource(hGlobalIcon)))
        return NULL;

    // Now, use CreateIconFromResourceEx to create the actual HICON

    return CreateIconFromResourceEx(
        (unsigned char*) pIconBits, // Pointer to icon data
        pGrpIconDir->idEntries[i].dwBytesInRes, // 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.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8225928
Yes, I would like the points.  Thanks.
- Dan
0

Featured Post

Free learning courses: Active Directory Deep Dive

Get a firm grasp on your IT environment when you learn Active Directory best practices with Veeam! Watch all, or choose any amount, of this three-part webinar series to improve your skills. From the basics to virtualization and backup, we got you covered.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

After several hours of googling I could not gather any information on this topic. There are several ways of controlling the USB port connected to any storage device. The best example of that is by changing the registry value of "HKEY_LOCAL_MACHINE\S…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question