从RES文件加载图标后,默认图标使用错误

5

我正在尝试创建一个自定义组件,当鼠标移动到它上面时会显示一个图标。 我是这样加载图标的:

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;

事情是这样的,一旦我将Test.pas添加到我的测试应用程序的USES中,应用程序的图标(红色delphi头盔)就会被“文件夹”图标替换。
更新:
EXE文件中的图标顺序为:“文件夹”,Default_Delphi_icon 因此,在应用程序图标之前添加了TTestPath的图标。
问题出在哪里:TTestPath以这种方式存在于EXE文件中还是它被放置在应用程序(默认)图标之前?
下面是控件代码:
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.

测试应用程序:

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.

3
Delphi使用名为MAINICON的资源名称中的主图标,即第一个图标。图标名称按字母顺序排序。如果您将其他图标命名为例如X_FOLDER,它应该可以工作。 - kobik
有趣的是,exe中的所有图标都必须以'N'(或更高字符)开头 :) 但我会尝试。谢谢。 - Gabriel
但是在EXE中,'FOLDER'应该作为可访问的图标存在吗? - Gabriel
1
这不是一个 bug。操作系统使用第一个图标。 - kobik
问题在于Delphi没有遵循底层平台的规则,并确保首先写入“'MAINICON'”。 - David Heffernan
显示剩余2条评论
1个回答

7
由于Embarcadero做出了一个相当混乱的决定,图标资源在链接时按字母顺序排序。Windows规则是,可执行文件使用的图标是第一个图标。Delphi VCL代码假定应用程序图标命名为'MAINICON'。
将这些要求结合在一起,您可以推断出所有图标的名称必须按字母顺序出现在'MAINICON'之后。
这相当令人沮丧,但很容易解决。采用适当的图标命名约定,一切都会按您的意图运行。
Embarcadero为什么不更改他们的代码,以确保命名为'MAINICON'的图标首先被发射,或者安排应用程序图标被定义为第一个图标,从而遵循平台的规则,这让我感到困惑。但我们无能为力。

我猜另一个选项是不使用Delphi的主图标,而是链接到我的自定义资源文件。 - kobik
@kobik - 这不是一个难以解决的问题。已经有解决方案了(重命名您的图标,不要使用Delphi的主图标)。问题在于对此问题的了解。一旦您掌握了这个知识...... :) :) - Gabriel
我看到在柏林修复了数量惊人的漏洞。也许这也会修复它(使用aMAINICON作为名称)。柏林终于成为值得花钱购买的版本了。 - Gabriel
1
每个新版本都有数百个漏洞修复。我想要的是更基本的东西,而且我不认为他们有能力提供它。他们已经解雇了所有的人才。 - David Heffernan
1
他们原来有不错的程序员,却把他们都解雇了!还让 Allen Bauer 走了。真是疯狂。 - David Heffernan
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接