//主函数为SaveIco
/******************************************************************************/// 宏定义
/******************************************************************************/
#define WIDTHBYTES(bits) ((((bits) + 31)>>5)<<2)
/******************************************************************************/
// 结构定义
/******************************************************************************/
#pragma pack( push )
#pragma pack( 2 )
typedef struct tagGRPICONDIRENTRY
{
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInRes;
WORD nID;
}GRPICONDIRENTRY, *LPGRPICONDIRENTRY;;
typedef struct tagGRPICONDIR
{
WORD idReserved;
WORD idType;
WORD idCount;
GRPICONDIRENTRY idEntries[1];
}GRPICONDIR, *LPGRPICONDIR;
#pragma pack( pop )
typedef struct
{
UINT Width, Height, Colors; // Width, Height and bpp
LPBYTE lpBits; // ptr to DIB bits
DWORD dwNumBytes; // how many bytes?
LPBITMAPINFO lpbi; // ptr to header
LPBYTE lpXOR; // ptr to XOR image bits
LPBYTE lpAND; // ptr to AND image bits
} ICONIMAGE, *LPICONIMAGE;
typedef struct
{
UINT nNumImages; // How many images?
ICONIMAGE IconImages[1]; // Image entries
} ICONRESOURCE, *LPICONRESOURCE;
//*****************************************************************************
// 得到颜色位数//*****************************************************************************
WORD DIBNumColors(LPSTR lpbi)
{
WORD wRet=0;
WORD wBitCount;
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
if(dwClrUsed)
{
wRet = (WORD)dwClrUsed;
}
else
{
wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
switch(wBitCount)
{
case 1:
wRet = 2;
break;
case 4:
wRet = 16;
break;
case 8:
wRet = 256;
break;
default:
wRet = 0;
break;
}
}
return wRet;
}
//*****************************************************************************
// 得到DIB数据地址
//*****************************************************************************
LPSTR FindDIBBits(LPSTR lpbi)
{
WORD wPaletteSize;
wPaletteSize = DIBNumColors(lpbi) * sizeof(RGBQUAD);
return (lpbi + *(LPDWORD)lpbi + wPaletteSize);
}
//*****************************************************************************
// 每行字节数
//*****************************************************************************
DWORD BytesPerLine(LPBITMAPINFOHEADER lpBMIH)
{
return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);
}
//*****************************************************************************
//调整各项指针
//*****************************************************************************
BOOL AdjustIconImagePointers(LPICONIMAGE lpImage)
{
// Sanity check
if(lpImage == NULL) return FALSE;
// BITMAPINFO is at beginning of bits
lpImage->lpbi = (LPBITMAPINFO)lpImage->lpBits;
// Width - simple enough
lpImage->Width = lpImage->lpbi->bmiHeader.biWidth;
// Icons are stored in funky format where height is doubled - account for it
lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2;
// How many colors?
lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes * lpImage->lpbi->bmiHeader.biBitCount;
// XOR bits follow the header and color table
lpImage->lpXOR = (LPBYTE)FindDIBBits((LPSTR)lpImage->lpbi);
// AND bits follow the XOR bits
lpImage->lpAND = lpImage->lpXOR + (lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER)(lpImage->lpbi)));
return TRUE;
}
//*****************************************************************************
//计算ICON图标数据偏移地址
//*****************************************************************************
DWORD CalculateImageOffset(LPICONRESOURCE lpIR, UINT nIndex)
{
DWORD dwSize;
UINT i;
dwSize = 3 * sizeof(WORD);
dwSize += lpIR->nNumImages * sizeof(ICONDIRENTRY);
for(i=0; i<nIndex; i++) dwSize += lpIR->IconImages[i].dwNumBytes;
return dwSize;
}
//*****************************************************************************
//保存ICON文件头
//*****************************************************************************
BOOL WriteICOHeader(HANDLE hFile, UINT nNumEntries)
{
WORD Output;
DWORD dwBytesWritten;
Output = 0;
if(!WriteFile(hFile, &Output, sizeof(WORD), &dwBytesWritten, NULL)) return FALSE;
if(dwBytesWritten != sizeof(WORD)) return FALSE;
Output = 1;
if(!WriteFile(hFile, &Output, sizeof(WORD), &dwBytesWritten, NULL)) return FALSE;
if(dwBytesWritten != sizeof(WORD)) return FALSE;
Output = (WORD)nNumEntries;
if(!WriteFile(hFile, &Output, sizeof(WORD), &dwBytesWritten, NULL)) return FALSE;
if(dwBytesWritten != sizeof(WORD)) return FALSE;
return TRUE;
}
//*****************************************************************************
// 保存ICON图标
// lpszApp: 包含图标资源的EXE、DLL文件
// lpszName: 图标资源名称或ID
// szFilePath: 图标文件名
//*****************************************************************************
BOOL SaveIcon(LPCTSTR lpszApp, LPTSTR lpszName, LPCTSTR szFilePath)
{
BOOL fgRet = FALSE;
DWORD dwSize;
LPTSTR lpName;
HINSTANCE hLibrary;
HRSRC hResSrc(NULL);
HGLOBAL hGlobal(NULL);
LPGRPICONDIR lpResGroup(NULL) ;
LPVOID lpResIcon(NULL);
LPICONRESOURCE lpIR(NULL);
DWORD dwId = (DWORD)lpszName;
if(HIWORD(dwId) == 0)
{
lpName = MAKEINTRESOURCE(dwId);
}
else
{
dwId = *((DWORD *)lpszName);
if(HIWORD(dwId) == 0)
lpName = MAKEINTRESOURCE(dwId);
else
lpName = lpszName;
}
//装入EXE文件,并读取资源
hLibrary = ::LoadLibrary(lpszApp); //装载模块
if(hLibrary == NULL) return FALSE;
hResSrc = ::FindResource(hLibrary, lpName, RT_GROUP_ICON); //查找指定资源
if(hResSrc == NULL) {::FreeLibrary(hLibrary); return FALSE;}
hGlobal = LoadResource(hLibrary, hResSrc); //装载找到的资源
if(hGlobal == NULL) {::FreeLibrary(hLibrary); return FALSE;}
lpResGroup = (LPGRPICONDIR)LockResource(hGlobal); //锁定资源
if(lpResGroup == NULL) {::FreeLibrary(hLibrary); return FALSE;}
//为资源分配内存空间
lpIR = (LPICONRESOURCE)malloc(sizeof(ICONRESOURCE) + ((lpResGroup->idCount-1)*sizeof(ICONIMAGE)));
if(lpIR == NULL) {::FreeLibrary(hLibrary); return FALSE;}
//保存图标数据
lpIR->nNumImages = lpResGroup->idCount;
for(UINT i=0; i<lpResGroup->idCount; i++)
{
//查找并定位图标资源
hResSrc = FindResource(hLibrary, MAKEINTRESOURCE(lpResGroup->idEntries[i].nID), RT_ICON);
if(hResSrc == NULL) {::FreeLibrary(hLibrary); return FALSE;}
hGlobal = LoadResource(hLibrary, hResSrc);
if(hGlobal == NULL) {::FreeLibrary(hLibrary); return FALSE;}
lpResIcon = LockResource(hGlobal);
if(lpResIcon == NULL) {::FreeLibrary(hLibrary); return FALSE;}
//资源大小
dwSize = SizeofResource(hLibrary, hResSrc);
//填充图标数据各各项指针
lpIR->IconImages[i].dwNumBytes = dwSize;
lpIR->IconImages[i].lpBits = (LPBYTE)malloc(dwSize);
memcpy(lpIR->IconImages[i].lpBits, lpResIcon, dwSize);
AdjustIconImagePointers(&(lpIR->IconImages[i]));
}
//释放资源
::FreeLibrary(hLibrary);
//保存数据为文件
HANDLE hFile;
hFile = CreateFile(szFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile== INVALID_HANDLE_VALUE) return FALSE;
//写文件头
if(!WriteICOHeader(hFile, lpIR->nNumImages))
{
CloseHandle( hFile );
return FALSE;
}
//写文件描述信息
ICONDIRENTRY ide;
for(i=0; i<lpIR->nNumImages; i++)
{
ide.bWidth = lpIR->IconImages[i].Width;
ide.bHeight = lpIR->IconImages[i].Height;
ide.bReserved = 0;
ide.wPlanes = lpIR->IconImages[i].lpbi->bmiHeader.biPlanes;
ide.wBitCount = lpIR->IconImages[i].lpbi->bmiHeader.biBitCount;
if((ide.wPlanes * ide.wBitCount) >= 8)
ide.bColorCount = 0;
else
ide.bColorCount = 1 << (ide.wPlanes * ide.wBitCount);
ide.dwBytesInRes = lpIR->IconImages[i].dwNumBytes;
ide.dwImageOffset = CalculateImageOffset(lpIR, i);
if(!WriteFile(hFile, &ide, sizeof(ICONDIRENTRY), &dwSize, NULL)) return FALSE;
if(dwSize != sizeof(ICONDIRENTRY)) return FALSE;
}
//写图像数据
for(i=0; i<lpIR->nNumImages; i++ )
{
DWORD dwTemp = lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage;
lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage = 0;
if(!WriteFile(hFile, lpIR->IconImages[i].lpBits, lpIR->IconImages[i].dwNumBytes, &dwSize, NULL)) return FALSE;
if(dwSize != lpIR->IconImages[i].dwNumBytes) return FALSE;
lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage = dwTemp;
}
CloseHandle( hFile );
return fgRet;
}