修改 EXE 图标,图标失真。

wenfh2020 2010-08-12 04:48:09
将要替换的图标文件 Demo.ico, 这个图标文件有下面的形式:

48*48 -RGB/A 32*32 -RGB/A 24*24-RGB/A 16*16-RGB/A
48*48 -256/A 32*32 -256/A 24*24-256/A 16*16-256/A

用下面代码替换后,Exe 图片失真,请问有什么方法能解决这问题?

注意:不要在 res 添加图标的方法。要 exe 外部用代码解决的。






#include <windows.h>
#include <tchar.h>
#include "SX_String.h"

struct ICONDIRENTRY
{
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInRes;
DWORD dwImageOffset;
};

struct ICONDIR
{
WORD idReserved;
WORD idType;
WORD idCount;
//ICONDIRENTRY idEntries;
};

struct GRPICONDIRENTRY
{
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInRes;
WORD nID;
};
struct GRPICONDIR
{
WORD idReserved;
WORD idType;
WORD idCount;
GRPICONDIRENTRY idEntries;
};

//////////////////////////////////////////////
//函数说明:修改EXE图标
//
//参 数:IconFile 图标文件
// ExeFile 被修改的EXE文件
//
//返回值: 成功为True,否则False
/////////////////////////////////////////////

bool ChangeExeIcon(LPWSTR IconFile, LPWSTR ExeFile)
{
ICONDIR stID;
ICONDIRENTRY stIDE;
GRPICONDIR stGID;
HANDLE hFile;
DWORD nSize, nGSize, dwReserved;
HANDLE hUpdate;
PBYTE pIcon, pGrpIcon;
BOOL ret;
hFile = CreateFile(IconFile, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return false;
}
ZeroMemory(&stID, sizeof(ICONDIR));
ret = ReadFile(hFile, &stID, sizeof(ICONDIR), &dwReserved, NULL);
ZeroMemory(&stIDE, sizeof(ICONDIRENTRY));
ret = ReadFile(hFile, &stIDE, sizeof(ICONDIRENTRY), &dwReserved, NULL);
nSize = stIDE.dwBytesInRes;
pIcon = (PBYTE)malloc(nSize);
SetFilePointer(hFile, stIDE.dwImageOffset, NULL, FILE_BEGIN);
ret = ReadFile(hFile, (LPVOID)pIcon, nSize, &dwReserved, NULL);
if (!ret)
{
CloseHandle(hFile);
return false;
}
ZeroMemory(&stGID, sizeof(GRPICONDIR));
stGID.idCount = stID.idCount;
stGID.idReserved = 0;
stGID.idType = 1;
CopyMemory(&stGID.idEntries, &stIDE, 12);
stGID.idEntries.nID = 0;
nGSize = sizeof(GRPICONDIR);
pGrpIcon = (PBYTE)malloc(nGSize);
CopyMemory(pGrpIcon, &stGID, nGSize);

hUpdate = BeginUpdateResource(ExeFile, false);
ret = UpdateResource(hUpdate, RT_GROUP_ICON, MAKEINTRESOURCE(1), 0, (LPVOID)pGrpIcon, nGSize);
ret = UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(1), 0, (LPVOID)pIcon, nSize);
EndUpdateResource(hUpdate, false);
if (!ret)
{
CloseHandle(hFile);
return false;
}
CloseHandle(hFile);
return true;
}
...全文
463 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
wenfh2020 2010-08-13
  • 打赏
  • 举报
回复
回楼上

那样还不是要 重新编译一次。这样也只能是程序员自己操作,如果让第三方操作就显得不那么方便了。

把所有的图片和 icon 放在 skin 文件夹里,一键替换,要的就是这个。
jackyjkchen 2010-08-13
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wenfh2020 的回复:]
引用 3 楼 m_tornado 的回复:

代码解决?
一般直接在资源里创建256色的,把其它的ico都删除掉,编译下而已~


如果是订制版的,而且工程代码依赖有几十万行,每次为一个图标 Rebuild all,一次半次没所谓,次数多了就不好处理了。
[/Quote]
那要,直接用VC打开exe文件,所有菜单、图标、按钮控件等资源都可以编辑,然后保存下就行了
wenfh2020 2010-08-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 m_tornado 的回复:]

代码解决?
一般直接在资源里创建256色的,把其它的ico都删除掉,编译下而已~
[/Quote]

如果是订制版的,而且工程代码依赖有几十万行,每次为一个图标 Rebuild all,一次半次没所谓,次数多了就不好处理了。
wenfh2020 2010-08-13
  • 打赏
  • 举报
回复
忙到很深夜,终于解决问题了。以下是网络上好心人的代码。


#include <windows.h>
#include <tchar.h>

typedef struct tagHEADER
{
WORD idReserved;
WORD idType;
WORD idCount;
}HEADER, *LPHEADER;

typedef struct tagICONDIRENTRY
{
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInRes;
DWORD dwImageOffset;
}ICONDIRENTRY, *LPICONDIRENTRY;

#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 )


