2009-06-17 25 views

risposta

58

Dipende se si tratta di un componente visivo o non visivo. Il principio è lo stesso, ma ci sono alcune considerazioni aggiuntive per ogni tipo di componente.

Per i componenti non visivi

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

Per componenti visivi:

In sostanza componenti visivi vengono creati nello stesso modo come componenti non visivi. Ma devi impostare alcune proprietà aggiuntive per renderle visibili.

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; 

Alcuni spiegazioni al codice di cui sopra:

  • Impostando il proprietario del componente (il parametro del costruttore) la componente viene distrutta quando il modulo possessore viene distrutta.
  • L'impostazione della proprietà Parent rende visibile il componente. Se lo dimentichi, il tuo componente non verrà visualizzato. (E 'facile perdere che uno :))

Se volete molti componenti si può fare lo stesso come sopra, ma in un ciclo:

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; 

Questo aggiungerà 10 pulsanti a sinistra confine della forma. Se si desidera modificare i pulsanti in un secondo momento, è possibile memorizzarli in un elenco. (TComponentList ist più adatto, ma anche dare un'occhiata alle proposte dei commenti a questa risposta)

Come assegnare i gestori di eventi:

È necessario creare un metodo del gestore di eventi e assegnarlo al proprietà dell'evento.

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

Ma se non so sicuramente quanti componenti voglio creare, ad es. se dipende dalla decisione dell'utente. Quindi, come posso dichiarare i componenti dinamicamente? –

+0

La distinzione se passare nil o un altro componente come proprietario non ha nulla a che fare con il componente che è visibile o meno, solo con la durata dell'oggetto. Un componente invisibile che non è stato liberato nello stesso metodo potrebbe essere creato proprio come nel secondo frammento e essere liberato automaticamente dal proprietario. – mghie

+0

s/visible/visual/g – mghie

0

Molto facile. Chiama Crea. Esempio:

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

Questo crea un componente (TButton è un componente) in fase di esecuzione e imposta la proprietà visibile.


Per il costruttore: passare nil se si desidera gestire la memoria da soli. Passa a un puntatore un altro componente se desideri che venga distrutto quando l'altro componente viene distrutto.

+1

È necessario passare il puntatore al proprietario dell'elemento. TButton.Create (proprietario); –

+3

Questo codice non viene compilato –

+0

> necessario per il proprietario Non necessariamente. TButton.Create (zero); è un codice valido ma ora devi distruggerlo esplicitamente. È utile creare componenti visivi con un proprietario nullo. – Despatcher

23

per semplificare il processo di creazione componente runtime, è possibile utilizzare GExperts.

  1. Creare un componente (o più componenti) visivamente e impostarne le proprietà.
  2. Selezionare uno o più componenti ed eseguire GExperts, Componenti su codice.
  3. Incolla il codice generato nella tua applicazione.
  4. Rimuovi componente/i dal designer del modulo visivo.
(codice TButton-creazione generata in questo modo)

Esempio:

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

Ottimo consiglio! È esattamente quello che avrei suggerito. GExperts è un ottimo strumento da usare con Delphi. –

+0

... oppure è possibile progettarlo nell'editor visivo e quindi inserire un picco nel file .dfm. Fondamentalmente la stessa identica cosa c'è nel testo – Earlz

+0

Gracias. Preferisco scrivere da solo tutte le cose (so che è forse reinventare la ruota ma ho più controllo su di essa) comunque sembra che lo strumento GExpert non cambi in puro codice e che suoni sia buono. Grazie ancora per un consiglio. – QMaster

1

Ma se io non di certo so quanti componenti voglio creare, ad esempio, se dipende dalla decisione dell'utente. Quindi, come posso dichiarare i componenti dinamicamente?

La risposta è stata suggerita - il modo più semplice è un elenco di oggetti (componenti). TObjectList è il più semplice da usare (in unità contnrs). Le liste sono fantastiche!

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

// è possibile ottenere più sofisticati e dichiarare // TNotifyevents e assegnarli ma lascia mantenerlo semplice :) . . .

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; 

un elenco di oggetti può contenere qualsiasi oggetto visivo o no, ma che ti dà un overhead aggiunto di smistamento quali elementi sono che - meglio avere elenchi correlati se si vuole più controlli dinamici su pannelli simili, per esempio.

Nota: come altri commentatori, potrei aver semplificato per brevità ma spero che l'idea. Hai bisogno di un meccanismo per gestire gli oggetti una volta creati e gli elenchi sono eccellenti per questa roba.

0

Alcuni componenti sovrascrivono il metodo "Caricato". Questo metodo non verrà chiamato automaticamente se si crea un'istanza in fase di runtime. Verrà chiamato da Delphi quando il caricamento dal file di modulo (DFM) è completo.

Se il metodo contiene codice di inizializzazione, l'applicazione potrebbe mostrare un comportamento imprevisto quando viene creata in fase di esecuzione. In questo caso, controlla se il writer del componente ha utilizzato questo metodo.

0

Se si annidano i controlli di vittoria in Caselle di gruppo/Controlli di pagina/Ecc ..., penso che sia utile avere anche la casella del gruppo principale. Ho notato una forte diminuzione dei tempi di chiusura delle finestre quando si fa questo, invece di avere il proprietario sempre il modulo principale.

1

Durante una ricerca su "creazione di un modulo delphi utilizzando un modello basato su xml", trovo qualcosa di utile che indica RTTI e utilizza open tools api (ToolsApi.pas penso). Dai un'occhiata alle interfacce nell'unità.

4

Vorrei aggiungere che quando si aggiungono dinamicamente i controlli ... è consigliabile aggiungerli a un elenco di oggetti (TObjectList) come suggerito in < 1> da @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; 

è necessario aggiungere l'Unità 'Contnrs' alla tua lista Usi. I.e System.Contnrs.pas alla base Unità contenitori E si possono avere molti elenchi di oggetti. Suggerisco di utilizzare una TObjectList per ogni tipo di controllo che si utilizza ad es.

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 

questo consente di manipolare/gestire facilmente ciascun controllo poiché saprete quale tipo di controllo è, ad es.

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; 

Ciò consente di utilizzare per i metodi e le proprietà di tale controllo Non dimenticare di creare le TObjectLists, magari sotto forma di creare eventi ...

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

Questo è esempio come emulare il tag button su 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. 
Problemi correlati