Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong icon used as default icon after loading icons from a RES file

I am trying to create a custom component that shows an icon when the mouse is moved over it. I am loading the icons like this:

UNIT Test;

constructor TTestPath.Create(aOwner: TComponent);
VAR myIcon: TIcon;
begin
 inherited Create(aOwner);

 ImgList:= TImageList.Create(Self);   
 myicon := TIcon.Create;
 TRY
   myicon.LoadFromResourceName(HInstance, 'FOLDER');  <------ this becomes application's icon!
   ImgList.AddIcon(myicon);
 FINALLY
   FreeAndNil(myicon);
 end;

The thing is that as soon as I add Test.pas to the USES cause of my test application, application's icon (red delphi helmet) is replaced by the 'FOLDER' icon.

Update:
The icons in EXE file are in this order: 'FOLDER', Default_Delphi_icon So, TTestPath's icon is added to the exe BEFORE application's icon.

What is wrong here: the fact that TTestPath's icon be present in this way in EXE file or the fact that it is placed before application's (default) icon?


Control's code below:

UNIT test;

INTERFACE

USES
  System.SysUtils, Winapi.Windows, System.Classes, Vcl.StdCtrls, Vcl.Controls, Vcl.Graphics, vcl.imglist, Vcl.ExtCtrls;   {$WARN GARBAGE OFF}   {Silent the: 'W1011 Text after final END' warning }

TYPE
  TValidity= (vaNone, vaValid, vaInvalid);                   { Normal / Green / Red color }
  TInputType= (itFile, itFolder);                            { What kind of path will the user type in this control: folder or file }

  TTestPath = class(TCustomGroupBox)
   private
     edtPath     : TButtonedEdit;
     btnApply    : TButton;
     btnExplore  : TButton;
     FInputType  : TInputType;
     imgList     : TImageList;
     FShowApplyBtn: Boolean;
    protected
   public
     constructor Create(aOwner: TComponent);  override;
   published

     property Align;
     property Anchors;
     property BiDiMode;
     property Caption;
     property Color;
     property Constraints;
     property Ctl3D;
     property DockSite;
     property DoubleBuffered;
     property DragCursor;
     property DragKind;
     property DragMode;
     property Enabled;
     property Font;
     property Padding;
     property ParentBackground default True;
     property ParentBiDiMode;
     property ParentColor;
     property ParentCtl3D;
     property ParentDoubleBuffered;
     property ParentFont;
     property ParentShowHint;
     property PopupMenu;
     property ShowHint;
     property TabOrder;
     property TabStop;
     property Touch;
     property Visible;
     property StyleElements;
     property OnAlignInsertBefore;
     property OnAlignPosition;
     property OnClick;
     property OnContextPopup;
     property OnDblClick;
     property OnDragDrop;
     property OnDockDrop;
     property OnDockOver;
     property OnDragOver;
     property OnEndDock;
     property OnEndDrag;
     property OnEnter;
     property OnExit;
     property OnGesture;
     property OnGetSiteInfo;
     property OnMouseActivate;
     property OnMouseDown;
     property OnMouseEnter;
     property OnMouseLeave;
     property OnMouseMove;
     property OnMouseUp;
     property OnStartDock;
     property OnStartDrag;
     property OnUnDock;
  end;


procedure Register;



IMPLEMENTATION {$R cPathEdit.res}

USES cIO;




constructor TTestPath.Create(aOwner: TComponent);
VAR myIcon: TIcon;
begin
 inherited Create(aOwner);
 Caption := 'Folder';
 Height:= 41;
 FShowApplyBtn:= TRUE;

 ImgList:= TImageList.Create(Self);   { Freed by Self }
 myicon := TIcon.Create;
 TRY
   myicon.LoadFromResourceName(HInstance, 'FOLDER');
   ImgList.AddIcon(myicon);

   myicon.LoadFromResourceName(HInstance, 'FOLDER_OPEN');
   ImgList.AddIcon(myicon);
 FINALLY
   FreeAndNil(myicon);
 end;

 edtPath:= TButtonedEdit.Create(Self);
 WITH edtPath DO
  begin
   Parent                := Self;
   Align                 := alClient;
   Margins.Left          := 1;
   Margins.Top           := 2;
   Margins.Right         := 1;
   Margins.Bottom        := 1;
   AlignWithMargins      := TRUE;
   Images                := imgList;
   TabOrder              := 0 ;
   OnChange              := nil;
   RightButton.Hint      := 'Browse for a folder';
   RightButton.ImageIndex:= 0;
   RightButton.HotImageIndex:= 1;
   RightButton.Visible   := TRUE;
   OnRightButtonClick    := nil;
   OnKeyPress            := nil;
  end;

 btnExplore:= TButton.Create(Self);
 WITH btnExplore DO
  begin
   Parent           := Self;
   Align            := alRight;
   Width            := 22;
   Margins.Left     := 1;
   Margins.Top      := 1;
   Margins.Right    := 1;
   Margins.Bottom   := 1;
   AlignWithMargins := TRUE;
   Caption          := '^';
   TabOrder         := 1;
   Hint             := 'Open this folder in Windows Explorer';
   OnClick          := nil;
 end;

 btnApply:= TButton.Create(Self);
 WITH btnApply DO
  begin
   Parent           := Self;
   Align            := alRight;
   Width            := 38;
   Margins.Left     := 1;
   Margins.Top      := 1;
   Margins.Right    := 1;
   Margins.Bottom   := 1;
   AlignWithMargins := TRUE;
   Hint             := 'Create folder if necessary';
   Caption          := 'Apply';
   TabOrder         := 2;
   OnClick          := nil;
 end;

 FInputType:= itFolder;
end;

procedure Register;
begin
  RegisterComponents('xxx', [TTestPath]);
end;

end.

Test app:

unit Unit1;
interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, Forms, 
  test;   <-------- this 

type
  TForm1 = class(TForm)
  private
  public
  end;

var
  Form1: TForm1;

IMPLEMENTATION
{$R *.dfm}

end.
like image 832
Server Overflow Avatar asked Oct 09 '16 11:10

Server Overflow


1 Answers

Due to a rather messed up decision from Embarcadero, icon resources are sorted alphabetically when linked. The Windows rule is that the icon used by the shell for an executable is the first icon. Delphi VCL code assumes that the application icon is named 'MAINICON'.

Put these requirements together and you can deduce the all your icons must have names that appear after 'MAINICON' in alphabetical order.

It's rather frustrating but easy enough to work around. Adopt a suitable naming convention for your icons and everything will behave as you intend.

Quite why Embarcadero don't change their code to make sure that the icon named 'MAINICON' is emitted first is beyond me. Or arrange that the application icon is defined to be the first one, and thus follow the rules of the platform. But there's nothing much that we can do.

like image 59
David Heffernan Avatar answered Sep 19 '22 17:09

David Heffernan