Y
Y
Yakov Kravtsov2014-02-22 13:05:07
Delphi
Yakov Kravtsov, 2014-02-22 13:05:07

How to solve the problem with writing a 256x256 icon to the *.exe file resources?

Greetings!
I set out to learn how to set an arbitrary icon for an arbitrary * .exe file. All this will be needed for the future project.
I write in Delphi, at the moment I completely switched to the XE5 version (before that, I used XE) for x64 and Android.
Operating system - Windows 8.1 Pro x64.
I immediately set myself the task of finding (making) code that compiles and is suitable for x32 and x64 executable files.
It was not possible to find anything suitable, although there were successful solutions. I decided to understand how it works (in what resources it is stored, what format these resources are available in) the *.exe icon in general.
I read carefully these two materials:
msdn.microsoft.com/en-us/library/ms997538.aspx
www.codeproject.com/Articles/30644/Replacing-ICON-...
I realized that in fact it is * .ico file. The difference with which is in two things:
1) The "entity" header is less than 2 bytes (for *.ico, the offset in the file is indicated - the DWORD type, and in the case of the application, the resource ID is indicated - the WORD type)
2) In the *.ico file, everything headers and data are included in 1 file and in application - headers are specified in RT_ICON_GROUP resource named 'MAINICON' and data is specified in RT_ICON resources with numeric name
Started writing code.
To begin with, I downloaded data from * .ico file and * .exe. Everything worked the first time, and worked without errors!
Further, I did the saving of the received data in * .ico - everything is fine. The icon file turned out to be identical in all checksums with the original one (including the one that was compiled into *.exe).
Here, at the stage of saving to *.exe, I immediately ran into a problem:
*.exe file was obtained without an icon, although all the resources were present in the water, but ResourceHacker could not read them.
All functions returned True.
I asked on several forums but couldn't find an answer.
I save like this:

procedure TdsIconResource.SaveToResource(aFileName: WideString; aLanguage: LANGID);
var
 entityid: Word;
 aStream: TMemoryStream;
 hUpdate: THandle;
 i: Integer;
 entity: TdsIconResourceEntity;
 procedure SpecialWrite(const Buffer; Count: Longint);
 var
  Writed: LongInt;
 begin
  Writed:=aStream.Write(Buffer, Count);

  if Writed <> Count then
   raise Exception.Create(Format('Writed fail, %d\%d', [writed, count]));
 end;
begin
 hUpdate:=BeginUpdateResourceW(PWideChar(aFileName), False);

 aStream:=TMemoryStream.Create;

 SpecialWrite(FHeader, SdsIconHeader);

 for I := 0 to FHeader.wCount - 1 do
  begin
   entity:=TdsIconResourceEntity(FEntities.Objects[i]);

   SpecialWrite(entity.FHeader, SdsIconEntityHeader);

   entityid:=i+1;

   SpecialWrite(entityid, SizeOf(Word));

   entity.FData.Position:=0;

   if not UpdateResourceW(hUpdate, RT_ICON, MAKEINTRESOURCE(entityid), aLanguage, entity.FData.Memory, entity.FData.Size) then
    raise Exception.Create('not UpdateResourceW~Icon~, '+IntToStr(GetLastError));
  end;

 aStream.Position:=0;

 if not UpdateResourceW(hUpdate, RT_GROUP_ICON, 'MAINICON', aLanguage, aStream.Memory, aStream.Size) then
  raise Exception.Create('not UpdateResourceW~Group~, '+IntToStr(GetLastError));

 if not EndUpdateResourceW(hUpdate, False) then
  raise Exception.Create('not EndUpdateResourceW, '+IntToStr(GetLastError));

 FreeAndNil(aStream);
end;

I made this application:
gm7zfSP7UWTsEWrhp437w.jpg
Link: floomby.ru/s2/E4d47u
(includes various *.ico files created in IcoFX from the original 256x256; the application itself; x32 blank - a console application, without any extra code and resources) .
Blank x64: floomby.ru/s2/54dWpb
During the tests
I found the reason why resources are struggling for some reason - this is the essence of an icon sized 256x256!
If there is one, it does not matter whether it is in the *.ico file or in the *.exe resources - then the "blank is burned" crookedly - the resources are struggling, the executable file refuses to start!
At the same time, Delphi - compiles with such an icon perfectly!
What can be wrong?
And how can you fix all this? And in which direction to dig?
PS
Can you help me with one more question? As I understand it, if we take a pointer to the RT_ICON resource data - that is, to the entity data itself, without a header and lead to the HICON type - then we will get a ready-to-use HICON?
I tried to make TImage.Picture.Icon.Handle:=HIcon(...) - it doesn't output anything!

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question