#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. У них были приличные программисты. Они избавились от них! Они переместили Аллена Бауэра дальше. Сумасшедший.