2009-06-17 4 views

Antwort

58

Es hängt davon ab, ob es sich um eine visuelle oder nicht-visuelle Komponente handelt. 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. Sie müssen jedoch 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 Erklärungen zum Code oben:

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

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

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; 

Diese 10 Tasten auf der linken Seite hinzufügen wird Grenze des Formulars. Wenn Sie die Schaltflächen später ändern möchten, können Sie sie 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 Ereignishandler zuweisen:

Sie haben eine Event-Handler-Methode erstellen und weisen es die Ereigniseigenschaft.

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

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

Aber wenn ich nicht sicher weiß, wie viele Komponenten ich erstellen möchte, z. wenn es von der Entscheidung des Benutzers abhängt. Wie kann ich Komponenten dynamisch deklarieren? –

+0

Der Unterschied, ob nil oder eine andere Komponente als Eigentümer übergeben werden soll, hat nichts damit zu tun, ob die Komponente sichtbar ist oder nicht, nur mit der Lebensdauer des Objekts. Eine unsichtbare Komponente, die nicht in derselben Methode freigegeben wurde, kann genau wie in Ihrem zweiten Snippet erstellt und automatisch vom Eigentümer freigegeben werden. – mghie

+0

s/visible/visual/g – mghie

0

Sehr einfach. Rufen Sie Erstellen auf. Beispiel:

Dies erstellt eine Komponente (TButton ist eine Komponente) zur Laufzeit und legt die Eigenschaft sichtbar.


Für den Konstruktor: pass nil, wenn Sie den Speicher selbst verwalten möchten. Übergeben Sie einen Zeiger an eine andere Komponente, wenn Sie ihn zerstören möchten, wenn die andere Komponente zerstört wird.

+1

Es ist notwendig, den Zeiger auf den Besitzer des Elements zu übergeben. TButton.Create (Besitzer); –

+3

Dieser Code wird nicht kompiliert –

+0

> Notwendigkeit für Besitzer Nicht unbedingt. TButton.Create (Null); ist ein gültiger Code. aber Sie müssen es jetzt explizit zerstören. Das Erstellen von visuellen Komponenten mit einem Null-Besitzer ist manchmal nützlich. – Despatcher

23

Um die Erstellung der Laufzeitkomponente zu vereinfachen, können Sie GExperts verwenden.

  1. Erstellen Sie eine Komponente (oder mehrere Komponenten) visuell und legen Sie ihre Eigenschaften fest.
  2. Wählen Sie eine oder mehrere Komponenten aus und führen Sie GExperts, Components to Code aus.
  3. Fügen Sie den generierten Code in Ihre Anwendung ein.
  4. Komponente (n) aus dem visuellen Formular-Designer entfernen.

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; 
+0

Toller Tipp! Genau das hätte ich vorgeschlagen. GExperts ist ein großartiges Tool für die Verwendung mit Delphi. –

+0

... oder Sie können es im visuellen Editor entwerfen und dann einen Blick in die .dfm-Datei werfen. Grundsätzlich ist genau das Gleiche im Text – Earlz

+0

Gracias. Ich ziehe es vor, alle Dinge selbst zu schreiben (ich weiß, dass das Rad vielleicht neu erfunden wird, aber ich habe mehr Kontrolle darüber), trotzdem scheint es, dass das GExpert-Tool keinen reinen Code ändert und das klingt gut. Danke nochmal für die Beratung. – QMaster

1

Aber wenn ich weiß nicht sicher, wie viele Komponenten I erstellen möchten, zum Beispiel wenn es von der Entscheidung des Benutzers abhängt. Wie kann ich Komponenten dynamisch deklarieren?

Die Antwort wurde vorgeschlagen - der einfachste Weg ist eine Liste von Objekten (Komponenten). TObjectList ist am einfachsten zu verwenden (in Einheiten). Listen sind großartig!

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

// Sie können anspruchsvollere bekommen und // TNotifyevents erklären und ihnen zuweisen, sondern lässt es einfach halten :) . . .

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; 

Eine Objektliste kann eine beliebige 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 Kommentatoren habe ich vielleicht kurz verkürzt, aber ich hoffe, Sie haben die Idee. Sie benötigen einen Mechanismus, um die Objekte zu verwalten, sobald sie erstellt sind und Listen sind hervorragend für diese Dinge.

0

Einige Komponenten haben Vorrang vor der Loaded-Methode. Diese Methode wird nicht automatisch aufgerufen, wenn Sie eine Instanz zur Laufzeit erstellen. Es wird von Delphi aufgerufen, wenn das Laden aus der Formulardatei (DFM) abgeschlossen ist.

Wenn die Methode Initialisierungscode enthält, zeigt Ihre Anwendung möglicherweise ein unerwartetes Verhalten, wenn sie zur Laufzeit erstellt wird. Überprüfen Sie in diesem Fall, ob der Komponentenschreiber diese Methode verwendet hat.

0

Wenn Sie win-Steuerelemente in Gruppenrahmen/Seitensteuerelemente/Etc ... verschachteln, ist es meiner Meinung nach vorteilhaft, wenn die Gruppe der übergeordneten Gruppen auch der Eigentümer sein soll. Ich habe eine starke Abnahme der Schließzeiten von Fenstern bemerkt, wenn ich dies tue, im Gegensatz dazu, dass der Besitzer immer die Hauptform sein muss.

1

Während einer Forschung über "Erstellen eines Delphi-Formulars mit XML-basierte Vorlage", finde ich etwas nützlich, RTTI und die Verwendung von Open Tools API (ToolsApi.pas denke ich). Sehen Sie sich die Schnittstellen in der Einheit an.

4

Ich möchte nur hinzufügen, dass beim dynamischen Hinzufügen von Steuerelementen ... es eine gute Idee, sie zu einer Objektliste (TObjectList) wie in < 1> von @Despatcher vorgeschlagen 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. Ie System.Contnrs.pas die Basis Container Unit Und Sie können viele Objektlisten haben. Ich empfehle die Verwendung einer TObjectList für jede Art von Steuerelement, das 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 

Dies ermöglicht es Ihnen, jedes Steuerelement leicht zu manipulieren/verwalten, wie Sie wissen, welche Art von Steuerelement es ist, 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 die Methoden und Eigenschaften dieser Kontrolle Vergessen Sie nicht die TObjectLists erstellen können, vielleicht in Form Ereignis erstellen ...

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

Dieses Beispiel ist So emulieren Sie den Button Tag auf 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.