我怎么可以创建一个组件在运行时,然后与它的工作(改变性等等)?

有帮助吗?

解决方案

它取决于如果这是一种视觉或非些组成部分。原理是一样的,但也有一些额外的考虑因素的各种组成部分。

对于非些组件

var
  C: TMyComponent;
begin
  C := TMyComponent.Create(nil);
  try
    C.MyProperty := MyValue;
    //...
  finally
    C.Free;
  end;
end;

对于些组成部分:

在本质上视成分是建立在同样方式作为非些组成。但你必须设置一些额外的性质,使他们可见。

var
  C: TMyVisualComponent;
begin
  C := TMyVisualComponent.Create(Self);
  C.Left := 100;
  C.Top := 100;
  C.Width := 400;
  C.Height := 300;
  C.Visible := True;
  C.Parent := Self; //Any container: form, panel, ...

  C.MyProperty := MyValue,
  //...
end;

一些解释说明上述代码:

  • 通过设置的所有者组分(参数的构造)的成分被破坏时所拥有的形式得到销毁。
  • 设置 Parent 酒店使得组件可见。如果你忘记了你的组成部分将不会显示。(很容易错过那一个:))

如果你想要的 很多部件 你可以做与上述相同,但在一个循环:

var
  B: TButton;
  i: Integer;
begin
  for i := 0 to 9 do
  begin
    B := TButton.Create(Self);
    B.Caption := Format('Button %d', [i]);
    B.Parent := Self;
    B.Height := 23;
    B.Width := 100;
    B.Left := 10;
    B.Top := 10 + i * 25;
  end;
end;

这将增加10个按钮在左边界的形式。如果你想要修改的按钮之后,可以将它们储存在一个列表。(TComponentList ist最适合的,但还要看看该提议的意见,以此回答)

如何分配的事件的处理程序:

你必须创建一个事件处理方法,并将其分配给活动的财产。

procedure TForm1.MyButtonClick(Sender: TObject);
var
  Button: TButton;
begin
  Button := Sender as TButton; 
  ShowMessage(Button.Caption + ' clicked');
end;

B := TButton.Create;
//...
B.OnClick := MyButtonClick;

其他提示

要简化运行时组件创建过程,您可以使用 GExperts

  1. 直观地创建一个组件(或更多组件)并设置其属性。
  2. 选择一个或多个组件并执行GExperts,Components to Code。
  3. 将生成的代码粘贴到您的应用程序中。
  4. 从视觉表单设计器中删除组件。
  5. 示例(以这种方式生成的TButton创建代码):

    var
      btnTest: TButton;
    
    btnTest := TButton.Create(Self);
    with btnTest do
    begin
      Name := 'btnTest';
      Parent := Self;
      Left := 272;
      Top := 120;
      Width := 161;
      Height := 41;
      Caption := 'Component creation test';
      Default := True;
      ParentFont := False;
      TabOrder := 0;
    end;
    

我想在动态添加控件时添加... 最好按照<!> lt; 1 <!> gt;中的建议将它们添加到对象列表(TObjectList)中;通过@Despatcher。

procedure Tform1.AnyButtonClick(Sender: TObject);
begin
  If Sender is TButton then
  begin
    Case Tbutton(Sender).Tag of 
    .
    .
    .
// Or You can use the index in the list or some other property 
// you have to decide what to do      
// Or similar :)
  end;
end;

procedure TForm1.BtnAddComponent(Sender: TObJect)
var
  AButton: TButton;
begin
  AButton := TButton.Create(self);
  Abutton. Parent := [Self], [Panel1] [AnOther Visual Control];
  AButton.OnClick := AnyButtonClick;
// Set Height and width and caption ect.
  .
  .
  . 
  AButton.Tag := MyList.Add(AButton);
end;

您需要将单位'Contnrs'添加到您的使用列表中。 即System.Contnrs.pas基础容器单元 你可以有很多对象列表。 我建议为您使用的每种控件使用TObjectList e.g。

Interface
 Uses Contnrs;
Type
 TMyForm = class(TForm)
