使用ICON动态修改exe文件图标

来源:互联网 发布:淘宝转盘抽奖怎么做 编辑:程序博客网 时间:2024/06/05 03:09
前言:这两天为exe文件做一个随机图标的功能,要求每次运行后图标都动态改变,在网上找了很多代码,都有一部分缺陷,参考了一些文档后进行了修改,现在在此进行总结:
一个icon资源(可以是*.ico文件,也可以是windows资源节区里的icon group),可以包含多张图片。这些图片有着各自的size或者颜色深度,这些图片可以是bmp格式或者png格式(vista之后支持,一般256*256时使用)


****************如果我们在win32环境下打开一个*.ico文件**************************

Icon文件结构由两部分组成:icon文件头和多张图片数据,图片可以是bmp、png:

Icon文件头typedef struct{    WORD idReserved; //必须为0    WORD idType; //如果是icons则必须是1    WORD idCount; //表示有多少张图片} ICONDIR, *LPICONDIR;其中idReserved必须是0;idType对于ICON文件来说必须是1;idCount指明icon文件有多少张图片,也就指明了接下来有多少个ICONDIRENTRY结构体数据。//在文件头后面则是 idCount个结构体  ICONDIRENTRY idEntries[x]; 每张图片详情结构体,图片数据不在这其中typedef struct{    BYTE bWidth;    BYTE bHeight;     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;//下面例子为从一个*.ico文件中更改exe文件的图标void changedExeIcon(LPCTSTR lpExeName, LPCTSTR lpIconFile){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];//填充信息,这里相当于一个转换的过程  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;}//开始更新EXE中的图标资源,ID定为最小0,如果原来存在0ID的图标信息则被替换为新的。  hUpdate = BeginUpdateResource(lpExeName, false);if (hUpdate != NULL){//首先更新RT_GROUP_ICON信息  ret = UpdateResource(hUpdate, RT_GROUP_ICON, MAKEINTRESOURCE(128), 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];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文件,到此更新操作结束!  delete[] pGrpIconDir;delete[] pIconDirEntry;CloseHandle(hIconFile);}


****************如果我们在一个exe或者ico的资源文件中使用icon**************************
它的结构有些微改变,如下:

注意:g_hModule为本进程实例句柄,也可以通过g_hModule = LoadLibrary(_TEXT("C:\\Ohter.exe")); 来获取其他exe中的资源文件,达到复制图标的效果。

//在使用时,这儿需要重新设置结构体对其方式,不然系统会默认为4个字节,我们就不能正确读取资源文件了#pragma pack( push ) #pragma pack( 2 )  //我们调整为2个字节对其typedef struct tagGRPICONDIR{WORD idReserved;WORD idType;WORD idCount;GRPICONDIRENTRY idEntries[1];}GRPICONDIR, *LPGRPICONDIR;#pragma pack( pop ) //恢复对齐状态#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;;#pragma pack( pop )//下面例子为从一个Icon资源文件中更改exe文件的图标void changedExeIcon(LPCTSTR lpExeName, UINT ulIconID){HRSRChRsrc = NULL;HGLOBALhGlobal = NULL;HANDLE  hUpdateRes = NULL;LPVOIDlpRes = NULL;LPGRPICONDIR lpIcon;if ((hRsrc = FindResource(g_hModule, MAKEINTRESOURCE(ulIconID), RT_GROUP_ICON)) == NULL)//获取ID为ulIconID1的Icon图标资源return ;if ((hGlobal = LoadResource(g_hModule, hRsrc)) == NULL)return ;if ((lpIcon = (LPGRPICONDIR)LockResource(hGlobal)) == NULL)return ;hUpdateRes = BeginUpdateResource(lpExeName, FALSE);if (hUpdateRes == NULL)return;DWORD szRes = SizeofResource(g_hModule, hRsrc);//128是WINDOWS系统默认图标//更新exe的RT_GROUP_ICONBOOL bSuc = UpdateResource(hUpdateRes, RT_GROUP_ICON, MAKEINTRESOURCE(128), MAKELANGID(LANG_CHINESE, SUBLANG_SYS_DEFAULT), LockResource(hGlobal), szRes);//读取Icon中每一个图片for (size_t i = 0; i < lpIcon->idCount; i++){if ((hRsrc = FindResource(g_hModule, MAKEINTRESOURCE(lpIcon->idEntries[i].nID), RT_ICON)) == NULL){return;}if ((hGlobal = LoadResource(g_hModule, hRsrc)) == NULL){return;}szRes = SizeofResource(g_hModule, hRsrc);//更新exe相应的RT_ICONUpdateResource(hUpdateRes, RT_ICON, MAKEINTRESOURCE(i), MAKELANGID(LANG_CHINESE, SUBLANG_SYS_DEFAULT), LockResource(hGlobal), szRes);//这儿有个疑问,在DLL中修改exe则为下面这样的格式,不知道为什么?//UpdateResource(hUpdateRes, RT_ICON, MAKEINTRESOURCE(lpIcon->idEntries[i].nID), MAKELANGID(LANG_CHINESE, SUBLANG_SYS_DEFAULT), LockResource(hGlobal), szRes);}EndUpdateResource(hUpdateRes, FALSE);}

本文参考:http://blog.csdn.net/hbxtlhx/article/details/5026725

原创粉丝点击