已阅读5页,还剩2页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
通过代码实现EXE文件图标的替换最近,好多人问我如何通过写个小程序,动态替换可执行文件的图标。这个问题看起来虽小,但却涉及到很多问题。网上也只能找到一些零零散散的资料,却没有详细的指导性文档。所以我决定把这个问题写下来,以方便大家查阅。EXE文件图标的替换有很多方法,例如用一个EXE文件的图标替换另外一个EXE文件的图标;用一个ICO文件内的图标替换EXE文件的图标。这两种情况替换的方法不太相同,下面会详细讨论。EXE文件图标的替换更一般的情形,是PE(Portable Executable)文件图标的替换。只不过Windows操作系统只会显示EXE文件的图标罢了。但DLL、OCX等PE文件也都可以包含图标资源。下面我们从ICO文件格式说起,一步步讲解替换EXE文件图标的方法和原理。.ico文件中图标的保存格式对于一个扩展名是.ico的文件,大部分人会认为一个ICO文件里面只能包含一个图标。但事实上,一个ICO文件里面可以包含很多图标。而且,目前大部分ICO文件里面都包含有不同尺寸、不同色深的好几个图标。我们以MSN安装包里的msnmsn.ico为例,这个图标文件就包含了9个不同尺寸、不同色深的图标,如图所示:图1 msnms.ico这样做的目的,是为了保证不同的操作系统、不同的桌面色深,图标显示均可达到最佳效果。操作系统会选择并显示一个最合适的图标。Windows XP支持32位色的图标,Windows 2000最多只支持256色的图标。所以,如果我们开发的软件若要同时支持Windows XP和2000,那么为了达到视觉上的最佳效果,每一个ICO文件应至少包含两个图标,一个是32位色的,一个是256色的。 ICO文件头部结构定义如下:typedef struct ICONDIR WORD idReserved; /保留(must be 0) WORD idType; /资源的类型(1 for icons) WORD idCount; /有多少图片? ICONDIRENTRY idEntries1; /图片的为每个形象(idCount of em)typedef struct ICONDIR *LPICONDIR;/DWORD相当于C#中的uintidCount表示该ICO文件包含图标的数量,所以理论上,一个ICO文件最多可以包含65535个图标。接下来,是该文件所包含的每一个图标的描述。typedef struct ICONDIRENTRY BYTE bWidth; /在像素,宽度的形象 BYTE bHeight; /高度,在像素,的形象 BYTE bColorCount; /颜色的数字图像(0 if =8bpp) BYTE bReserved; / 保留 ( must be 0) WORD wPlanes; /彩色平面 WORD wBitCount; /每像素比特数 DWORD dwBytesInRes; /有多少字节这资源? DWORD dwImageOffset; /在该文件是这形象?,typedef struct ICONDIRENTRY *LPICONDIRENTRY;ICONDIRENTRY中记录了每一个图标的尺寸、色深、图标资源占用的字节数。dwImageOffset是一个文件偏移地址,指向图标资源数据起始位置。至于每一个图标资源内部的具体格式,与本文关系不大,这里就不再详细介绍了。PE文件中的图标保存格式PE文件中的图标保存格式与.ico文件中图标的保存格式略有不同。PE文件中,把ICONDIR和图标资源作为两种资源类型分别保存,前者是RT_GROUP_ICON类型,后者是RT_ICON类型。为了与.ico文件中图标的保存格式做以区分,我们把PE文件中的图标保存格式重新定义如下:/ #使用的来确保结构/包装,记忆与包装EXE或DLL.#pragma pack( push )#pragma pack( 2 )typedef struct WORD idReserved; / Reserved (must be 0) WORD idType; / Resource type (1 for icons) WORD idount; / How many images? GRPICONDIRENTRY idEntries1; / The entries for each image GRPICONDIR, *LPGRPICONDIR;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 )这里有一个区别,就是在.ico文件中,ICONDIRENTRY结构最后一个成员dwImageOffset表示的是图标资源文件偏移地址。而PE文件中,GRPICONDIRENTRY结构最后一个成员nID表示的是图标的索引ID。Windows APIWindows操作系统为我们提供了几个API函数,用来更新PE文件中资源的函数有:BeginUpdateResource, UpdateResource, EndUpdateResource。用来枚举PE文件中资源的函数有:EnumResourceTypes,EnumResourceNames,EnumResourceLanguages。具体的使用方法可以参见MSDN。下面我们通过具体的例子,来验证上面的方案是否可行。用一个EXE中的图标替换另外一个EXE文件的图标在这个例子中,我们用Windows XP自带的记事本的图标替换计算器的图标。 图2 记事本图标图3 计算器图标下面代码演示了如何替换32x32 32bits的图标:HMODULE hModule = :LoadLibrary(notepad.exe);HRSRC hResInfo = :FindResource(hModule, MAKEINTRESOURCE(8), RT_ICON);HGLOBAL hGlobal = :LoadResource(hModule, hResInfo);DWORD dwSize = :SizeofResource(hModule, hResInfo);void* pData = :LockResource(hGlobal);HANDLE hUpdate = :BeginUpdateResource(calc.exe, FALSE);VERIFY(:UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(7), MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), pData, dwSize);VERIFY(:EndUpdateResource(hUpdate, FALSE);VERIFY(:FreeLibrary(hModule);大家肯定有个疑问,上面代MAKEINTRESOURCE(8)和MAKEINTRESOURCE(7)是怎么来的呢?其实索引8和7分别是notepad.exe和calc.exe中,32x32 32bits图标的索引。我们可以通过加载RT_GROUP_ICON资源,然后遍历GRPICONDIRENTRY中每一个图标的大小、色深,找到这个图标的索引。为了简便,这里直接写死的索引号,省略了这一动态查找的过程。还有一个疑问应该就MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)了。PE文件中,每一个资源都至少对应一种语言。因为我的操作系统是英文的,所以记事本和计算器中的图标资源语言也是英文的。对于简体中文Windows XP操作系统所自带的记事本和计算器,这个值应该是MAKELANGID(LANG_CHINESE, SUBLANG_SYS_DEFAULT)。那么我们怎么才能知道一个PE文件中,图标资源的语言是什么呢?我们可以通过资源枚举API,枚举所有图标、语言。可以参考上面提到过的那几个API函数,并查阅MSDN获取这些函数的帮助文档。我们用记事本32x32 32bits图标替换计算器同样尺寸、色深的图标后,效果如下,在Titles显示方式下,图标大小是48x48的,图标没有被改变:图4 48x48图标在Icons显示方式下,图标大小是32x32的,图标被我们改变了: 图5 32x32图标用一个ICO文件中的图标替换另外一个EXE文件的图标用ICO文件中的图标替换EXE文件图标稍微有点麻烦,我们必须借助数据结构ICONDIR和ICONDIRENTRY来完成。我们使用msnms.ico中的32x32 32bits图标替换计算器中同样大小色深的图标:DWORD dwSize = sizeof(ICONDIRENTRY);HANDLE hFile = :CreateFile(msnms.ico, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);:SetFilePointer(hFile, sizeof(ICONDIR) + dwSize * 6, NULL, FILE_BEGIN);DWORD dwRead = 0;ICONDIRENTRY Entry;VERIFY(:ReadFile(hFile, &Entry, dwSize, &dwRead, NULL);:SetFilePointer(hFile, Entry.dwImageOffset, NULL, FILE_BEGIN);void* pData = new charEntry.dwImageOffset;VERIFY(:ReadFile(hFile, pData, Entry.dwBytesInRes, &dwRead, NULL);HANDLE hUpdate = :BeginUpdateResource(calc.exe, FALSE);VERIFY(:UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(7), MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), pData, Entry.dwBytesInRes);VERIFY(:EndUpdateResource(hUpdate, FALSE);delete pData;pData = NULL;VERIFY(:CloseHandle(hFile);上面代码中sizeof(ICONDIR) + dwSize * 6的意思是定位到第8个标结构体ICONDIRENTRY的位置,这个图标是32x32 32bits的。我们可以通过遍历每一个ICONDIRENTRY来判断,到底哪个图标是这个尺寸的。这里我们为了简便,把这部分代码省略了。定位到第8个图标结构体ICONDIRENTRY的位置后,Entry.dwImageOffset的值就是第
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 46733-2025车载独立空调器安装规范
- GB/T 43584.1-2025生物技术大规模并行测序第1部分:核酸与文库制备
- 市场监督管理局股权转让合同6篇
- 2025年合同研究组织项目发展计划
- 游乐园安全课件图片高清
- 度煤矿井下从业人员安全知识考试题库(含答案)
- 儿童暑期安全教育课件
- 心理咨询师二级考试模拟试题及答案
- 成都市规培护士考试题库
- 手术室新入职护士考试试题及答案
- 民间体育游戏培训
- 走进创业学习通超星期末考试答案章节答案2024年
- 安全生产全员责任制度
- 互联网域名产业报告(2024年)
- CATTI汉英词汇手册
- 高三英语一轮复习课标3000词汇表清单
- 窗抗风载荷计算
- 2023年全国职业院校技能大赛-植物病虫害防治赛项规程
- HG∕T 5259-2017 聚醚酯消泡剂
- 国有企业采购管理规范 T/CFLP 0027-2020
- 幼儿园大班语言诗歌:《冬天》 课件
评论
0/150
提交评论