come from http://www.vckbase.com/vckbase/vckbase12/vc/nonctrls/gdi_17/1217001.htm
//h
#pragma pack( push )
#pragma pack( 2 )
typedef struct
{
BYTE bWidth; // Width of the image
BYTE bHeight; // Height of the image (times 2)
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
} MEMICONDIRENTRY, *LPMEMICONDIRENTRY;
typedef struct
{
WORD idReserved; // Reserved
WORD idType; // resource type (1 for icons)
WORD idCount; // how many images?
MEMICONDIRENTRY idEntries[1]; // the entries for each image
} MEMICONDIR, *LPMEMICONDIR;
#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
{
BOOL bHasChanged; // Has image changed?
TCHAR szOriginalICOFileName[MAX_PATH]; // Original name
TCHAR szOriginalDLLFileName[MAX_PATH]; // Original name
UINT nNumImages; // How many images?
ICONIMAGE IconImages[1]; // Image entries
} ICONRESOURCE, *LPICONRESOURCE;
typedef struct
{
LPCTSTR szFileName;
HINSTANCE hInstance;
LPTSTR lpID;
} EXEDLLICONINFO, *LPEXEDLLICONINFO;
typedef struct
{
BYTE bWidth; // Width of the image
BYTE bHeight; // Height of the image (times 2)
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?
DWORD dwImageOffset; // where in the file is this image
} ICONDIRENTRY, *LPICONDIRENTRY;
LPICONRESOURCE ReadIconFromModuleFile(LPCTSTR szFileName,LPCTSTR lpID);
void FreeICONRESOURCE(LPICONRESOURCE pRsIcon);
BOOL WriteIconToICOFile(LPICONRESOURCE lpIR, LPCTSTR szFileName);
// cpp
#define WIDTHBYTES(bits) ((((bits) + 31)>>5)<<2)
WORD DIBNumColors( LPSTR lpbi )
{
WORD wBitCount;
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
if (dwClrUsed)
return (WORD) dwClrUsed;
wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
switch (wBitCount)
{
case 1: return 2;
case 4: return 16;
case 8: return 256;
default:return 0;
}
return 0;
}
WORD PaletteSize( LPSTR lpbi )
{
return ( DIBNumColors( lpbi ) * sizeof( RGBQUAD ) );
}
LPSTR FindDIBBits( LPSTR lpbi )
{
return ( lpbi + *(LPDWORD)lpbi + PaletteSize( lpbi ) );
}
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;
}
LPICONRESOURCE ReadIconFromModuleFile(LPCTSTR lpFileName,LPCTSTR lpID )
{
LPICONRESOURCE lpIR = NULL;
HINSTANCE hLibrary = NULL;
BOOL bRetValue = FALSE;
do
{
hLibrary = LoadLibraryEx(lpFileName, NULL, LOAD_LIBRARY_AS_DATAFILE);
if(hLibrary == NULL)
{
break;
}
EXEDLLICONINFO EDII;
EDII.szFileName = lpFileName;
EDII.hInstance = hLibrary;
if(lpID == NULL)
{
break;
}
HRSRC hRsrc = NULL;
hRsrc = ::FindResource(hLibrary, lpID, RT_GROUP_ICON);
if(hRsrc == NULL)
{
break;
}
HGLOBAL hGlobal = NULL;
hGlobal = ::LoadResource(hLibrary, hRsrc);
if(hGlobal == NULL)
{
break;
}
LPMEMICONDIR lpIcon = NULL;
lpIcon = (LPMEMICONDIR)LockResource(hGlobal);
if(lpIcon == NULL)
{
break;
}
lpIR = (LPICONRESOURCE)malloc(sizeof(ICONRESOURCE) + (lpIcon->idCount - 1) * sizeof(ICONIMAGE));
if(lpIR == NULL)
{
break;
}
lpIR->nNumImages = lpIcon->idCount;
_tcscpy(lpIR->szOriginalDLLFileName, lpFileName);
_tcscpy(lpIR->szOriginalICOFileName, TEXT(""));
UINT uIndex = 0;
for (uIndex=0; uIndex<lpIR->nNumImages; uIndex++)
{
hRsrc = ::FindResource(hLibrary, MAKEINTRESOURCE(lpIcon->idEntries[uIndex].nID), RT_ICON);
if(hRsrc == NULL)
break;
hGlobal = ::LoadResource(hLibrary, hRsrc);
if(hGlobal == NULL)
break;
lpIR->IconImages[uIndex].dwNumBytes = SizeofResource(hLibrary, hRsrc);
lpIR->IconImages[uIndex].lpBits = (LPBYTE)malloc(lpIR->IconImages[uIndex].dwNumBytes);
memcpy(lpIR->IconImages[uIndex].lpBits, ::LockResource(hGlobal), lpIR->IconImages[uIndex].dwNumBytes);
if(!AdjustIconImagePointers(&(lpIR->IconImages[uIndex])))
break;
}
bRetValue = (uIndex == lpIR->nNumImages);
} while(0);
if(!bRetValue)
{
FreeICONRESOURCE(lpIR);
lpIR = NULL;
}
if(hLibrary != NULL)
{
::FreeLibrary(hLibrary);
hLibrary = NULL;
}
return lpIR;
}
void FreeICONRESOURCE(LPICONRESOURCE pRsIcon)
{
if(pRsIcon != NULL)
{
DWORD dwIndex = 0;
for(dwIndex=0; dwIndex<pRsIcon->nNumImages; dwIndex++)
{
free(pRsIcon->IconImages[dwIndex].lpBits);
pRsIcon->IconImages[dwIndex].lpBits = NULL;
}
free(pRsIcon);
pRsIcon = NULL;
}
}
BOOL WriteICOHeader( HANDLE hFile, UINT nNumEntries )
{
WORD Output;
DWORD dwBytesWritten;
// Write 'reserved' WORD
Output = 0;
if( ! WriteFile( hFile, &Output, sizeof( WORD ), &dwBytesWritten, NULL ) )
return FALSE;
// Did we write a WORD?
if( dwBytesWritten != sizeof( WORD ) )
return FALSE;
// Write 'type' WORD (1)
Output = 1;
if( ! WriteFile( hFile, &Output, sizeof( WORD ), &dwBytesWritten, NULL ) )
return FALSE;
// Did we write a WORD?
if( dwBytesWritten != sizeof( WORD ) )
return FALSE;
// Write Number of Entries
Output = (WORD)nNumEntries;
if( ! WriteFile( hFile, &Output, sizeof( WORD ), &dwBytesWritten, NULL ) )
return FALSE;
// Did we write a WORD?
if( dwBytesWritten != sizeof( WORD ) )
return FALSE;
return TRUE;
}
DWORD CalculateImageOffset( LPICONRESOURCE lpIR, UINT nIndex )
{
DWORD dwSize;
UINT i;
// Calculate the ICO header size
dwSize = 3 * sizeof(WORD);
// Add the ICONDIRENTRY's
dwSize += lpIR->nNumImages * sizeof(ICONDIRENTRY);
// Add the sizes of the previous images
for(i=0;i<nIndex;i++)
dwSize += lpIR->IconImages[i].dwNumBytes;
// we're there - return the number
return dwSize;
}
BOOL WriteIconToICOFile(LPICONRESOURCE lpIR, LPCTSTR szFileName)
{
HANDLE hFile;
UINT i;
DWORD dwBytesWritten;
// open the file
if( (hFile = CreateFile( szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE )
{
return FALSE;
}
// Write the header
if( ! WriteICOHeader( hFile, lpIR->nNumImages ) )
{
CloseHandle( hFile );
return FALSE;
}
// Write the ICONDIRENTRY's
for( i=0; i<lpIR->nNumImages; i++ )
{
ICONDIRENTRY ide;
// Convert internal format to ICONDIRENTRY
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 );
// Write the ICONDIRENTRY out to disk
if( ! WriteFile( hFile, &ide, sizeof( ICONDIRENTRY ), &dwBytesWritten, NULL ) )
return FALSE;
// Did we write a full ICONDIRENTRY ?
if( dwBytesWritten != sizeof( ICONDIRENTRY ) )
return FALSE;
}
// Write the image bits for each image
for( i=0; i<lpIR->nNumImages; i++ )
{
DWORD dwTemp = lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage;
// Set the sizeimage member to zero
lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage = 0;
// Write the image bits to file
if( ! WriteFile( hFile, lpIR->IconImages[i].lpBits, lpIR->IconImages[i].dwNumBytes, &dwBytesWritten, NULL ) )
return FALSE;
if( dwBytesWritten != lpIR->IconImages[i].dwNumBytes )
return FALSE;
// set it back
lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage = dwTemp;
}
CloseHandle( hFile );
return TRUE;
}
// call
#include "SSIconMan.h"
TCHAR g_lpFirstID[256] = {0};
UINT g_uFirstID = 0;
//////////////////////////////////////////////////////////////////////////
BOOL CALLBACK MyEnumProcedure( HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam )
{
TCHAR szBuffer[256];
LONG nIndex = LB_ERR;
LPTSTR lpID = NULL;
// Name is from MAKEINTRESOURCE()
if(IS_INTRESOURCE(lpszName))
{
_stprintf( szBuffer, TEXT("Icon [%d]"), (DWORD)lpszName );
g_uFirstID = (UINT)lpszName;
}
else
{
// Name is string
_tcscpy(g_lpFirstID, lpszName);
_stprintf( szBuffer, TEXT("Icon [%s]"), lpID );
}
::MessageBox(::GetActiveWindow(), szBuffer, lpID, MB_OK);
return TRUE;
}
CString strDistFile;
GetDlgItemText(IDC_EDIT_DIST, strDistFile);
HINSTANCE hLibrary = ::LoadLibraryEx( strDistFile, NULL, LOAD_LIBRARY_AS_DATAFILE );
if(hLibrary == NULL)
{
AfxMessageBox(TEXT("Not a Valid Module"));
return;
}
g_uFirstID = 0;
memset(g_lpFirstID, 0, sizeof(g_lpFirstID));
EnumResourceNames(hLibrary, RT_GROUP_ICON, (ENUMRESNAMEPROC )MyEnumProcedure, (LPARAM)GetSafeHwnd());
if(_tcslen(g_lpFirstID) <= 0 && g_uFirstID <= 0)
{
FreeLibrary(hLibrary);
hLibrary = NULL;
AfxMessageBox(TEXT("No Resource"));
return;
}
FreeLibrary(hLibrary);
hLibrary = NULL;
LPICONRESOURCE lpIR = ReadIconFromModuleFile(strDistFile, /*MAKEINTRESOURCE(ID_APP_ABOUT)*/
g_uFirstID > 0 ? MAKEINTRESOURCE(g_uFirstID) : g_lpFirstID);
if(lpIR == NULL)
{
AfxMessageBox(TEXT("Read Icon failed"));
return;
}
BOOL bRetValue = WriteIconToICOFile(lpIR, TEXT("D://IconNew.ico"));
if(!bRetValue)
{
AfxMessageBox(TEXT("Write Icon failed"));
}else{
AfxMessageBox(TEXT("Write Icon successed"));
}
FreeICONRESOURCE(lpIR);
lpIR = NULL;