我有一个* .ico文件,其中包含与我的可执行文件链接的不同大小的多个图标作为资源。 我使用这个资源来设置我的应用程序的图标与RegisterClassEx()
,
即
wcx.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
除此之外,我还想将这个资源中的所有单个图标转换为ARGB
像素数组。 这应该可以通过使用GetIconInfo()
返回的位图上的GetDIBits()
GetIconInfo()
。
但是,有一个问题:我需要找出LoadIcon()
返回的HICON
句柄中的图标数量及其大小。 我似乎没有find需要HICON
句柄的API,并告诉我在那里有多less图标,以及它们的大小是多less。
这是否有可能以某种方式,或者我需要去困难的方式和parsing* .ico资源我自己?
原始的图标处理功能是古老的。 它们是在16位Windows中引入的,专为仅定义一个图标大小的系统而设计。 因此,这些功能中的大部分都不知道多个图标大小的可能性。 要获得资源中不同大小的图标,需要额外的工作。
ICO文件格式由一个图标目录和实际的图标图像组成,图标资源也由两部分组成: RT_GROUP_ICON
类型的图标目录和各个图标( RT_ICON
)。 该目录由以下结构表示:
#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 )
和
#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 )
可以使用以下代码检索图标组ID的图标目录:
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; }
使用图标目录中的信息,可以使用以下代码构建各个图标:
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; }
将所有的部分放在一起,下面的代码将explorer.exe
加载为资源文件,检索ID为101
的第一个图标组,并从每个条目的图标目录中打印信息。 然后创建个别图标并输出xHotspot
和yHotspot
数据。 对于图标,热点位于中心:
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; }
综上所述:检索图标资源的所有图标大小和颜色变化涉及两个步骤:
CreateIconFromResourceEx
构造单个图标。 参考文献: