일단 소스 코드 입니다.
아래 소스를 ChangeExeIcon.h 을 만들어서 붙혀 넣고 저장 합니다.
#ifndef ChangeExeIconH
#define ChangeExeIconH
#include
#include
#include
#include
#include
typedef struct
{
BYTE width;
BYTE height;
BYTE colorCount;
BYTE reserved;
WORD planes;
WORD bitCount;
DWORD bytesInRes;
DWORD imageOffset;
} ICONENTRY;
typedef struct
{
WORD reserved;
WORD type;
WORD count;
ICONENTRY entries[1];
} ICONHEADER;
typedef struct
{
BITMAPINFOHEADER header;
RGBQUAD colors;
BYTE xors[1];
BYTE ands[1];
} ICONIMAGE;
#pragma pack(push)
#pragma pack(2)
typedef struct
{
BYTE width;
BYTE height;
BYTE colourCount;
BYTE reserved;
BYTE planes;
BYTE bitCount;
WORD bytesInRes;
WORD bytesInRes2;
WORD reserved2;
WORD id;
} GRPICONENTRY;
typedef struct
{
WORD reserved;
WORD type;
WORD count;
GRPICONENTRY entries[1];
} GRPICONHEADER;
#pragma pack(pop)
bool __fastcall SetExeIcon(LPSTR exeFile, LPSTR iconFile);
bool __fastcall LoadingIcon(LPSTR iconFile, ICONHEADER*& pHeader, ICONIMAGE**& pIcons, GRPICONHEADER*& pGrpHeader, int index=0);
#endif
그 다음 아래 소스를 ChangeExeIcon.cpp 을 만들어서 붙혀 넣기 하고 저장 합니다.
#pragma hdrstop
#include "ChangeExeIcon.h"
#pragma package(smart_init)
#include
bool __fastcall SetExeIcon(LPSTR exeFile, LPSTR iconFile){
ICONHEADER* pHeader;
ICONIMAGE** pIcons;
GRPICONHEADER* pGrpHeader;
bool res = LoadingIcon(iconFile, pHeader, pIcons, pGrpHeader);
if(!res) {
return false;
}
HANDLE hUpdate = BeginUpdateResource(exeFile, FALSE);
if(!hUpdate)return false;
UpdateResource(hUpdate, RT_GROUP_ICON, "MAINICON", MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
pGrpHeader, sizeof(WORD)*3+pHeader->count*sizeof(GRPICONENTRY));
for(int i = 0; i < pHeader->count; i++) {
UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(i + 1), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
pIcons[i], pHeader->entries[i].bytesInRes);
}
EndUpdateResource(hUpdate, FALSE);
return true;
}
bool __fastcall LoadingIcon(LPSTR iconFile, ICONHEADER*& pHeader, ICONIMAGE**& pIcons, GRPICONHEADER*& pGrpHeader, int index){
HANDLE hFile = CreateFile(TEXT(iconFile), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)return false;
pHeader = (ICONHEADER*) malloc(sizeof(ICONHEADER));
DWORD bytesRead;
ReadFile(hFile, &(pHeader->reserved), sizeof(WORD), &bytesRead, NULL);
ReadFile(hFile, &(pHeader->type), sizeof(WORD), &bytesRead, NULL);
ReadFile(hFile, &(pHeader->count), sizeof(WORD), &bytesRead, NULL);
pHeader = (ICONHEADER*) realloc(pHeader, sizeof(WORD)*3+sizeof(ICONENTRY)*pHeader->count);
ReadFile(hFile, pHeader->entries, pHeader->count*sizeof(ICONENTRY), &bytesRead, NULL);
pIcons = (ICONIMAGE**) malloc(sizeof(ICONIMAGE*)*pHeader->count);
for(int i = 0 ; i < pHeader->count; i++) {
pIcons[i] = (ICONIMAGE*) malloc(pHeader->entries[i].bytesInRes);
SetFilePointer(hFile, pHeader->entries[i].imageOffset, NULL, FILE_BEGIN);
ReadFile(hFile, pIcons[i], pHeader->entries[i].bytesInRes, &bytesRead, NULL);
}
pGrpHeader = (GRPICONHEADER*) malloc(sizeof(WORD)*3+pHeader->count*sizeof(GRPICONENTRY));
pGrpHeader->reserved = 0;
pGrpHeader->type = 1;
pGrpHeader->count = pHeader->count;
for(int i = 0; i < pHeader->count; i++) {
ICONENTRY* icon = &pHeader->entries[i];
GRPICONENTRY* entry = &pGrpHeader->entries[i];
entry->bitCount = 0;
entry->bytesInRes = icon->bitCount;
entry->bytesInRes2 = (WORD)icon->bytesInRes;
entry->colourCount = icon->colorCount;
entry->height = icon->height;
entry->id = (WORD)(i+1+index);
entry->planes = (BYTE)icon->planes;
entry->reserved = icon->reserved;
entry->width = icon->width;
entry->reserved2 = 0;
}
CloseHandle(hFile);
return true;
}
그담 사용 하고 싶은곳에 두 파일을 프로잭트에 포함시키고
ChangeExeIcon.h 헤더를 include 합니다.
사용법:
AnsiString ExeFileName = "c:\\a.exe";
AnsiString IconFileName = "c:\\a.ico";
SetExeIcon(ExeFileName .c_str(), IconFileName .c_str());
바꿀 아이콘 파일의 포든 포맷을 테스트 해보진 못 했습니다.
아이콘 크기나 비트에 따라 안될 수도 있습니다.