Frage

Wie kann ich eine Komponente zur Laufzeit und dann mit ihr arbeiten zu erstellen (Ändern von Eigenschaften, etc.)?

War es hilfreich?

Lösung

Es hängt davon ab, ob es sich um eine visuelle oder nicht-visuelle Komponente ist. Das Prinzip ist das gleiche, aber es gibt einige zusätzliche Überlegungen für jede Art von Komponente.

Für nicht-visuelle Komponenten

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

Zur visuellen Komponenten:

Im Wesentlichen visuelle Komponenten sind in der gleichen Art und Weise wie nicht-visuelle Komponenten erstellt. Aber Sie haben einige zusätzliche Eigenschaften festlegen, um sie sichtbar zu machen.

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;

Einige Erläuterungen zu dem obigen Code:

  • Durch den Eigentümer der Komponente Einstellung (die Parameter des Konstruktors) die Komponente zerstört wird, wenn die besitzende Form zerstört wird.
  • die Parent Eigenschaft Einstellung macht die Komponente sichtbar. Wenn Sie es Ihre Komponente vergessen werden nicht angezeigt. (Es ist einfach, dass man verpassen :))

Wenn Sie viele Komponenten Sie können das gleiche tun wie oben, aber in einer Schleife:

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;

Dies wird 10 Tasten am linken Rand des Formulars hinzufügen. Wenn Sie die Tasten später ändern möchten, können Sie diese in einer Liste speichern. ( TComponentList ist am besten geeignet, sondern nehmen auch einen Blick auf die Vorschläge aus den Kommentaren zu dieser Antwort)

Wie Event-Handler zuweisen:

Sie haben eine Event-Handler-Methode erstellen und an die Ereigniseigenschaft zuweisen.

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

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

Andere Tipps

, um die Laufzeitkomponente Erstellungsprozess zu vereinfachen, können Sie GExperts .

  1. Erstellen Sie eine Komponente (oder mehr Komponenten) visuell und legen Sie seine Eigenschaften.
  2. Wählen Sie eine oder mehrere Komponenten und führen GExperts, Komponenten zu-Code.
  3. Fügen Sie den erzeugten Code in Ihre Anwendung.
  4. Entfernen Komponente (n) aus der visuellen Form Designer.

Beispiel (TButton-Erstellungscode auf diese Weise generiert):

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;

Ich möchte nur hinzufügen, dass, wenn Steuerelemente dynamisch das Hinzufügen ... es als eine gute Idee, sie zu einer Objektliste (TObjectList) wie vorgeschlagen in <1> durch @Despatcher hinzuzufügen.

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;

Sie müssen die Einheit 'Contnrs' zu Ihrer uses-Liste hinzuzufügen. D.h System.Contnrs.pas die Basis Container Einheit Und Sie können viele Objektlisten haben. Ich schlage vor, mit einer TObjectList für jede Art von Kontrolle, die Sie verwenden z.

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

So können Sie leicht manipulieren / verwalten jede Kontrolle, wie Sie wissen, welche Art der Steuerung ist es z.

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;

Auf diese Weise können Sie dann auf die Methoden und Eigenschaften dieser Kontrolle verwenden Vergessen Sie nicht die TObjectLists zu schaffen, vielleicht in Form erstellen Ereignis ...

checkBoxCntrlsList := TObjectList.Create;
comboboxCntrlsList := TObjectList.Create;
  

Aber wenn ich weiß nicht sicher, wie viele Komponenten I erstellen möchten, zum Beispiel wenn es hängt von Benutzer-Entscheidung. Wie kann ich also Komponenten dynamisch deklarieren?

Die Antwort wird vorgeschlagen - der einfachste Weg, eine Liste von Objekten (Komponenten) ist. TObjectList ist die einfachste (in Einheit contnrs) zu verwenden. Listen sind groß!

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

// Sie können anspruchsvollere bekommen und // TNotifyevents erklären und sie zuweisen, aber es einfach halten :) lassen   .   .   .

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;

kann eine Objektliste enthalten ein beliebiges Objekt visuelle oder nicht, aber das gibt Ihnen einen zusätzlichen Aufwand für Aussortieren, welche Elemente sind, die -. Besser bezogene Listen haben, wenn Sie mehrere dynamische Steuerelemente auf ähnliche Platten zum Beispiel wollen

Hinweis: wie andere commenters kann ich der Kürze wegen zu stark vereinfachte, aber ich hoffe, dass Sie ge die Idee. Sie benötigen einen Mechanismus, um die Objekte zu verwalten, sobald sie erstellt werden und Listen sind für dieses Material ausgezeichnet.

Während eines Forschungs auf „die Schaffung eines delphi Form XML-basierte Vorlage“, finde ich etwas Nützliches Aufzeigen RTTI und Verwendung von offenen Tools api (ToolsApi.pas glaube ich). Werfen Sie einen Blick auf die Schnittstellen im Gerät.

Sehr erleichtern. Rufen Sie erstellen. Beispiel:

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

Dies erzeugt eine Komponente (TButton ist eine Komponente) zur Laufzeit und setzt die Eigenschaft sichtbar.


Für den Konstruktor: pass null, wenn Sie den Speicher selbst zu verwalten. Übergeben Sie einen Zeiger eine andere Komponente, wenn Sie haben wollen, es zerstört, wenn die andere Komponente zerstört.

Einige Komponenten überschreiben die ‚Loaded‘ -Methode. Diese Methode wird nicht automatisch aufgerufen werden, wenn Sie eine Instanz zur Laufzeit erstellen. Es wird von Delphi aufgerufen werden, wenn aus der Formulardatei (DFM) Laden abgeschlossen ist.

Wenn die Methode Initialisierungscode enthält, kann Ihre Anwendung unerwartetes Verhalten zeigen, wenn zur Laufzeit erstellt. In diesem Fall überprüfen, ob die Komponente Schreiber diese Methode verwendet hat.

Wenn Sie nisten Kontrollen in Gruppe Boxen gewinnen / Seite Steuerelemente / Etc ..., ich denke, dass es von Vorteil ist, die übergeordnete Gruppe Box auch der Eigentümer sein zu haben. Ich habe einen starken Rückgang der Fenster schließen mal bemerkt, wenn dies zu tun, im Gegensatz zu, das der Eigentümer immer die wichtigste Form sein.

Dies ist Beispiel dafür, wie Ohrenmarke auf Evernote zu emulieren

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.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top