我一直在编写一些自己的自定义组件,其中一些只是从其他组件派生而来,例如TCustomButton,TCustomListBox等。
让我们说我有TMyButton = class(TCustomButton)
,这是在一个名为MyButton的单元中,我已经将这个组件注册并打包并安装到IDE中。
现在我将创建一个新的空项目并将TMyButton拖放到表单中。当我编译项目时,它会自动将这些单元添加到接口部分:
.., StdCtrls, MyButton;
我当然希望添加MyButton,但希望StdCtrls不是。
这不是那么糟糕,但我的其他一些组件更糟糕,例如一个来自TCustomActionMainMenuBar
,当我将其添加到我的表单并编译时,我将添加这些额外的单位:
.., ToolWin, ActnMan, ActnCtrls, ActnMenus, MyMenu;
我想创建自己的组件的一个原因是为了防止在界面部分添加了这么多单元名称,我希望自己绘画并更改默认属性等。
当我将3或4个组件添加到表单时,会自动添加额外的6-10个单元名称,我不希望这种情况发生。
所以我的问题 - 是否可以阻止IDE自动将单元名称添加到接口部分?
事实上,我已经在我自己的组件源的实际使用界面中拥有“不需要的”单元名称,我认为这已经足够了。我的组件知道他们需要哪些单元,那么为什么表单的源文件必须知道/被允许包含这些名称呢?
我只想自动添加MyButton, MyMenu;
,而不是要添加所有其他常用单位名称。
答案 0 :(得分:9)
您的组件可能来自已注册TSelectionEditor
派生实现的其他组件(请参阅RegisterSelectionEditor()
),这些实现覆盖虚拟TSelectionEditor.RequiresUnits()
方法以将所需单元插入{{1条款。执行此操作的一个原因是,这些组件是否定义了依赖于其他单元中的类型的属性/事件。
答案 1 :(得分:8)
<强> TL;博士; 强>
不可能阻止添加这些单位,你不应再关心它了。
我的组件知道他们需要哪些单元,那么为什么表单的源文件也必须知道这些名称呢?
你是对是错。当然,如果代码仅限于创建组件,那么只需要声明该组件的单元。运行时和设计时。但是当代码开发出来,并且您希望实现需要来自祖先单元的类型的事件处理程序时,那么您的代码需要uses子句中的那些单元。运行时和设计时。
示例:从表单上的单元TDBGrid
中删除DBGrids
时,还会添加单元Grids
,因为其中包含类型发布的State
事件的TGridDrawState
参数OnDrawDataCell
的声明在祖先单元中声明。在设计器中双击该事件会导致添加以下处理程序:
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
Field: TField; State: TGridDrawState);
begin
end;
现在,由于TGridDrawState
的存在,此源文件需要知道Grids
单元。
结论:可能有太多的单位用于次要开发,但总有足够的单位用于实施所有已发布的事件。
我做了一些关于它是如何工作的研究。我已经赞成Remy's answer,因为没有它我就不会想到这样做,但他实际上并不完全正确。
考虑以下示例单位:
unit AwLabel;
interface
uses
Classes, StdCtrls;
type
TAwLabelStyle = (bsWide, bsTall);
TAwLabel = class(TLabel)
private
FStyle: TAwLabelStyle;
published
property Style: TAwLabelStyle read FStyle write FStyle default bsWide;
end;
implementation
end.
unit AwLabelEx;
interface
uses
Classes, AwLabel;
type
TAwLabelEx = class(TAwLabel);
implementation
end.
unit AwReg;
interface
uses
AwLabel, AwLabelEx;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TAwLabel, TAwLabelEx]);
end;
现在,您在表单上放置了TAwLabelEx
组件,添加了单位AwLabel
和AwLabelEx
,这会自动发生。不需要特别的参与。 AwLabel
类型需要TAwLabelStyle
单位。请注意,在这种情况下,它与事件无关。剩下的唯一参数是该类型在组件定义的已发布部分中使用。
雷米告诉我ISelectionEditor.RequiresUnits
怎么样?
考虑我们将TAwLabelStyle
移到另一个单位:
unit AwTypes;
interface
type
TAwLabelStyle = (bsWide, bsTall);
implementation
end.
现在,当您在表单上放置TAwLabel
或TAwLabelEx
组件时,AwTypes
单元未添加 。引用上一个链接:
注意:事件可能会使用其参数之一的类型既不在类单元中也不在其任何祖先单元中。在这种情况下,应该注册实现RequiresUnits的选择编辑器,并将其用于声明事件所需类型的每个单元。
所以,让我们注册一个选择编辑器:
unit AwReg;
interface
uses
Classes, AwTypes, AwLabel, AwLabelEx, DesignIntf, DesignEditors;
type
TAwLabelSelectionEditor = class(TSelectionEditor)
public
procedure RequiresUnits(Proc: TGetStrProc); override;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TAwLabel, TAwLabelEx]);
RegisterSelectionEditor(TAwLabel, TAwLabelSelectionEditor);
end;
{ TAwLabelSelectionEditor }
procedure TAwLabelSelectionEditor.RequiresUnits(Proc: TGetStrProc);
begin
Proc('AwTypes');
end;
end.
现在,在表单上删除TAwLabel
或TAwLabelEx
组件会导致将AwTypes
单元添加到uses子句中;
答案 2 :(得分:4)
TCustomActionMainMenuBar的继承树如下所示:
System.Classes.TObject
System.Classes.TPersistent
System.Classes.TComponent
Vcl.Controls.TControl
Vcl.Controls.TWinControl
Vcl.ToolWin.TToolWindow
Vcl.ActnMan.TCustomActionBar
Vcl.ActnCtrls.TCustomActionDockBar
Vcl.ActnMenus.TCustomActionMenuBar
Vcl.ActnMenus.TCustomActionMainMenuBar
Vcl.ActnMenus.TActionMainMenuBar
当您在表单上包含组件时,此树中显示的所有单元都将被绘制到uses子句中。每次保存时都会重新插入。如其他人所说,组件还可以使用Open Tools API包含其他不包含祖先的单元。
答案 3 :(得分:2)
这种情况正在发生,因为组件的祖先正在使用Open Tools API
将一些单元添加到uses子句中,其代码如下:
uses
ToolsAPI;
var
currentProject: IOTAProject;
begin
currentProject := GetActiveProject();
currentProject.AddFile('StdCtrls.pas', True);
您可能还会发现this question有趣。