在 Delphi 个组件之间移动控件
Moving controls between Delphi components
我正在尝试创建一个 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 returns 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 对象获取控件并将它们存储在 TPanelDiago 中的方法(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 获取 "ownership" 在 TDesignTimePanel 上绘制的组件。
我终于设法解决了我的问题。
我需要的是覆盖父对象上的 GetChildren 方法,这样我就可以将临时面板中的所有元素放入 TComponentList 中。然后我将这个列表的每个元素写入 DFM 文件。
读取 DFM 文件时,我在 TPanelDialogo.Components 属性 中获取了这些元素,但由于来自 Delphi 环境的重复控件,将这些元素存储在这里给我带来了麻烦。所以在 Loaded 方法中,我再次将所有这些组件放入 TComponentList 中。
这是代码
type
TPanelDialogo = class;
// especialización de Frame para pruebas
TDesignTimePanel = class(TPanel)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
end;
TPanelDialogo = class(TComponent)
private
FDesignPanel: TDesignTimePanel;
FGENPant: TGENPant;
FListaComponentes : TComponentList;
procedure CerrarPanel;
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;
procedure Loaded; override;
published
property ListaComponentes: TComponentList read FListaComponentes;
end;
procedure Register;
implementation
uses
ToolsApi,
SysUtils, Graphics,
Dialogs, StdCtrls,
ComponentesGEN;
{ TDesignTimePanel }
constructor TDesignTimePanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
destructor TDesignTimePanel.Destroy;
begin
inherited;
end;
procedure TDesignTimePanel.GetChildren(Proc: TGetChildProc; Root: TComponent);
begin
exit;
end;
constructor TPanelDialogo.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FListaComponentes := TComponentList.Create(True);
end;
destructor TPanelDialogo.Destroy;
begin
inherited Destroy;
end;
procedure TPanelDialogo.VolcarFrameEnLista( );
var
i: integer;
Componente: TControl;
OwnerName, ParentName: string;
begin
// recorrer el frame y rescatar sus componentes
if FDesignPanel = nil then
exit;
for i := FDesignPanel.ControlCount - 1 downto 0 do
begin
Componente := FDesignPanel.Controls[i];
if Componente.Owner <> nil then
OwnerName := Componente.Owner.Name;
if Componente.Parent <> nil then
ParentName := Componente.Parent.Name;
if Pos( self.Name + '_', Componente.Name ) = 0 then
begin
Componente.Name := self.Name + '_' + Componente.Name;
end;
if FListaComponentes.IndexOf(Componente) < 0 then
begin
FListaComponentes.Add( Componente );
end;
end;
end;
procedure TPanelDialogo.CerrarPanel;
begin
if FDesignPanel = nil then Exit;
FDesignPanel.Visible := false;
end;
function TPanelDialogo.GetChildOwner: TComponent;
begin
Result := self;
end;
procedure TPanelDialogo.GetChildren(Proc: TGetChildProc; Root: TComponent);
var
i: integer;
OwnedComponent: TComponent;
begin
if FDesignPanel <> nil then
begin
VolcarFrameEnLista();
for i := 0 to self.FListaComponentes.Count - 1 do
begin
OwnedComponent := FListaComponentes.Items[i];
Proc(OwnedComponent);
end;
end;
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';
// ...
try
for i := 0 to FListaComponentes.Count - 1 do
begin
Componente := FListaComponentes.Items[i] as TControl;
Componente.Parent := FDesignPanel;
end;
finally
FDesignPanel.Parent := Owner as TWinControl;
end;
FDesignPanel.Visible := true;
Result := FDesignPanel;
end;
procedure TPanelDialogo.Loaded;
var
i: integer;
OwnedComponent: TComponent;
begin
inherited;
for i := 0 to self.ComponentCount - 1 do
begin
OwnedComponent := self.Components[i];
self.FListaComponentes.Add(OwnedComponent);
end;
for i := self.ComponentCount - 1 downto 0 do
begin
OwnedComponent := self.Components[i];
self.RemoveComponent(OwnedComponent);
end;
self.FLoaded := true;
end;
这是设计时显示的内容:
这是表单的 DFM
object Form1: TForm1
...
object PanelDialogo1: TPanelDialogo
...
object PanelDialogo1_Label2: TLabel
Caption = 'Another label right here'
end
object PanelDialogo1_Label1: TLabel
Caption = 'A label in the top of the panel'
end
object PanelDialogo1_Edit1: TEdit
Text = 'Write something here...'
end
object PanelDialogo1_Panel1: TPanel
object PanelDialogo1_Button1: TButton
Caption = 'OK'
end
end
object PanelDialogo1_Label3: TLabel
Caption = 'Some label just here'
end
end
end
我正在尝试创建一个 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 returns 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 对象获取控件并将它们存储在 TPanelDiago 中的方法(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 获取 "ownership" 在 TDesignTimePanel 上绘制的组件。
我终于设法解决了我的问题。
我需要的是覆盖父对象上的 GetChildren 方法,这样我就可以将临时面板中的所有元素放入 TComponentList 中。然后我将这个列表的每个元素写入 DFM 文件。
读取 DFM 文件时,我在 TPanelDialogo.Components 属性 中获取了这些元素,但由于来自 Delphi 环境的重复控件,将这些元素存储在这里给我带来了麻烦。所以在 Loaded 方法中,我再次将所有这些组件放入 TComponentList 中。
这是代码
type
TPanelDialogo = class;
// especialización de Frame para pruebas
TDesignTimePanel = class(TPanel)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
end;
TPanelDialogo = class(TComponent)
private
FDesignPanel: TDesignTimePanel;
FGENPant: TGENPant;
FListaComponentes : TComponentList;
procedure CerrarPanel;
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;
procedure Loaded; override;
published
property ListaComponentes: TComponentList read FListaComponentes;
end;
procedure Register;
implementation
uses
ToolsApi,
SysUtils, Graphics,
Dialogs, StdCtrls,
ComponentesGEN;
{ TDesignTimePanel }
constructor TDesignTimePanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
destructor TDesignTimePanel.Destroy;
begin
inherited;
end;
procedure TDesignTimePanel.GetChildren(Proc: TGetChildProc; Root: TComponent);
begin
exit;
end;
constructor TPanelDialogo.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FListaComponentes := TComponentList.Create(True);
end;
destructor TPanelDialogo.Destroy;
begin
inherited Destroy;
end;
procedure TPanelDialogo.VolcarFrameEnLista( );
var
i: integer;
Componente: TControl;
OwnerName, ParentName: string;
begin
// recorrer el frame y rescatar sus componentes
if FDesignPanel = nil then
exit;
for i := FDesignPanel.ControlCount - 1 downto 0 do
begin
Componente := FDesignPanel.Controls[i];
if Componente.Owner <> nil then
OwnerName := Componente.Owner.Name;
if Componente.Parent <> nil then
ParentName := Componente.Parent.Name;
if Pos( self.Name + '_', Componente.Name ) = 0 then
begin
Componente.Name := self.Name + '_' + Componente.Name;
end;
if FListaComponentes.IndexOf(Componente) < 0 then
begin
FListaComponentes.Add( Componente );
end;
end;
end;
procedure TPanelDialogo.CerrarPanel;
begin
if FDesignPanel = nil then Exit;
FDesignPanel.Visible := false;
end;
function TPanelDialogo.GetChildOwner: TComponent;
begin
Result := self;
end;
procedure TPanelDialogo.GetChildren(Proc: TGetChildProc; Root: TComponent);
var
i: integer;
OwnedComponent: TComponent;
begin
if FDesignPanel <> nil then
begin
VolcarFrameEnLista();
for i := 0 to self.FListaComponentes.Count - 1 do
begin
OwnedComponent := FListaComponentes.Items[i];
Proc(OwnedComponent);
end;
end;
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';
// ...
try
for i := 0 to FListaComponentes.Count - 1 do
begin
Componente := FListaComponentes.Items[i] as TControl;
Componente.Parent := FDesignPanel;
end;
finally
FDesignPanel.Parent := Owner as TWinControl;
end;
FDesignPanel.Visible := true;
Result := FDesignPanel;
end;
procedure TPanelDialogo.Loaded;
var
i: integer;
OwnedComponent: TComponent;
begin
inherited;
for i := 0 to self.ComponentCount - 1 do
begin
OwnedComponent := self.Components[i];
self.FListaComponentes.Add(OwnedComponent);
end;
for i := self.ComponentCount - 1 downto 0 do
begin
OwnedComponent := self.Components[i];
self.RemoveComponent(OwnedComponent);
end;
self.FLoaded := true;
end;
这是设计时显示的内容:
这是表单的 DFM
object Form1: TForm1
...
object PanelDialogo1: TPanelDialogo
...
object PanelDialogo1_Label2: TLabel
Caption = 'Another label right here'
end
object PanelDialogo1_Label1: TLabel
Caption = 'A label in the top of the panel'
end
object PanelDialogo1_Edit1: TEdit
Text = 'Write something here...'
end
object PanelDialogo1_Panel1: TPanel
object PanelDialogo1_Button1: TButton
Caption = 'OK'
end
end
object PanelDialogo1_Label3: TLabel
Caption = 'Some label just here'
end
end
end