Неправильный значок, используемый в качестве значка по умолчанию после загрузки значков из файла RES

#delphi #controls #vcl #delphi-xe7

#delphi #элементы управления #vcl #delphi-xe7

Вопрос:

Я пытаюсь создать пользовательский компонент, который показывает значок при наведении на него мыши. Я загружаю значки следующим образом:

 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 в причину использования моего тестового приложения, значок приложения (красный шлем delphi) заменяется значком «ПАПКА».

Обновление:
значки в EXE-файле расположены в следующем порядке: ‘ПАПКА’, Default_Delphi_icon Таким образом, значок TTestPath добавляется в exe ПЕРЕД значком приложения.

Что здесь не так: тот факт, что значок 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.
  

Комментарии:

1. Delphi использует основной значок из MAINICON имени ресурса, который является первым значком. Имена значков отсортированы по алфавиту. если вы назовете свой другой значок, например X_FOLDER , он должен работать.

2. Странно, что все значки в exe ДОЛЖНЫ начинаться с ‘N’ (или более высокого символа) 🙂 Но я попробую это. Спасибо.

3. Но должна ли «ПАПКА» присутствовать в качестве значка доступа в EXE?

4. @kobik — Это сработало. Спасибо. Я приму ваш ответ, если вы его опубликуете. Это ошибка или она задокументирована?

5. Это не ошибка. ОС использует первый значок.

Ответ №1:

Из-за довольно запутанного решения Embarcadero ресурсы значков сортируются в алфавитном порядке при связывании. Правило Windows заключается в том, что значок, используемый оболочкой для исполняемого файла, является первым значком. Код Delphi VCL предполагает, что значок приложения имеет имя 'MAINICON' .

Соедините эти требования, и вы сможете сделать вывод, что все ваши значки должны иметь имена, которые появляются после 'MAINICON' в алфавитном порядке.

Это довольно неприятно, но достаточно легко обойти. Примите подходящее соглашение об именовании для ваших значков, и все будет работать так, как вы задумали.

Совершенно непонятно, почему Embarcadero не меняет свой код, чтобы убедиться, что значок с именем 'MAINICON' выдается первым. Или сделайте так, чтобы значок приложения был определен как первый, и, таким образом, следуйте правилам платформы. Но мы ничего не можем сделать.

Комментарии:

1. Я думаю, что другой вариант — вообще не использовать основной значок Delphi. и ссылка на мой собственный файл ресурсов.

2. @kobik Я думаю, что компоновщик Delphi берет все предоставленные вами значки, а затем сортирует их по именам. Я сам не использую основной значок Delphi и помещаю все свои значки в один файл res. Но Delphi заказывает их в исполняемом IIRC.

3. @kobik — Справиться с этой проблемой несложно. Доступны решения (переименуйте свои значки, не используйте главный значок delphi). Проблема заключается в знании об этой проблеме. Как только у вас появятся знания…… 🙂 🙂

4. В каждом новом выпуске исправлены сотни ошибок. То, что я хочу от продукта, является более фундаментальным, и я не думаю, что у них есть талант для его доставки. Они уволили всех своих талантов.

5. У них были приличные программисты. Они избавились от них! Они переместили Аллена Бауэра дальше. Сумасшедший.