如何使用 Delphi 更改外部 EXE 文件的图标?
How to change the icon of an external EXE file using Delphi?
我想使用 Delphi 更改以前生成的 EXE 文件的主图标。 EXE文件也是我用Delphi生成的。但我希望用户能够更改其图标。
我尝试使用 UpdateResource 函数更改 RT_GROUP_ICON 和 RT_ICON 但没有成功:
procedure UpdateExeIcon(Const IconFilename, ExternalExeFilename:string);
var
Stream : TFileStream;
hDestRes : THANDLE;
lpData : Pointer;
cbData : DWORD;
begin
Stream := TFileStream.Create(IconFilename,fmOpenRead or fmShareDenyNone);
try
Stream.Seek(0, soFromBeginning);
cbData:=Stream.Size;
if cbData>0 then
begin
GetMem(lpData,cbData);
try
Stream.Read(lpData^, cbData);
hDestRes:= BeginUpdateResource(PChar(ExternalExeFilename), False);
if hDestRes <> 0 then
begin
//if UpdateResource(hDestRes, RT_ICON,PChar('1'),1033,lpData,cbData) then
if UpdateResource(hDestRes, RT_GROUP_ICON,PChar('MAINICON'),1033,lpData,cbData) then
begin
if not EndUpdateResource(hDestRes,FALSE) then RaiseLastOSError;
end else RaiseLastOSError;
end else RaiseLastOSError;
finally
FreeMem(lpData);
end;
end;
finally
Stream.Free;
end;
end;
有多个错误:
- 在
UpdateResource(hDestRes, RT_ICON,PChar('1'),1033,lpData,cbData)
中,lpName
参数有两种工作方式:PChar('1')
将显示为文本,而 MakeIntResource(1)
将显示为数字。你想要后者,而不是前者。
- 对于资源类型
RT_ICON
,您必须提供实际图标 有效负载,而不是整个图标 文件。现在你做的是后者,而不是前者。看看一个Icon文件长什么样,再看看资源只有什么
- 资源类型
RT_GROUP_ICON
“只是”一个描述现有 RT_ICON
资源的索引,应该根据更新后的图标进行修补(除非宽度、高度、颜色、像素深度和负载长度是全都一样)。在这里填写文件内容毫无意义。
您在上方看到 Resource Hacker 显示了我们要更新的资源的原始字节。 128
是十六进制的字节长度。
上面你看到 HxD 显示了整个图标 file - 我选择了第一个图标 payload 所在的部分:从偏移量 26
开始,长度为 128
(均为十六进制)。两个字节序列匹配。
如果你做了所有这些(在 RT_ICON
上使用 MakeIntResource(1)
并仅提供图标文件的图片数据)那么你很好 - 它对我来说很好:然后显示我的 EXE Windows' 资源管理器中的新图标(还没有执行,不过)。更新 RT_GROUP_ICON
也应该完成,因为我不确定它似乎无效的地方以及它突然成为问题的时间。在十六进制编辑器中查看文件并在资源编辑器中查看 EXE 将使您更好地理解所有操作。延伸阅读:
- Icon file format(很简单)
- RT_GROUP_ICON format(几乎与图标文件相同)
我想使用 Delphi 更改以前生成的 EXE 文件的主图标。 EXE文件也是我用Delphi生成的。但我希望用户能够更改其图标。
我尝试使用 UpdateResource 函数更改 RT_GROUP_ICON 和 RT_ICON 但没有成功:
procedure UpdateExeIcon(Const IconFilename, ExternalExeFilename:string);
var
Stream : TFileStream;
hDestRes : THANDLE;
lpData : Pointer;
cbData : DWORD;
begin
Stream := TFileStream.Create(IconFilename,fmOpenRead or fmShareDenyNone);
try
Stream.Seek(0, soFromBeginning);
cbData:=Stream.Size;
if cbData>0 then
begin
GetMem(lpData,cbData);
try
Stream.Read(lpData^, cbData);
hDestRes:= BeginUpdateResource(PChar(ExternalExeFilename), False);
if hDestRes <> 0 then
begin
//if UpdateResource(hDestRes, RT_ICON,PChar('1'),1033,lpData,cbData) then
if UpdateResource(hDestRes, RT_GROUP_ICON,PChar('MAINICON'),1033,lpData,cbData) then
begin
if not EndUpdateResource(hDestRes,FALSE) then RaiseLastOSError;
end else RaiseLastOSError;
end else RaiseLastOSError;
finally
FreeMem(lpData);
end;
end;
finally
Stream.Free;
end;
end;
有多个错误:
- 在
UpdateResource(hDestRes, RT_ICON,PChar('1'),1033,lpData,cbData)
中,lpName
参数有两种工作方式:PChar('1')
将显示为文本,而MakeIntResource(1)
将显示为数字。你想要后者,而不是前者。 - 对于资源类型
RT_ICON
,您必须提供实际图标 有效负载,而不是整个图标 文件。现在你做的是后者,而不是前者。看看一个Icon文件长什么样,再看看资源只有什么 - 资源类型
RT_GROUP_ICON
“只是”一个描述现有RT_ICON
资源的索引,应该根据更新后的图标进行修补(除非宽度、高度、颜色、像素深度和负载长度是全都一样)。在这里填写文件内容毫无意义。
您在上方看到 Resource Hacker 显示了我们要更新的资源的原始字节。 128
是十六进制的字节长度。
上面你看到 HxD 显示了整个图标 file - 我选择了第一个图标 payload 所在的部分:从偏移量 26
开始,长度为 128
(均为十六进制)。两个字节序列匹配。
如果你做了所有这些(在 RT_ICON
上使用 MakeIntResource(1)
并仅提供图标文件的图片数据)那么你很好 - 它对我来说很好:然后显示我的 EXE Windows' 资源管理器中的新图标(还没有执行,不过)。更新 RT_GROUP_ICON
也应该完成,因为我不确定它似乎无效的地方以及它突然成为问题的时间。在十六进制编辑器中查看文件并在资源编辑器中查看 EXE 将使您更好地理解所有操作。延伸阅读:
- Icon file format(很简单)
- RT_GROUP_ICON format(几乎与图标文件相同)