4

How to accomplish the following goal in Delphi 10.2 Tokyo: I need Delphi to automatically set not just the big icon, but both the big and small icons for each window. I need to have an opportunity, for some of the forms, and for the TApplication, to change icons at run-time. I want this to be accomplished without modifying VCL.Forms.pas (the small icon is one that displayed in a window title bar, to the left from window caption).

There is a function in TCustomForm:

function GetIconHandle: HICON;

Unfortunately, Delphi only sets big icon handle, for example, here is a quote from VCL.Forms.pas:

  SendMessage(Handle, WM_SETICON, ICON_BIG, GetIconHandle);

As you see, the above code only sets the big icon handle, but I also need to set the small icon handle, since the .ICO files that I use contain different images for big and small icons.

Let me brefly summarize the differences between the big and the small icons, since even the Microsoft documentation almost tells nothing about it. Here are the main differences:

  • Small icon image is displayed on the window title bar.

  • Large icon image is displayed in the Windows taskbar (usually located at the bottom part of the screen), if the taskbar is thick; the large icon image is also displayed when you press Alt+Tab.

See https://blog.barthe.ph/2009/07/17/wmseticon/ for more information on big and small icons.

Delphi, by setting only the large window handle, effectively phases out the alternative image for a smaller icon shown on window titles. If only big icon is given but not the small one, Windows resamples the image from the bigger icon to the smaller one, quality worsens, and the main idea of a smaller, simpler image is lost.

See the example image courtesy sanyok. The left column, labeled v7.4.16 are screenshots from a program compiled with a code that sets both ICON_BIG and ICON_SMALL. The right column, labeled v7.4.16.22 is a screenshot from the same program that doesn't explicitly sets both small and big icons, but just assigns TIcon to a form, an then Delphi using its standard code just assigns just the big icon, so the image from the windows title bar is resized by Windows from the large icon. You may see how poor the quality becomes as a result of standard Delphi behaviour.

Big vs Small Icons

In the past, I was changing the GetIconHandle in the interface section of the VCL.Forms.pas from static to virtual, changing it from function to procedure and adding two parameters:

procedure GetIconHandle(var Big, Small: HICON); virtual;

So the subsequent code in the VCL.Forms.pas was like the following:

var
  Big, Small: HICON;
begin    
  [...]
  GetIconHandle(Big, Small);
  SendMessage(Handle, WM_SETICON, ICON_BIG, LParam(Big));
  SendMessage(Handle, WM_SETICON, ICON_SMALL, LParam(Small));
  [...]

Is it possible to easily accomplish this without modifying the VCL.Forms.pas?

I did solve the problem in Delphi 2007 by modifying VCL units, but I can no longer modify VCL units in Delphi 10.20 Tokyo for the following reasons:

  1. VCL units compile, but then, when I compile my application, I get "Internal Error: AV0047C6C7-R000004CC-0", regardless of a target targets (Win32/Win64; Debug/Release), see https://quality.embarcadero.com/browse/RSP-18455 - the first part of the error number (address) is different, but the second - R000004CC-0 - is always the same.

  2. I have to manually add (TObject) to each of the classes that do not inherit from any class; otherwise I gen an error that Create or Destroy is not found in base class. In previous versions of Delphi, writing simply class without any ancestor implicitly inherited it from TObject, but when I compile code from command-line by dcc32 with dcc32 -Q -M -$D- -$M+ command line options, this error occurs that Create or Destroy is not found in base class.

Here is how I did loaded the icons in the past:

