【发布时间】:2019-10-17 04:02:36
【问题描述】:
我正在尝试创建一个可以容纳一些可视组件的 Delphi 非可视组件。
在设计时,我创建了一个自定义 TPanel,因此我可以将我的可视组件放入其中,然后我尝试从 TPanel 获取此控件并将它们存储在另一个组件中。
这是我的自定义面板
TDesignTimePanel = class(TPanel)
private
FPanel: TPanelDialogo;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
function GetChildOwner: TComponent; override;
end
GetChildren 方法什么都不做,因为我不想在 DFM 文件中以传统方式编写此面板。 GetChildOwner 方法返回我希望存储可视控件的 TPanelDialogo。
这是我想要存储来自 TDesignTimePanel 的控件的组件
TPanelDialogo = class(TComponent)
private
FDesignPanel: TDesignTimePanel;
procedure VolcarFrameEnLista();
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function CrearPanel(AOwner: TComponent): TPanel;
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
function GetChildOwner: TComponent; override;
end;
我以这种方式创建自定义面板
function TPanelDialogo.CrearPanel(AOwner: TComponent): TPanel;
var
i: integer;
Componente : TControl;
begin
if FDesignPanel = nil then
begin
FDesignPanel := TDesignTimePanel.Create(self);
FDesignPanel.AsociarPanel( self );
end;
FDesignPanel.Name := Name + '_frame';
FDesignPanel.Left := FX;
// some other config
FDesignPanel.Parent := Owner as TWinControl;
FDesignPanel.Show;
Result := FDesignPanel;
end;
所以我的 GetChildren 方法执行以下操作,其中 VolcarFrameEnLista 是我从 TDesignTimePanel 对象中获取控件并将它们存储在 TPanelDialogo 中的方法(FListaComponentes 是一个 TComponentList)
procedure TPanelDialogo.GetChildren(Proc: TGetChildProc; Root: TComponent);
var
i: integer;
OwnedComponent: TComponent;
begin
if FDesignPanel <> nil then
begin
VolcarFrameEnLista();
if Root = Self then
for i := 0 to self.FListaComponentes.Count - 1 do
begin
OwnedComponent := FListaComponentes.Items[i];
Proc(OwnedComponent);
end;
end;
end;
procedure TPanelDialogo.VolcarFrameEnLista( );
var
i: integer;
Componente: TControl;
begin
for i := FDesignPanel.ControlCount - 1 downto 0 do
begin
Componente := FDesignPanel.Controls[i];
if Pos( self.Name + '_', Componente.Name ) = 0 then
begin
Componente.Name := self.Name + '_' + Componente.Name;
end;
Componente.Parent := nil;
if FListaComponentes.IndexOf(Componente) < 0 then
begin
FListaComponentes.Add( Componente );
end;
end;
end;
我希望我的 DFM 有这样的东西:
object Form1: TForm1
object PanelDialogo1: TPanelDialogo
Left = 712
// ...
object PanelDialogo1_Label1: TLabel
Left = 88
// ..
end
object PanelDialogo1_Label2: TLabel
Left = 40
// ..
end
end
end
但是我得到了这样的东西
object Form1: TForm1
object PanelDialogo1: TPanelDialogo
Left = 712
// ...
end
object PanelDialogo1_Label1: TLabel
Left = 88
// ..
end
object PanelDialogo1_Label2: TLabel
Left = 40
// ..
end
end
我应该怎么做才能让 TPanelDialogo 获得在 TDesignTimePanel 上绘制的组件的“所有权”。
【问题讨论】:
-
InsertComponent。不过乍一看不太对劲…… -
已经试过了。 InsertComponent 失败:“名为 ... 的组件已存在”。但是,如果我尝试 RemoveComponent,那么该组件就会被破坏。
-
别无选择,您必须插入到组件数组中才能更改所有权。名称必须是唯一的,请参阅文档。
-
您要解决的实际问题是什么?为什么要将可视组件存储为非可视组件的子项? Delphi 的 dfm 存储与基于父/子的层次结构一起用于可视化组件。非可视组件始终具有作为父/所有者的表单,并且不能有子。
-
@R.Hoek - 我同意并且已经说过,设计看起来有问题,但 dfm 树并没有那么严格。菜单项 f.i. 覆盖
Get|SetParentComponent以修改您描述的行为。