private
   { Private declarations }
public
   { Public declarations }
end;
 Var
  MyForm: TMyForm;
  checkBoxCntrlsList: TObjectList; //a list for the checkBoxes I will createin a TPanel
  comboboxCntrlsList: TObjectList; //a list of comboBoxes that I will create in some Form Container

这使您可以轻松地操纵/管理每个控件,因为您将知道它是什么类型的控件。

Var comboBox: TComboBox;
I: Integer;

begin
 For I = 0 to comboboxCntrlsList.Count -1 do // or however you like to identify the control you are accessing such as using the tag property as @Despatcher said
   Begin
    comboBox := comboboxCntrlsList.Items[I] as TComboBox;
    ...... your code here
   End;
end;

这允许您使用该控件的方法和属性 不要忘记创建TObjectLists,也许在创建事件...

的形式
checkBoxCntrlsList := TObjectList.Create;
comboboxCntrlsList := TObjectList.Create;
  

但如果我不确定知道我想要创建多少个组件,例如如果这取决于用户的决定。那么如何动态声明组件呢?

已经提出了答案 - 最简单的方法是对象列表(组件)。 TObjectList是最简单的使用(在单位contnrs中)。列表很棒!

  In Form1 Public
  MyList: TObjectList;
  procedure AnyButtonClick(Sender: TObject); 

//你可以变得更复杂并声明// TNotifyevents并分配它们但是让它保持简单:)   。   。   

procedure Tform1.AnyButtonClick(Sender: TObject);
begin
  If Sender is TButton then
  begin
    Case Tbutton(Sender).Tag of 
    .
    .
    .
// Or You can use the index in the list or some other property 
// you have to decide what to do      
// Or similar :)
  end;
end;

procedure TForm1.BtnAddComponent(Sender: TObJect)
var
  AButton: TButton;
begin
  AButton := TButton.Create(self);
  Abutton. Parent := [Self], [Panel1] [AnOther Visual Control];
  AButton.OnClick := AnyButtonClick;
// Set Height and width and caption ect.
  .
  .
  . 
  AButton.Tag := MyList.Add(AButton);
end;

对象列表可以包含任何可视对象,但是这会给你一个额外的开销,即排序哪些项目 - 如果你想在类似的面板上有多个动态控件,最好有相关的列表。

注意:像其他评论者一样,为简洁起见,我可能会过度简化,但我希望你能够理解这个想法。您需要一种机制来在对象创建后管理它们,并且列表非常适合这些内容。

在研究<!>使用基于xml的模板<!>“创建delphi表单时,我找到了一些有用的指出RTTI并使用开放工具api(ToolsApi.pas我认为)。看看单元中的接口。

非常轻松。致电创建。例如:

procedure test
var
  b : TButton;
begin
  b:=TButton.Create(nil);
  b.visible:=false;
end;

这会在运行时创建一个组件(TButton是一个组件),并将该属性设置为可见。


对于构造函数:如果要自己管理内存,则传递nil。如果要在销毁其他组件时将其销毁,请将指针传递给另一个组件。

某些组件会覆盖“已加载”方法。如果在运行时创建实例,则不会自动调用此方法。当从表单文件(DFM)加载完成后,Delphi将调用它。

如果方法包含初始化代码,则应用程序在运行时创建时可能会显示意外行为。在这种情况下,请检查组件编写器是否使用了此方法。

如果您在组框/页面控件/等等中嵌套win控件,我认为让父组框也是所有者是有益的。我注意到这样做时窗口关闭时间急剧减少,而不是让主人总是主要形式。

这是如何在Evernote上模拟按钮标记的示例

unit Unit7;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, CHButton, Vcl.ExtCtrls, RzPanel, CHPanel, RzCommon,RzBmpBtn, Vcl.StdCtrls;

type
  // This is panel Button
  TButtonClose = class (TRzPanel)
   CloseButton : TRzBmpButton;
   procedure CloseButtonClick(Sender: TObject);
   procedure CloseButtonMouseEnter(Sender: TObject);
   procedure MouseDown(Sender: TObject; Button: TMouseButton;
             Shift: TShiftState; X, Y: Integer);
   procedure MouseUp(Sender: TObject; Button: TMouseButton;
             Shift: TShiftState; X, Y: Integer);
