如何使用Delphi更改外部EXE文件的图标?

时间:2020-08-01 09:09:48

标签: delphi delphi-10.3-rio

我想使用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;

1 个答案:

答案 0 :(得分:6)

有多个错误:

  1. UpdateResource(hDestRes, RT_ICON,PChar('1'),1033,lpData,cbData)中,lpName参数有两种工作方式:PChar('1')将显示为文本,而MakeIntResource(1)将显示为数字。您想要后一种,而不是前一种。
  2. 对于资源类型RT_ICON,您必须提供实际的图标有效载荷,而不是整个图标文件。现在,您要做的是后者,而不是前者。查看Icon文件的外观,然后查看资源仅包含的内容。
  3. 资源类型RT_GROUP_ICON是“仅”描述现有RT_ICON资源的索引,应根据更新的图标进行修补(除非宽度,高度,颜色,像素深度和有效载荷长度都是相同)。在这里填写文件内容毫无意义。

Resource Hacker: icon payload

上面您看到Resource Hacker显示我们要更新的资源的原始字节。 128是十六进制的字节长度。

HxD icon file container

在上方看到HxD显示整个图标文件-我选择了第一个图标有效载荷所在的部分:从偏移量26开始长度为128(均为十六进制)。两个字节序列都匹配。

如果您执行了所有操作(使用MakeIntResource(1)上的RT_ICON并仅提供图标文件的图片数据),那么您就可以了-对我来说很好:我的EXE然后显示了新的Windows'资源管理器中的图标(尚未执行)。还应该完成RT_GROUP_ICON的更新,因为我不确定它似乎在什么地方无效以及何时突然变成问题。在十六进制编辑器中查看文件,在资源编辑器中查看EXE将使您更好地理解所有操作。进一步阅读: