序
有的时候看见其他程序图标非常漂亮,想获取出来,在自己程序(非商业用途)里面使用。
但是windows自带的 ExtractIcon 函数获取的32x32的图标,分比例不高导致清晰度差。
而且有的应用程序或者模块有好几种图标,无法全部提取。
实现方案
之前有一篇替换应用程序里面的图标时,讲到的那几个函数,现在正好派上用场。
不清楚的小伙伴可以看一下之前那一篇编程笔记:替换windows应用图标。
通过里面的 FindResource、LoadResource 和 LockResource 就可以获取到资源数据。
唯一要注意的是该资源数据没有对应的资源数据头。
图标文件头
以我们课题讨论的,以图标资源为例,图标的文件头定义如下:
#pragma pack(push) //保正对齐状态#pragma pack(1)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 ( must be 0) WORD wPlanes; // Color Planes WORD wBitCount; // Bits per pixel DWORD dwBytesInRes; // How many bytes in this resource? DWORD dwImageOffset; // Where in the file is this image?} ICONDIRENTRY, *LPICONDIRENTRY;#pragma pack(pop)#pragma pack(push) //保正对齐状态#pragma pack(1)typedef struct{ WORD idReserved; // Reserved (must be 0) WORD idType; // Resource Type (1 for icons) WORD idCount; // How many images? ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em)} ICONDIR, *LPICONDIR;#pragma pack(pop)
然后只要我们根据对应的数据解释,填充对应数据即可。
初始数据可如下填充:
ICONDIR ico; // 资源头对象memset(&ico, 0, sizeof(ICONDIR)); // 清零,这样那些必须为零的数据就不用填写了ico.idType = 1;ico.idCount = 1;ico.idEntries[0].wPlanes = 1;ico.idEntries[0].dwImageOffset = 22;
数据填充
上面初始化部分头数据已经填充完毕,接下来就是根据图片数据,对应更新图标宽高以及大小信息。
在资源函数枚举回调函数(这里命名为 SaveIcons )中,实现对数据的获取及填充。
具体实现代码如下:
BOOL CALLBACK SaveIcons(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam){ HRSRC hRes = FindResource(hModule, lpszName, lpszType); HGLOBAL hResLoaded = LoadResource(hModule, hRes); void* pData = LockResource(hResLoaded); int nSizeOfIconRes = SizeofResource(hModule,hRes); ico.idEntries[0].dwBytesInRes = nSizeOfIconRes*4; // 图标数据长度 int w = (byte)((char*)pData)[4]; // 该索引位置是图标尺寸 ico.idEntries[0].bWidth = ico.idEntries[0].bHeight = w; // 图标是正方形 // save data (略) // 然后将 ico 的 22 字节数据写入文件, // 后面追加 pData 的 nSizeOfIconRes*4 字节数据; // 将图片命名为 "xxx.ico" 即可 UnlockResource(hResLoaded); FreeResource(hResLoaded); return TRUE;}void getIcons(const char *appName) // 传递需要获取的图标资源程序路径{ HMODULE hModule = LoadLibraryExA(appName, NULL, LOAD_LIBRARY_AS_DATAFILE ); EnumResourceNames(hModule, RT_ICON, SaveIcons, NULL); ::FreeLibrary(hModule);}
当然也可以直接通过UI应用去展示各个图片效果,保存需要的。
以下图片效果是我基于Qt做的界面运行效果:
总结
EnumResourceNames 函数资源类型哪里除了 RT_ICON 外还有好几个,
比如 RT_BITMAP 获取位图的,有兴趣的小伙伴可以自己实现。
如果觉得我写的还不错的话,求赞,求关注哦!(^▽^)