public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
end;

TForm7 = class(TForm)
   CHButton1: TCHButton;
   RzPanel1: TRzPanel;
   RzBmpButton1: TRzBmpButton;
   procedure CHButton1Click(Sender: TObject);
   procedure RzBmpButton1Click(Sender: TObject);
   procedure RzPanel1MouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure RzPanel1MouseUp(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure RzPanel1MouseEnter(Sender: TObject);
   procedure RzBmpButton1MouseEnter(Sender: TObject);
   procedure FormMouseEnter(Sender: TObject);
   procedure FormCreate(Sender: TObject);
private
  { Private declarations }
public
  { Public declarations }
end;

var
  Form7: TForm7;
  MyCloseButton : TButtonClose;

implementation

{$R *.dfm}

// constructor for on the fly component created
constructor TButtonClose.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);

   // Set Events for the component
   Self.OnMouseEnter := Self.CloseButtonMouseEnter;
   Self.OnMouseDown := Self.MouseDown;
   Self.OnMouseUp := Self.MouseUp;
   Self.Height := 25;

   // Close button on top panel Button
   // Inherited from Raize Bitmap Button
   CloseButton := TRzBmpButton.Create(self);
   // Set On Click Event for Close Button
   CloseButton.OnClick := Self.CloseButtonClick;
   // Place Close Button on Panel Button
   CloseButton.Parent := self;
   CloseButton.Left := 10;
   CloseButton.Top := 5;
   CloseButton.Visible := False;
   // Setting the image for the button
   CloseButton.Bitmaps.Up.LoadFromFile(ExtractFilePath(Application.ExeName)+'\close.bmp');
end;

procedure TButtonClose.CloseButtonClick(Sender: TObject);
begin
   // Free the parent (Panel Button)
   TControl(Sender).Parent.Free;
end;

procedure TButtonClose.CloseButtonMouseEnter(Sender: TObject);
begin
   // Show the Close button
   CloseButton.Visible := True;
end;

procedure TButtonClose.MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   // Emulate Button down state, since it is panel
   TRzPanel(Sender).BorderOuter := fsLowered;
end;

procedure TButtonClose.MouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
   // Emulate Button up state, since it is panel
   TRzPanel(Sender).BorderOuter := fsRaised;
end;

destructor TButtonClose.Destroy;
begin
   inherited Destroy;
end;

procedure TForm7.FormCreate(Sender: TObject);
begin
   // Create Panel Button on the fly
   MyCloseButton := TButtonClose.Create(self);
   MyCloseButton.Caption := 'My Button';
   MyCloseButton.Left := 10;
   MyCloseButton.Top := 10;
   // Don't forget to place component on the form
   MyCloseButton.Parent := self;
end;

procedure TForm7.FormMouseEnter(Sender: TObject);
begin
   if Assigned(RzBmpButton1) then
      RzBmpButton1.Visible := False;

   // Hide when mouse leave the button
   // Check first if myCloseButton Assigned or not before set visible property
   if Assigned(MyCloseButton.CloseButton) then
      MyCloseButton.CloseButton.Visible := False;
end;

procedure TForm7.RzBmpButton1Click(Sender: TObject);
begin
   TControl(Sender).Parent.Free;
end;

procedure TForm7.RzBmpButton1MouseEnter(Sender: TObject);
begin
   RzBmpButton1.Visible := True;
end;

procedure TForm7.RzPanel1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  TRzPanel(Sender).BorderOuter := fsLowered;
end;

procedure TForm7.RzPanel1MouseEnter(Sender: TObject);
begin
   RzBmpButton1.Visible := True;
end;

procedure TForm7.RzPanel1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   TRzPanel(Sender).BorderOuter := fsRaised;
end;

procedure TForm7.CHButton1Click(Sender: TObject);
begin
   FreeAndNil(Sender);
end;

end.
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top