如何使用 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;

有多个错误:

  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 显示了我们要更新的资源的原始字节。 128 是十六进制的字节长度。

上面你看到 HxD 显示了整个图标 file - 我选择了第一个图标 payload 所在的部分:从偏移量 26 开始,长度为 128(均为十六进制)。两个字节序列匹配。

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