一直以来用 AxIcon Workshop 来处理图标,但是 AxIcon Workshop稍微有点问题就是,不支持重复图标过滤,而且,在处理大量图标的时候很容易没有响应!:( 为此,我自己写了一个图标处理工具,可以自动抽取 DLL/EXE/ICL 等文件中的图标,并进行重复图标自动过滤,图标扫描等功能,其中比较困难的是对 ICL 文件的处理,ICL 文件本质上是一个 16 Bit 的 DLL 资源文件,但是在 Windows 2000 下好象没有直接操作它的函数,至少我是不知道,查了 Google 也没查到相关资料,没有办法,只有硬来了,查了 16 Bit 的 EXE 的文件结构资料,结合网上可以找到的一些对16 Bit 的 EXE 的读写代码片段,再经过探索和摸索,终于成功的将从 ICL 中分离出 ICON 。其中的关键代码如下:希望给你有帮助 typedef UINT16 HANDLE16; typedef HANDLE16 *LPHANDLE16; DECLARE_HANDLE(FARPROC16); #pragma pack( push ) #pragma pack( 2 ) typedef struct { WORD offset; WORD length; WORD flags; WORD id; HANDLE16 handle; WORD usage; } NE_NAMEINFO; typedef struct { WORD type_id; /* Type identifier */ WORD count; /* Number of resources of this type */ FARPROC16 resloader; /* SetResourceHandler() */ /* * Name info array. */ } NE_TYPEINFO; typedef struct { WORD idReserved; // Reserved (must be 0) WORD idType; // Resource Type (1 for icons) WORD idCount; // How many images? 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? } NE_ICONDIRENTRY, *LPNE_ICONDIRENTRY; // 图标目录 typedef struct { WORD idReserved; // Reserved (must be 0) WORD idType; // Resource type (1 for icons) WORD idCount; // How many images? } GRPICONDIR, *LPGRPICONDIR; // 图标项 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 } GRPNE_ICONDIRENTRY, *LPGRPNE_ICONDIRENTRY; #pragma pack( pop ) #define NE_RT_CURSOR 0x8001 #define NE_RT_BITMAP 0x8002 #define NE_RT_ICON 0x8003 #define NE_RT_MENU 0x8004 #define NE_RT_DIALOG 0x8005 #define NE_RT_STRING 0x8006 #define NE_RT_FONTDIR 0x8007 #define NE_RT_FONT 0x8008 #define NE_RT_ACCELERATOR 0x8009 #define NE_RT_RCDATA 0x800a #define NE_RT_GROUP_CURSOR 0x800c #define NE_RT_GROUP_ICON 0x800e
// ICL 图标枚举 HRESULT ICL_EnumResourceNames(IN CONST HANDLE hFile, IN UINT nType, IN NE_ENUM_RES_NAME_PROC pFunc, IN LPARAM lParam) { DWORD dwRead = 0; // 读区 DOS 文件头 IMAGE_DOS_HEADER oDOSHeader; if(!::ReadFile( hFile, &oDOSHeader, sizeof(IMAGE_DOS_HEADER), &dwRead, NULL ) ) { return ::GetLastError(); } // 读区 NE 文件头 IMAGE_OS2_HEADER oNEHeader; ::SetFilePointer(hFile, oDOSHeader.e_lfanew, NULL, FILE_BEGIN); if(!::ReadFile( hFile, &oNEHeader, sizeof(IMAGE_OS2_HEADER), &dwRead, NULL ) ) { return ::GetLastError(); } // 读区 RSRC 资源表 DWORD nPos = oDOSHeader.e_lfanew + oNEHeader.ne_rsrctab; ::SetFilePointer(hFile, nPos, NULL, FILE_BEGIN); WORD nSizeShift; if(!::ReadFile( hFile, &nSizeShift, sizeof(WORD), &dwRead, NULL ) ) { return ::GetLastError(); } NE_TYPEINFO oInfo; if(!::ReadFile( hFile, &oInfo, sizeof(NE_TYPEINFO), &dwRead, NULL ) ) { return ::GetLastError(); } // 枚举所有的资源 DWORD nPosEnd = oDOSHeader.e_lfanew + oNEHeader.ne_restab; DWORD nPosName = nPosEnd + 4; NE_NAMEINFO oName; UINT nIndex = 0; while (oInfo.type_id != 0 && nPos < nPosEnd) { for (UINT nCount = oInfo.count; nCount > 0; nCount--) { if(!::ReadFile(hFile, &oName, sizeof(NE_NAMEINFO), &dwRead, NULL)) { return ::GetLastError(); } if(oInfo.type_id == nType) { // 保存文件位置 DWORD nPosOld = ::SetFilePointer(hFile, 0, NULL, FILE_CURRENT); // 资源名 BYTE nSize; ::SetFilePointer(hFile, nPosName, NULL, FILE_BEGIN); if(!::ReadFile( hFile, &nSize, sizeof(BYTE), &dwRead, NULL)) { return ::GetLastError(); } if(nSize > 255) return E_FAIL; nPosName += sizeof(BYTE) + nSize; ACHAR sName[255 + 1]; if(!::ReadFile( hFile, sName, nSize, &dwRead, NULL)) { return ::GetLastError(); } if(nSize == 1 && sName[0] == __A('@')) nSize = 0; sName[nSize] = ACHR_NULL; // 资源组 GRPICONDIR oDir; DWORD nPosGroup = oName.offset << nSizeShift; ::SetFilePointer(hFile, nPosGroup, NULL, FILE_BEGIN); if(!::ReadFile( hFile, &oDir, sizeof(GRPICONDIR), &dwRead, NULL)) { return ::GetLastError(); } // 处理 STK_CONVERSIONU; pFunc(hFile, nIndex++, STK_A2T(sName), &oDir, lParam); // 恢复文件位置 ::SetFilePointer(hFile, nPosOld, NULL, FILE_BEGIN); } } if(!::ReadFile( hFile, &oInfo, sizeof(NE_TYPEINFO), &dwRead, NULL)) { return ::GetLastError(); } } return S_OK; }

|