// InjectIcon.cpp
#include <windows.h>
#include <assert.h>
//////////// 構造体定義 ////////////
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;
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( 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 )
//////////// クラス定義 ////////////
// アイコンファイルクラス
class IconFile
{
private:
ICONDIR _iconDir; // アイコンディレクトリ
ICONDIRENTRY* _iconEntry; // アイコンディレクトリエントリ
BYTE** _iconImage; // イメージデータの配列
BYTE* _iconGroupData; // イメージグループデータ
public:
// コンストラクタ
IconFile()
{
memset(&_iconDir, 0, sizeof(_iconDir));
_iconEntry = NULL;
_iconImage = NULL;
_iconGroupData = NULL;
}
// デストラクタ
~IconFile()
{
if (_iconImage)
{
for (int i = 0; i < _iconDir.idCount; i++)
{
delete _iconImage[i];
}
}
delete _iconImage;
delete _iconEntry;
delete _iconGroupData;
}
// アイコンの持つイメージの数を取得する
int GetImageCount() const
{
return _iconDir.idCount;
}
// index番目のイメージデータを取得する
BYTE* GetImageData(int index) const
{
assert(0 <= index && index < GetImageCount());
assert(_iconImage != NULL);
return _iconImage[index];
}
// index番目のイメージサイズを取得する
DWORD GetImageSize(int index) const
{
assert(0 <= index && index < GetImageCount());
assert(_iconEntry != NULL);
return _iconEntry[index].dwBytesInRes;
}
// アイコンファイルをロードする
void Load(LPCTSTR pszFileName)
{
// アイコンファイルのオープン
HANDLE hFile = ::CreateFile(pszFileName, GENERIC_READ,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
assert(hFile != INVALID_HANDLE_VALUE);
DWORD dwRead;
// ICONDIR部分の読み込み
assert(
::ReadFile(hFile, &_iconDir, sizeof(ICONDIR), &dwRead, NULL) != FALSE
);
// ICONDIRの内容確認
assert(_iconDir.idReserved == 0);
assert(_iconDir.idType == 1);
assert(_iconDir.idCount > 0);
// ICONDIRENTRYの読み込み
_iconEntry = new ICONDIRENTRY[_iconDir.idCount];
for (int i = 0; i < _iconDir.idCount; i++)
{
assert(
::ReadFile(hFile, &(_iconEntry[i]), sizeof(ICONDIRENTRY), &dwRead, NULL)
!= FALSE
);
}
// イメージデータの読み込み
_iconImage = new BYTE*[_iconDir.idCount];
for (i = 0; i < _iconDir.idCount; i++)
{
::SetFilePointer(hFile, _iconEntry[i].dwImageOffset, NULL, FILE_BEGIN);
_iconImage[i] = new BYTE[_iconEntry[i].dwBytesInRes];
assert(
::ReadFile(hFile, _iconImage[i], _iconEntry[i].dwBytesInRes, &dwRead, NULL)
!= FALSE
);
}
::CloseHandle(hFile);
}
// アイコングループデータのサイズ取得
int SizeOfIconGroupData() const
{
return sizeof(ICONDIR) + sizeof(GRPICONDIRENTRY) * GetImageCount();
}
// アイコングループデータの作成(nBaseIDはRT_ICONの基底インデックス番号)
BYTE* CreateIconGroupData(int nBaseID)
{
delete _iconGroupData;
// アイコングループデータの領域確保
_iconGroupData = new BYTE[SizeOfIconGroupData()];
// アイコングループディレクトリを書き込む
memcpy(_iconGroupData, &_iconDir, sizeof(ICONDIR));
int offset = sizeof(ICONDIR);
for (int i = 0; i < GetImageCount(); i++) {
GRPICONDIRENTRY grpEntry;
// イメージデータからBITMAPINFOHEADER取得
BITMAPINFOHEADER bitmapheader;
memcpy(&bitmapheader, GetImageData(i), sizeof(BITMAPINFOHEADER));
// アイコングループエントリ作成
grpEntry.bWidth = _iconEntry[i].bWidth;
grpEntry.bHeight = _iconEntry[i].bHeight;
grpEntry.bColorCount = _iconEntry[i].bColorCount;
grpEntry.bReserved = _iconEntry[i].bReserved;
grpEntry.wPlanes = bitmapheader.biPlanes;
grpEntry.wBitCount = bitmapheader.biBitCount;
grpEntry.dwBytesInRes = _iconEntry[i].dwBytesInRes;
grpEntry.nID = nBaseID + i;
// アイコングループエントリを書き込む
memcpy(_iconGroupData + offset, &grpEntry, sizeof(GRPICONDIRENTRY));
offset += sizeof(GRPICONDIRENTRY);
}
return _iconGroupData;
}
};
//////////// 関数定義 ////////////
// アイコンリソースを実行可能ファイルへ追加する
void InjectIcon(LPCTSTR pszExecutableFile, LPCTSTR pszIconFile,
UINT nIconGroupID, UINT nIconBaseID)
{
// アイコンファイルの読み込み
IconFile iconFile;
iconFile.Load(pszIconFile);
// リソースの更新開始
HANDLE hUpdate = ::BeginUpdateResource(pszExecutableFile, FALSE);
assert(hUpdate != NULL);
// RT_GROUP_ICON 書き込み
assert(
::UpdateResource(hUpdate, RT_GROUP_ICON, MAKEINTRESOURCE(nIconGroupID), 0,
iconFile.CreateIconGroupData(nIconBaseID), iconFile.SizeOfIconGroupData())
!= FALSE
);
// RT_ICON書き込み
for (int i = 0; i < iconFile.GetImageCount(); i++) {
assert(
::UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(nIconBaseID+i), 0,
iconFile.GetImageData(i), iconFile.GetImageSize(i))
!= FALSE
);
}
// リソースの更新終了
::EndUpdateResource(hUpdate, FALSE);
}
void main()
{
// アイコンの追加
// TODO: 環境に合わせてパラメータを変更してください。
InjectIcon("c:\\\\hoge\\\\hoge.exe", "c:\\\\hoge\\\\icon1.ico", 1000, 1000);
}
|