procedure LoadIconPair(var Big, Small: hIcon; AName: PChar);
begin
  if Win32MajorVersion < 4 then
  begin
    Big := LoadIcon(hInstance, AName);
    Small := 0;
  end
  else
  begin
    Big := LoadImage(hInstance, AName, IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
    Small := LoadImage(hInstance, AName, IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  end;
end;

This code can be further improved: the hard-coded sizes of 32x32 and 16x16 can be changed, as suggested at https://blog.barthe.ph/2009/07/17/wmseticon/ , to GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) for big icons and GetSystemMetrics(SM_CXSMICON) and GetSystemMetrics(SM_CYSMICON) for small icons.

So, each form essentially called LoadIconPair and then returned the handles via the overwritten procedure GetIconHandle(var Big, Small: HICON); override;.

So the questions are the following:

  1. Is it possible to let Delphi set both small and big icons without much hassle and without modifying VCL.Forms.pas? (this is the main question) -- I need to have an opportunity, for some of the forms, and for the TApplication, to change icons at run-time.;

  2. If not, how to add a modified source VCL unit to your application under Delphi 10.2 Tokyo, where the interface section of a unit is modified? Are there any instructions, or an official guide? If anybody managed to do that, how did you accomplish that? Did you compile them from the GUI IDE? Or using command line dcc32/dcc64? Or using msbuild? Or otherwise? Do you also have to manually add (TObject) to classes that do not inherit from any class to avoid the Create or Destroy is not found in base class error?

Update #1: Setting the icons again after VCL.Forms.pas has set it is not a complete solution: we have to also take care about the Application icon, not only the forms icons; besides that, VCL.Forms.pas sets the icons anyway, but only the ICON_BIG, we have to set the icons again, this time setting both small and big. Do you have an idea on how can we patch the VCL.Forms.pas to add setting the ICON_SMALL whenever it sets the big icon, so we only patch the implementation section, and will call some messages, even WM_USER+N to request the icon handles from the form, and our descendant of TForm will implement this message handler?

Update #2: TApplication and TForm have similar interfaces with regard to icons, but TApplication is a descendant of TComponent which do not have a window handle, and, respectively, don't have message handlers. What we can do with a TForm, we cannot do with TApplication.

Update #3: I have implemented a solution which is a mixture of what kobik has suggested in his post and Sertac Akyuz has suggested in his later post. Thank you also to the other people who have contributed in the comments. I've compiled the program and gave it to the beta testers and they have confirmed that the problem has been fixed, the icon look good now, also the animation of the icon in the TApplication via changing icons by timer is also working properly. Thank you all!

Maxim Masiutin
  • 3,991
  • 4
  • 55
  • 72
  • 2
    How is your `GetIconHandle` method looks like? What kind of icons you use? I mean is it consists of multiple sizes? (Can you upload a sample?) Also do you override this method for each form and return the appropriate icons? To be honest I never even thought about this issue... Interesting. in any case patching the `interface` section is a bad idea IMO. – kobik Jun 25 '17 at 17:17
  • 4
    1. No. I consider runtime patching not hassle free. 2. You can't. Modifiying interface sections of source units is not supported. – Sertac Akyuz Jun 25 '17 at 19:04
  • 5
    With so long a background story it is not surprising that you've got two answers which neither answers none of your two question. Additionally I wonder if you're interested with an actual answer regarding your comments to those answers. – Sertac Akyuz Jun 25 '17 at 19:08
  • @Paul - it supports, isn't it? https://www.ritlabs.com/unicode-in-folder-names-1.png https://www.ritlabs.com/unicode-in-folder-names-2.png – Maxim Masiutin Jun 28 '17 at 15:49
  • 2
    `Update #2: TApplication and TForm have similar interfaces with regard to icons, but TApplication is a descendant of TComponent which do not have a window handle...` this is simply wrong. `Application.Handle` represent its *internal* Window handle. You can `SendMessage(Application.Handle, WM_SETICON...` as I mentioned in my answer. maybe that was something you missed all along, – kobik Jul 02 '17 at 05:28
  • @kobik - this is not wrong. TComponent doesn't have a window handle, so the statement was true ("TComponent which do not have a window handle") - I've ment that it was TComonent that do not have a handle. As about the TApplication - it adds the handle and other methods, similar to those of TForm - adds from scratch. TApplication and TForm don't have common ancestors other than TComponent. You can find out more about TComponent at http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Classes_TComponent.html to find out that it do not have handle. – Maxim Masiutin Jul 02 '17 at 06:25
  • so you cannot unify the work with TForm and TApplicatoin via a common ancestor - you have to handle both of them differently. – Maxim Masiutin Jul 02 '17 at 06:26
  • 1
    @MaximMasiutin, `so you cannot unify the work with TForm and TApplicatoin via a common ancestor` - This is true. I never told otherwise. but I explained how to handle the **Application** icon. – kobik Jul 02 '17 at 06:50
  • @kobik - your explanation was helpful, I have solved the issue with the application so far, thank you! – Maxim Masiutin Jul 02 '17 at 07:03
  • 1
    @MaximMasiutin, You welcome. glad I could help. – kobik Jul 02 '17 at 09:34

3 Answers3

8

Patching the interface section of Delphi's core VCL/RTL sources in not allowed (in theory). The fact that you managed to do so previously returned as a boomerang now. You can in most case do what you need without patching the sources, e.g. by using inheritance, class helpers, patching code in runtime, detours, and in other cases (which IMO is the last resort) patch the implementation section and use a local copy for you project which is allowed - see also How to recompile modifications to VCL source file and How to change VCL code?

I suggest to create an ancestor base class for all your forms (I think any large project should do so) in the application and override CreateWnd:

procedure TBaseForm.CreateWnd;
var
  Big, Small: HICON;
begin
  inherited;
  if BorderStyle <> bsDialog then
  begin
    GetIconHandles(Big, Small);
    if Big <> 0 then
      SendMessage(Handle, WM_SETICON, ICON_BIG, LParam(Big));
    if Small <> 0 then
      SendMessage(Handle, WM_SETICON, ICON_SMALL, LParam(Small));
  end;
end;

Introduce two virtual methods:

procedure TBaseForm.GetIconResName(var Name: string);
begin
  Name := 'MAINICON';
end;

procedure TBaseForm.GetIconHandles(var Big, Small: HICON);
var
  ResName: string;
begin
  Big := 0;
  Small := 0;
  GetIconResName(ResName);
  if ResName = '' then Exit;

  Big := LoadImage(HInstance, PChar(ResName), IMAGE_ICON,
    GetSystemMetrics(SM_CXICON),
    GetSystemMetrics(SM_CYICON),
    0);
  Small := LoadImage(HInstance, PChar(ResName), IMAGE_ICON,
    GetSystemMetrics(SM_CXSMICON),
    GetSystemMetrics(SM_CYSMICON),
    0);
end;

All you need to do in your child classes is to override the GetIconResName.

i.e:

TMyChildForm = class(TBaseForm)
protected 
  procedure GetIconResName(var Name: string); override;
end;

procedure TMyChildForm.GetIconResName(var Name: string);
begin
  Name := 'SPIDERMAN';
end;

This is not a complete solution...

I tried to give you some leads to show patching the VCL source is not needed.

In any case, I don't have any issues if I use the Icon property (both Application and Form) and provide icon with at least 2 sizes (16x16 and 32x32) 32 bit depth (use other formats if needed), Windows will display the correct icon. i.e. the system displays the large icon in the ALT+TAB dialog box, and the small icon in the window caption. even though only ICON_BIG is sent to the Form/Application window handle. (Delphi7/Win7). (This is why I asked for MCVE. including information about your Icons format. and not just fragments of code like you did ...)


Since I am confused about your precise requirements, and you still refuse to provide MCVE, I'll try to provide another approach:

You say you need to handle the Application Icon also. the Application icon is set early when the Application is created - not simple to handle in your forms because they are not yet created. but whenever the Application.Icon is changed the application notifies the forms with CM_ICONCHANGED (see: procedure TApplication.IconChanged(Sender: TObject);). so you can re-set the the Application icon in that message handler via SendMessage(Application.Handle, WM_SETICON... (this won't trigger CM_ICONCHANGED) or setting the Application.Icon directly (which will also trigger CM_ICONCHANGED). if needed set the big and small icons via WM_SETICON message. You will also need to set the class icon:

SetClassLong(Application.Handle, GCL_HICON, FIcon);

So whenever the application icon is changed, covered by CM_ICONCHANGED in your forms.

TBaseForm = class(TForm)
private
  procedure CMIconChanged(var Message: TMessage); message CM_ICONCHANGED;
...
procedure TBaseForm.CMIconChanged(var Message: TMessage);
...

If you need to set that Icon early in your application (which I don't think is required) do the above in the Main form creation only.

To catch/handle the Forms icons use the WM_SETICON messages handler in your forms:

TBaseForm = class(TForm)
private
  procedure WMSetIcon(var Message: TWMSetIcon); message WM_SETICON;
...

procedure TBaseForm.WMSetIcon(var Message: TWMSetIcon);
begin
  if (Message.Icon <> 0) and (BorderStyle <> bsDialog) then
  begin    
    // this big icon is being set by the framework
    if Message.BigIcon then
    begin      
      // FBigIcon := LoadImage/LoadIcon...
      // if needed set Message.Icon to return a different big icon
      // Message.Icon := FBigIcon;
      // in practice create a virtual method to handle this section so your child forms can override it if needed
      inherited;

      FSmallIcon := LoadImage/LoadIcon...    
      // set small icon - this will also re-trigger WMSetIcon
      Perform(WM_SETICON, ICON_SMALL, FSmallIcon);
    end else
      inherited;
  end
  else
    inherited;
end;

This should get you covered in all situations.

kobik
  • 21,001
  • 4
  • 61
  • 121
  • Thank you! Excellent idea! I will do that and let you know the results. – Maxim Masiutin Jun 25 '17 at 18:12
  • 1
    BTW as you see `GetIconHandles` can be static. – kobik Jun 25 '17 at 18:19
  • 1
    Perhaps default implementation can return form class name, then you'll have the opportunity of not writing a single line of code and instead populate a resource file accordingly. Otherwise I fail to see any advantage over calling a utility function through a single liner from an OnCreate handler. – Sertac Akyuz Jun 25 '17 at 19:06
  • 2
    @SertacAkyuz, I simply followed the OP's implementation (`LoadIconPair`). using the class name as optional resource name is indeed a nice addition. – kobik Jun 26 '17 at 04:35
  • Could you please extend the answer with an idea of what to do with the Application icon - it should also honor small and large icon. We have figured out that unless we patch Forms.pas, there will be endless problems - users complaining that their taskbar icon is missing or incorrect. – Maxim Masiutin Jun 26 '17 at 10:52
  • This is not a complete solution: VCL.Forms.pas sets the icons anyway, but only the `ICON_BIG`, we have to set the icons again, this time setting both small and big. Do you have an idea on how can we patch the VCL.Forms.pas to add setting the `ICON_SMALL` whenever it sets the big icon, so we only patch the `implementation` section, and will call some messages, even WM_USER+N to request the icon handles from the form, and our descendant of TForm will implement this message handler? I have added the update to the initial question. – Maxim Masiutin Jun 26 '17 at 14:57
  • 3
    You don't need to patch anything in the VCL. You could just intercept all `WM_SETICON` messages sent to the Form's window (subclass the Form's `WindowProc` property, or override its virtual `WndProc()` method). Whenever you see a BIG icon being set, pass the message to the default handler, and then manually send a SMALL icon to the same default handler. You can do something similar with the `TApplication` window via the `TApplication.HookMainWindow()` method. – Remy Lebeau Jun 27 '17 at 00:45
  • 2
    @RemyLebeau, Very good idea. although I don't have any issue and can't reproduce the "problem". maybe post this comment as answer? – kobik Jun 27 '17 at 05:46
  • @RemyLebeau - please consider adding a full answer. – Maxim Masiutin Jun 28 '17 at 15:44
4

I just created a new VCL forms application, set the Application icon in the project options and the (only, main) form's Icon to the same file, which I had modified to make the 16x16 (32 bit depth) look differently, and added the following code:

{ TForm27 }

procedure TForm27.SetIcons;
var
  MainIcon, SmallIcon: HICON;
begin
  MainIcon := Application.Icon.Handle;
  SmallIcon := Icon.Handle;
  Perform(WM_SETICON, ICON_BIG, MainIcon);
  Perform(WM_SETICON, ICON_SMALL, SmallIcon);
end;

procedure TForm27.FormCreate(Sender: TObject);
begin
  SetIcons;
end;

This produced the following display:

Modified form icon

Note that both use the same .ico file, an ugly modification of ib.ico that comes with 10.2 Tokyo. I just painted a few black lines and ovals on the small icon only.

I don't know the code of your GetIconHandle modification, but you could do the same here. Also note that it doesn't work if I use (the Form's) Icon.Handle for both. If I do that, the ugly 16x16 icon gets displays in the application bar too.

But I did not have to modify any VCL code. You can do this in any VCL application.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
  • I know that explicitly calling WM_SETICON with ICON_BIG and ICON_SMALL works; however, Delphi itself sometimes sets ICON_BIG, so in some complex scenarios you will have to catch these cases and call the WM_SETICON with ICON_BIG again. The question was not on the Windows API, it was on Delphi to simplify the use of the icons when you have many forms. I'm sorry but I cannot accept this answer. Besides that, my code in the question did already have the same as you have posted: SendMessage(Handle, WM_SETICON, ICON_BIG, LParam(Big)); SendMessage(Handle, WM_SETICON, ICON_SMALL, LParam(Small)); – Maxim Masiutin Jun 25 '17 at 17:49
  • 1
    @Maxim: yes, I used your example code, merely to show you that this does not necessarily require a modifcation of the VCL. And you don't have to accept my answer, although it does answer what you ask, but a downvote is IMO not appropriate. – Rudy Velthuis Jun 25 '17 at 17:57
  • I didn't write that the modification of VCL is the only answer, I just wrote that I was used it in the past. This is obvious that `WM_SETICON` for each form works. Don't take offence, but it is like 'captain the obvious'. – Maxim Masiutin Jun 25 '17 at 18:03
  • 1
    Your main question was "Is it possible to let Delphi set both small and big icons without much hassle and without modifying VCL.Forms.pas?". Well, yes, it is, as I showed. Not much hassle and no mods of the VCL code. – Rudy Velthuis Jun 25 '17 at 18:05
  • 2
    If that was not what you wanted to know, then you should have asked a different question. Yes, of course it was a "Captain Obvious" answer, because it was pretty obvious, so I wonder why you don't simply do it that way? – Rudy Velthuis Jun 25 '17 at 18:09
  • 1
    This WM_SETICON and loading icons for each of the forms is a hassle - since I have shown that this code is now what I like. Somebody once wrote me that replies that are not replies to the exact questions should be posted as comments, not as replies, although I'm a newbie here, but the atmosphere is very unfriendly here. I once had a good question that was downvoted/deleted many times; I have changed it to create from scratch 4 times until finally got a good reply (about Base DPI) until it finally got deleted. – Maxim Masiutin Jun 25 '17 at 18:09
  • I wanted to cancel the downvote but it told me that I cannot do it until you edit the answer. – Maxim Masiutin Jun 25 '17 at 18:10
  • I would have expected, for example, a helper function or a base form from which to inherit forms that will do all the job for me. – Maxim Masiutin Jun 25 '17 at 18:11
  • 1
    Edited the answer a bit. – Rudy Velthuis Jun 25 '17 at 18:15
  • 1
    You could, for instance, use an inherited form and intercept the CM_ICONCHANGED message earlier, before CMIconChanged can be called. – Rudy Velthuis Jun 25 '17 at 18:20
  • Thank you for editing the answer, I have upvoted it. – Maxim Masiutin Jun 25 '17 at 18:23
  • 1
    @Maxim: Thanks. Overriding `CreateWnd` is another hook, as the other answer shows. For such things (especially in the VCL), there are usually several "hooks" that can be used to intercept a message before a private method is called. It is seldom necessary to modify the VCL, and, as you found out, that can cause several problems. – Rudy Velthuis Jun 25 '17 at 18:27
  • It's very common and normal for you to introduce such handling on your own projects. VCL is very old, and really tries its best to retain backwards compatibility. So, they don't like to change too much of the VCL. I mean, just look at the ancient `Printers` unit / WinAPI calls they're using still to this day. Of course there's a solution to just about any problem, but that solution is rarely ever modifying the VCL source. And even then, as covered in many other questions here, you can only modify the implementation, not the interface. – Jerry Dodge Jun 25 '17 at 21:13
  • @RudyVelthuis, I'm a bit confused. if you use a single icon file containing both 16 and 32 icons like you did, Do you really need to add any code to get the same result? I just tested this with Delphi 7 (which I did not at the time I answered the question) and I get the correct result without any code modification. i.e. the system displays the large icon in the ALT+TAB dialog box, and the small icon in the window caption – kobik Jun 27 '17 at 06:56
  • It didn't here (Win 7). It showed the *small* icon even on the taskbar (or whatever you call that part at the bottom of the screen). – Rudy Velthuis Jun 27 '17 at 07:54
  • @RudyVelthuis, I mean if you only use then application icon (project options). would you need to add some code to make it work right? also, if you add another form (not the Main form), and assign an Icon to it (with 2 size formats - 16+32) wouldn't it work as expected? works fine for me (D7/Win7). – kobik Jun 27 '17 at 08:51
  • I don't have D7 on this computer to check, but it could be that it doesn't use ICON_BIG to set the icon, while newer versions do. – Rudy Velthuis Jun 27 '17 at 09:28
2

There are two clear questions at the very end of the post.

  1. Is it possible to let Delphi set both small and big icons without much hassle and without modifying VCL.Forms.pas? (this is the main question);

In the context of the question, this really means to ask if forcing the VCL framework itself, without modifying it, to load different icon sizes is possible. This has a very short answer: No.

If taken literally however, it is possible to use Delphi to do this. Code snippets in your question is proof of that, which doesn't seem to have much hassle at all.

  1. If not, how to add a modified source VCL unit to your application under Delphi 10.2 Tokyo, where the interface section of a unit is modified?

Very short answer here too: not possible, you cannot modify interface sections of Delphi source files.



Now, the above is really the answer to the question. That's all there's to it. However, although this information is available in the comments and an answer that already exists, the question is still open. It is even providing a bounty. I have to look hard to find what the question really wants to ask.

The question in the title is no more explanatory than the ones included in the post.

There is an update part in the second question of the post:

Setting the icons again after VCL.Forms.pas has set it is not a complete solution ..

This really doesn't help. Having read the update several times and thinking over it; this update has no relation to what have been asked as questions, or even to the background information given in the post. And I have absolutely no idea what it is talking about.


Digging more, I encounter a comment of yours to Rudy's answer:

... Delphi itself sometimes sets ICON_BIG, so in some complex scenarios you will have to catch these cases and call the WM_SETICON with ICON_BIG again. ...

I'll assume the problem is this. Despite your setting of suitable icons, in some unforeseen cases, the VCL overwrites your icons. If this is not what you want to be solved, please modify your question to ask it.

I have not seen anything like this, in any case we don't need to modify "forms.pas" to disregard the framework's icon setting. A simple WM_SETICON handler on the form is enough, just don't let the message to be processed.

So how are we gonna set the icon? There is an answer to this on WM_GETICON's documentation:

.. A window that has no icon explicitly set (with WM_SETICON) uses the icon for the registered window class, ..

So, below is the solution contained in a form class of the assumed problem:

type
  TForm1 = class(TForm)
  protected
    procedure WMSetIcon(var Message: TWMSetIcon); message WM_SETICON;
    procedure CreateParams(var Params: TCreateParams); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WindowClass.hIcon := LoadIcon(HInstance, 'ICON_1');
end;

procedure TForm1.WMSetIcon(var Message: TWMSetIcon);
begin
end;

Below is a screen shot of the form running on W7, small icon (enter image description here) in the caption, big icon (enter image description here) on the top-left of the alt+tab dialog:

enter image description here

Note that XE2 has a problem with its resource manager, I identified the icon as 'CANCEL' in the "resources and images" dialog, but the icon in the executable ended up with "ICON_1" as identifier, so I had to use that in the code.

Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
  • 1
    So where do you handle the small vs big icons? You load a single icon containing 2 sizes. I had the same results without a single line of code. – kobik Jun 30 '17 at 08:00
  • 2
    @kobik - Yeah, and my vote too, I find that really cool.. but voted after the first paragraph is incorporated. Anyway, I find this question so frustrating. Every time there's an answer, there comes some more mumble about forms.pas. And then there's the upvotes which I cannot understand. This is my attempt at resolving/understanding what's happening here. – Sertac Akyuz Jun 30 '17 at 09:59
  • 2
    I'm also not sure what's the issue since I can't reproduce. is it a bug in newer Delphi versions? I only have D7 *sigh*. if I use an icon containing both small/big icons everything works as expected... I dunno. In fact my icons containing at least 4 formats to cover every resolution/state the system uses. I never had any issues. – kobik Jun 30 '17 at 10:16
  • @kobik Loading a single icon containing both sizes is a good idea. It turns out to be that it loads ALL the sizes needed in one go. I don't know why Delphi did explicitly specify ICON_BIG. So when I saw this code in Delphi, my first reaction was to also add ICON_SMALL. But it turned out to be that my reaction was wrong. The best reaction would have been to get rid of "LoadImage(HInstance, PChar(ResName), IMAGE_ICON,..." and replace it with just LoadIcon. (Delphi thought they know better what Windows wants but it turned out Delphi was wrong - simple solution would have been better) – Maxim Masiutin Jun 30 '17 at 10:59
  • 1
    @Maxim this is precisely what I post in my answer. IMO you need to do nothing but provide the appropriate icons and the system will handle it itself. – kobik Jun 30 '17 at 11:43
  • @kobik - my application need to change icons at runtime sometimes. Isn't it what is supposed to do by Windows? Setting " Params.WindowClass.hIcon" seems to be a one-time operation when a window is created, but later there seem to be no option to change an icon rather than WM_SETICON which requires ICON_BIG or ICON_SMALL. Or there is an option to set the icon handle later? – Maxim Masiutin Jun 30 '17 at 11:51
  • 2
    @Maxim - You can use SetClassLong with GCL_HICON index. – Sertac Akyuz Jun 30 '17 at 11:52
  • 2
    @MaximMasiutin there is. In the main form construction for example. Read my answers again I addressed that situation. call set `Application.icon` or send a `WM_SETICON` message to the Application. and use the `SetClassLong`. – kobik Jun 30 '17 at 12:01
  • 2
    @MaximMasiutin, It is not a "good idea" it is a must if you want the OS to display the correct icon in the appropriate situation. even a 256 size icon in PNG format is recommended. – kobik Jun 30 '17 at 12:02
  • 2
    But again , why on earth do you need to *change* the **Application** icon at run time??? You should NOT do that! I give up, good luck. – kobik Jun 30 '17 at 12:14
  • @Kobik - we have several icons, and if we set them sequentially one after another after a fixed time period, we have animation (the bat flying) – Maxim Masiutin Jun 30 '17 at 13:47
  • 2
    What more can I say? let it fly with the wind. – kobik Jun 30 '17 at 19:27
  • 2
    LOL! `/\ ^._.^ /\ ` :) – Sertac Akyuz Jun 30 '17 at 19:31