Click here to Skip to main content
15,881,877 members
Articles / Desktop Programming / MFC
Tip/Trick

Extracting A Particular Icon From an .ICO Resource

Rate me:
Please Sign up or sign in to vote.
4.83/5 (9 votes)
26 Jan 2011CPOL 23.4K   4   5
Extracting A Particular Icon From an .ICO Resource
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:

C++
//------------------------------------------------------------------------------
HICON LoadResourceIcon(UINT nResID, BYTE nWidth, BYTE nHeight, SHORT nBitDepth)
//------------------------------------------------------------------------------
{
    HICON hIconRet = NULL;

    #pragma pack(2)
        struct IcoMemEntry          // This is what an icon resource looks like in memory
        {
            byte Width;             // Width, in pixels, of the image
            byte Height;            // Height, in pixels, of the image
            byte ColorCount;        // Number of colors in image(0 if >=8bpp)
            byte Reserved;          // Reserved (must be 0)
            short Planes;           // Color Planes
            short BitCount;         // Bits per pixel
            int BytesInRes;         // How many bytes in this resource?
            short ID;               // Where in the file is this image?
        };

        struct IcoHeader
        {
            short Reserved;         // Reserved (must be 0)
            short Type;             // 1 = Icon, 0 = Bitmap
            short Count;            // number of icons
            IcoMemEntry Entries;    // address place holder
        };
    #pragma pack()

    // Find the start of the icon resource in memory
    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)
    {
        // Get the hicon headers so we can examine them
        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 an icon matches our criteria, extract it
            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;
            }
        }

        // Clean up
        if (pEntries != NULL)
        {
            delete[] pEntries;
        }
    }

    ::DestroyIcon((HICON)pHead);

    return hIconRet;
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
New Zealand New Zealand
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionA better of way to extract an icon from an executable file Pin
dc_200017-Jan-17 19:15
dc_200017-Jan-17 19:15 
AnswerRe: A better of way to extract an icon from an executable file Pin
Kyudos29-Jan-17 12:39
Kyudos29-Jan-17 12:39 
GeneralUse Visual Studio to extract resources Pin
Harold Bamford16-Mar-10 12:00
Harold Bamford16-Mar-10 12:00 
GeneralRe: Use Visual Studio to extract resources Pin
codevisio15-Oct-10 3:24
codevisio15-Oct-10 3:24 
GeneralRe: Use Visual Studio to extract resources Pin
Harold Bamford18-Oct-10 5:43
Harold Bamford18-Oct-10 5:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.