Find out number of icons in an icon resource using Win32 API

你离开我真会死。 提交于 2019-11-28 09:28:32
IInspectable

The original icon handling functions are ancient. They were introduced in 16-bit Windows and designed for a system that defined only one icon size. Therefore, most of those functions are unaware of the possibility of more than one icon size. To get to the differently sized icons in a resource additional work is required.

Following the ICO file format, consisting of an icon directory and the actual icon images, an icon resource consists of two parts as well: The icon directory of type RT_GROUP_ICON and the individual icons (RT_ICON). The directory is represented by the following structures:

#pragma pack( push )
#pragma pack( 2 )
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 )

and

#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;
#pragma pack( pop )

The icon directory for an icon group ID can be retrieved using the following code:

typedef std::list<GRPICONDIRENTRY> IconDirectory;

IconDirectory GetIconDirectory( HMODULE hMod, WORD Id ) {
    HRSRC hRsrc = FindResourceW( hMod, MAKEINTRESOURCE( Id ), RT_GROUP_ICON );
    HGLOBAL hGlobal = LoadResource( hMod, hRsrc );
    GRPICONDIR* lpGrpIconDir = (GRPICONDIR*)LockResource( hGlobal );

    IconDirectory dir;
    for ( size_t i = 0; i < lpGrpIconDir->idCount; ++i ) {
        dir.push_back( lpGrpIconDir->idEntries[ i ] );
    }
    return dir;
}

With the information from the icon directory the individual icons can be constructed with this code:

HICON LoadSpecificIcon( HMODULE hMod, WORD Id ) {
    HRSRC hRsrc = FindResourceW( hMod, MAKEINTRESOURCE( Id ), RT_ICON );
    HGLOBAL hGlobal = LoadResource( hMod, hRsrc );
    BYTE* lpData = (BYTE*)LockResource( hGlobal );
    DWORD dwSize = SizeofResource( hMod, hRsrc );

    HICON hIcon = CreateIconFromResourceEx( lpData, dwSize, TRUE, 0x00030000,
                                            0, 0, LR_DEFAULTCOLOR );
    return hIcon;
}

Putting all the pieces together, the following loads explorer.exe as a resource file, retrieves the first icon group with ID 101 and prints the information from the icon directory for each entry. It then creates the individual icons and outputs the xHotspot and yHotspot data. For icons, the hotspot is located in the center:

void PrintIconDirEntry( const GRPICONDIRENTRY& DirEntry ) {
    _wprintf_p( L"ID: %04d; width=%02d; height=%02d; bpp=%02d\n",
                DirEntry.nID,
                DirEntry.bWidth, DirEntry.bHeight, DirEntry.wBitCount );
}

void PrintIconInfo( HICON hIcon ) {
    ICONINFO ii = { 0 };
    GetIconInfo( hIcon, &ii );
    _wprintf_p( L"xHotspot=%02d; yHotspot=%02d\n", ii.xHotspot, ii.yHotspot );
}

typedef std::list<GRPICONDIRENTRY>::const_iterator IconDirectoryCIt;

int _tmain(int argc, _TCHAR* argv[])
{
    HMODULE hMod = LoadLibraryExW( L"C:\\Windows\\system32\\explorer.exe",
                                   NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE );
    IconDirectory dir = GetIconDirectory( hMod, 101 );
    for ( IconDirectoryCIt it = dir.begin(); it != dir.end(); ++it ) {
        PrintIconDirEntry( *it );
        HICON hIcon = LoadSpecificIcon( hMod, it->nID );
        PrintIconInfo( hIcon );
        DestroyIcon( hIcon );
    }
    return 0;
}

To sum this up: Retrieving all icon sizes and color variations for an icon resources involves two steps:

  1. Retrieve the icon directory with information for all icons in an icon group.
  2. Iterate over the icon directory and construct the individual icons using CreateIconFromResourceEx.

References:

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!