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

如何使用Delphi更改外部EXE文件的图标?,delphi,delphi-10.3-rio,Delphi,Delphi 10.3 Rio,我想使用Delphi更改以前生成的EXE文件的主图标。EXE文件也是由我使用Delphi生成的。但我希望用户能够更改其图标 我尝试使用UpdateResource函数更改RT_组图标和RT_图标,但未成功: procedure UpdateExeIcon(Const IconFilename, ExternalExeFilename:string); var Stream : TFileStream; hDestRes : THANDLE; lpData : Po

我想使用Delphi更改以前生成的EXE文件的主图标。EXE文件也是由我使用Delphi生成的。但我希望用户能够更改其图标

我尝试使用UpdateResource函数更改RT_组图标和RT_图标,但未成功:

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;
procedure-UpdateExeIcon(Const-IconFilename,ExternalExeFilename:string);
变量
流:TFileStream;
hDestRes:THANDLE;
lpData:指针;
cbData:DWORD;
开始
Stream:=TFileStream.Create(IconFilename、fmOpenRead或fmsharedynone);
尝试
Stream.Seek(0,从开始);
cbData:=Stream.Size;
如果cbData>0,则
开始
GetMem(lpData,cbData);
尝试
Stream.Read(lpData^,cbData);
hDestRes:=BeginUpdateResource(PChar(ExternalExeFilename),False);
如果hDestRes为0,则
开始
//如果更新资源(hDestRes、RT_图标、PChar('1')、1033、lpData、cbData),则
如果更新资源(hDestRes、RT_GROUP_图标、PChar('MAINICON')、1033、lpData、cbData),则
开始
如果不是EndUpdateResource(hDestRes,FALSE),则为RAISELASTERROR;
结束,否则将发生错误;
结束,否则将发生错误;
最后
FreeMem(lpData);
终止
终止
最后
免费;
终止
终止

有多个错误:

  • UpdateResource(hDestRes,RT_图标,PChar('1'),1033,lpData,cbData)
    中,
    lpName
    参数以两种方式工作:
    PChar('1')
    将显示为文本,而
    MakeIntResource(1)
    将显示为数字。您需要后一种变体,而不是前一种
  • 对于资源类型
    RT\u图标
    ,您必须提供实际图标有效负载,而不是整个图标文件。现在你做的是后者,而不是前者。查看图标文件的外观,然后查看资源仅有的内容
  • 资源类型
    RT_组_图标
    是描述现有
    RT_图标
    资源的“唯一”索引,应根据更新的图标进行修补(除非宽度、高度、颜色、像素深度和有效负载长度都相同)。在这里填写文件内容毫无意义
  • 上图显示了我们要更新的资源的原始字节
    128
    是十六进制字节的长度

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

    如果你做了所有这些(在
    RT\u ICON
    上使用
    MakeIntResource(1)
    并只提供图标文件的图片数据),那么你就没事了-这对我来说很好:然后我的EXE在Windows的资源管理器中显示了新图标(没有执行,tho)。还应该更新
    RT\u GROUP\u图标
    ,因为我不确定它在什么地方似乎没有效果,什么时候突然出现问题。在十六进制编辑器中查看文件和在资源编辑器中查看EXE将使您更好地理解所有操作。进一步阅读:

    • (相当容易)
    • 图标文件(几乎与图标文件相同)

      • 有多个错误:

      • UpdateResource(hDestRes,RT_图标,PChar('1'),1033,lpData,cbData)
        中,
        lpName
        参数以两种方式工作:
        PChar('1')
        将显示为文本,而
        MakeIntResource(1)
        将显示为数字。您需要后一种变体,而不是前一种
      • 对于资源类型
        RT\u图标
        ,您必须提供实际图标有效负载,而不是整个图标文件。现在你做的是后者,而不是前者。查看图标文件的外观,然后查看资源仅有的内容
      • 资源类型
        RT_组_图标
        是描述现有
        RT_图标
        资源的“唯一”索引,应根据更新的图标进行修补(除非宽度、高度、颜色、像素深度和有效负载长度都相同)。在这里填写文件内容毫无意义
      • 上图显示了我们要更新的资源的原始字节
        128
        是十六进制字节的长度

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

        如果你做了所有这些(在
        RT\u ICON
        上使用
        MakeIntResource(1)
        并只提供图标文件的图片数据),那么你就没事了-这对我来说很好:然后我的EXE在Windows的资源管理器中显示了新图标(没有执行,tho)。还应该更新
        RT\u GROUP\u图标
        ,因为我不确定它在什么地方似乎没有效果,什么时候突然出现问题。在十六进制编辑器中查看文件和在资源编辑器中查看EXE将使您更好地理解所有操作。进一步阅读:

        • (相当容易)
        • 图标文件(几乎与图标文件相同)

        您何时/何地得出“没有成功”的结论?其他哪些步骤成功?@AmigoJack该过程当然会注入一些东西,但不会更改主图标。Windows透视图中的主图标是第一个。使用资源编辑器检查可执行文件以查看发生了什么。和往常一样,解决问题的关键是调试它。刷新图标缓存有帮助吗@不,它不起作用。甚至尝试更改文件名。您何时/何地得出“未成功”的结论?其他哪些步骤成功?@AmigoJack该过程当然会注入一些东西,但不会更改主图标。Windows透视图中的主图标是第一个。Ins