//.CPP文件中的主要代码:
//view plaincopy to clipboardprint?
void ChangeExeIcon(LPCTSTR lpIconFile, LPCTSTR lpExeName)
{
LPICONDIRENTRY pIconDirEntry(NULL);
LPGRPICONDIR pGrpIconDir(NULL);
HEADER header;
LPBYTE pIconBytes(NULL);
HANDLE hIconFile(NULL);
DWORD dwRet(0), nSize(0), nGSize(0), dwReserved(0);
HANDLE hUpdate(NULL);
BOOL ret(FALSE);
WORD i(0);

//打开图标文件
hIconFile = CreateFile(lpIconFile, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hIconFile == INVALID_HANDLE_VALUE)
{
return;
}
//读取文件头部信息
ret=ReadFile(hIconFile, &header, sizeof(HEADER), &dwReserved, NULL);
if (!ret)
{
CloseHandle(hIconFile);
return;
}
//建立每一个图标的目录信息存放区域
pIconDirEntry = (LPICONDIRENTRY)new BYTE[header.idCount*sizeof(ICONDIRENTRY)];
if (pIconDirEntry==NULL)
{
CloseHandle(hIconFile);
return;
}
//从Icon文件中读取每一个图标的目录信息
ret = ReadFile(hIconFile, pIconDirEntry, header.idCount*sizeof(ICONDIRENTRY), &dwReserved, NULL);
if (!ret)
{
delete[] pIconDirEntry;
CloseHandle(hIconFile);
return;
}
//建立EXE文件中RT_GROUP_ICON所需的数据结构存放区域
nGSize=sizeof(GRPICONDIR)+header.idCount*sizeof(ICONDIRENTRY);
pGrpIconDir=(LPGRPICONDIR)new BYTE[nGSize];
ZeroMemory(pGrpIconDir, nSize);
//填充信息,这里相当于一个转换的过程
pGrpIconDir->idReserved=header.idReserved;
pGrpIconDir->idType=header.idType;
pGrpIconDir->idCount=header.idCount;
//复制信息并设置每一个图标对应的ID。ID为位置索引号
for(i=0;i<header.idCount;i++)
{
pGrpIconDir->idEntries[i].bWidth=pIconDirEntry[i].bWidth;
pGrpIconDir->idEntries[i].bHeight=pIconDirEntry[i].bHeight;
pGrpIconDir->idEntries[i].bColorCount=pIconDirEntry[i].bColorCount;
pGrpIconDir->idEntries[i].bReserved=pIconDirEntry[i].bReserved;
pGrpIconDir->idEntries[i].wPlanes=pIconDirEntry[i].wPlanes;
pGrpIconDir->idEntries[i].wBitCount=pIconDirEntry[i].wBitCount;
pGrpIconDir->idEntries[i].dwBytesInRes=pIconDirEntry[i].dwBytesInRes;
pGrpIconDir->idEntries[i].nID=i+1; //id == 0 是 RT_GROUP_ICON 的id,我这里替换的时候出现问题,所以就 + 1 了。
}
//开始更新EXE中的图标资源,ID定为最小0,如果原来存在0ID的图标信息则被替换为新的。
hUpdate = BeginUpdateResource(lpExeName, false);
if (hUpdate!=NULL)
{
HMODULE hMe= 0; // means load from this module

if (FindResource( hMe, lpExeName, RT_GROUP_ICON))
{
//首先更新RT_GROUP_ICON信息
ret = UpdateResource(hUpdate, RT_GROUP_ICON, MAKEINTRESOURCE(0), MAKELANGID(LANG_CHINESE, SUBLANG_SYS_DEFAULT), (LPVOID)pGrpIconDir, nGSize);
if (!ret)
{
delete[] pIconDirEntry;
delete[] pGrpIconDir;
CloseHandle(hIconFile);
return;
}
}

//接着的是每一个Icon的信息存放
for(i=0;i<header.idCount;i++)
{
//Icon的字节数
nSize = pIconDirEntry[i].dwBytesInRes;
//偏移文件的指针到当前图标的开始处
dwRet=SetFilePointer(hIconFile, pIconDirEntry[i].dwImageOffset, NULL, FILE_BEGIN);
if (dwRet==INVALID_SET_FILE_POINTER)
{
break;
}
//准备pIconBytes来存放文件里的Byte信息用于更新到EXE中。

delete[] pIconBytes;

pIconBytes = new BYTE[nSize];
ZeroMemory(pIconBytes, nSize);
ret = ReadFile(hIconFile, (LPVOID)pIconBytes, nSize, &dwReserved, NULL);
if(!ret)
{
break;
}
//更新每一个ID对应的RT_ICON信息
ret = UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(pGrpIconDir->idEntries[i].nID), MAKELANGID(LANG_CHINESE, SUBLANG_SYS_DEFAULT), (LPVOID)pIconBytes, nSize);
if(!ret)
{
break;
}
}
//结束EXE资源的更新操作
if (pIconBytes!=NULL)
{
delete[] pIconBytes;
}

EndUpdateResource(hUpdate, false);
}

//清理资源并关闭Icon文件,到此更新操作结束!
SAFE_ARRAY_DELETE(pGrpIconDir);
SAFE_ARRAY_DELETE(pIconDirEntry);
CloseHandle(hIconFile);
}

muzizongheng 2010-08-13
  • 打赏
  • 举报
回复
图片失真还是因为你的替换的icon像素不够。
ctwoz 2010-08-12
  • 打赏
  • 举报
回复
学习…
m_tornado 2010-08-12
  • 打赏
  • 举报
回复
代码解决?
一般直接在资源里创建256色的,把其它的ico都删除掉,编译下而已~
wenfh2020 2010-08-12
  • 打赏
  • 举报
回复
自己顶上去~
icefairy 2010-08-12
  • 打赏
  • 举报
回复
mark 学习下

15,978

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