L' esempio.Zip del post N. 7 del 3D http://www.lazaruspascal.it/index.php?topic=1348.msg7525#msg7525 descrive bene come creare UN SOLO pulsante.
Seguendo l'esempio ne ho creati TRE, che vengono correttamente visualizzati e risultano cliccabili.
Domanda: come posso creare / assegnare del codice per ciascuno dei pulsanti creati?
procedure TForm1.Button1Click(Sender: TObject);
Var N_pulsanti: integer;
begin
For N_pulsanti:= 1 to 3 do
Begin
Pulsante_1:=TButton.Create(nil);
Pulsante_1.Caption:='... CLICCAMI ...';
Pulsante_1.Top:=50 + 50* N_pulsanti;
Pulsante_1.Left:=100 + 100 * N_pulsanti;
Pulsante_1.Width:=100;
Pulsante_1.Height:=50;
Pulsante_1.Visible:=TRUE;
Pulsante_1.Parent:=Self;
Pulsante_1.OnClick:=@ModificaLabel ;
end;
end;
// Ovviamente(!) questa procedura è errata
procedure TForm1.ModificaLabel(Sender: TObject); // ATTENZIONE! Notare TForm1. prima della definizione
begin
ShowMessage('Questa è la label associata al pulsante N. 1!');
If Pulsante_1 then
Begin
Label1.caption:='Pulsante 1';
end;
end;
Il tuo codice dovrebbe diventare cosi:
procedure TForm1.Button1Click(Sender: TObject);
Var
N_pulsante: integer;
NewPulsante: TButton;
begin
For N_pulsante:= 1 to 3 do
Begin
NewPulsante := TButton.Create(Form1);
NewPulsante.Caption := '... CLICCAMI ...';
NewPulsante.Top := 50 + 50 * N_pulsante;
NewPulsante.Left := 100 + 100 * N_pulsante;
NewPulsante.Width := 100;
NewPulsante.Height := 50;
NewPulsante.Visible := TRUE;
NewPulsante.Parent := Self;
NewPulsante.OnClick := @ModificaLabel;
NewPulsante.Tag := N_pulsante;
end;
end;
procedure TForm1.ModificaLabel(Sender: TObject);
begin
If Assigned(Sender) and (Sender is TButton) then
Begin
case TButton(Sender).Tag of
1: TButton(Sender).Caption := 'Pulsante 1';
2: TButton(Sender).Caption := 'Pulsante 2';
3: TButton(Sender).Caption := 'Pulsante 3';
end;
end;
end;
Ricordati di assegnare un owner quando crei un componente a runtime, Form1 nel tuo caso
NewPulsante := TButton.Create(Form1);
altrimenti la memoria occupata dal programma non verrà rilasciata correttamente una volta chiuso.
.
...uhmm... non funziona: dopo la creazione dei pulsanti, li clicco (vengono evidenziati correttamente a ogni clic) ma non succede nulla.
Del resto, attivando il passo-passo, la procedura...
procedure TForm1.ModificaLabel(Sender: TObject);
...non viene mai intercettata.
Nella procedura Button_Crea_pulsantiClick assegni al tag dei pulsanti creati a runtime il valore della variabile N_Punsanti, variabile che però non inizializi ne usi nel codice della procedura.
Se guardi i messaggi del compilatore troverai un Warning, avresti dovuto scrivere:
Altre considerazioni:
La variabile Pulsante_1 è definita nella TForm1, se non hai un valido motivo per farlo, meglio spostarla nella procedura Button_Crea_pulsantiClick.
Nella procedura Button_Crea_pulsantiClick togli la prima righa
Pulsante_1:= TButton.Create(Form1);
viene creato un pultante che rimane in memoria ma non lo utilizi.
Nella procedura ModificaLabel, ripristina
If Assigned(Sender) and (Sender is TButton) then
e togli la riga
If Assigned(Sender) and (Pulsante_1 is TButton) then
La funzione Assign verifica che Sender è stato creato mentre (Sender is TButton) verifica che Sender è un pulsante visto che nel passaggio successivo si va a modificare la sua proprietà caption.
TButton(Sender).Caption := '1';
Questo perchè potenzialmente potresti assegnare a runtime la procedura ModificaLabel anche al Edit1, quindi in base alla tipologia di oggetto ricevuto la procedura ModificaLabel deve gestirlo correttamente, per esempio:
procedure TForm1.ModificaLabel(Sender: TObject);
...
If Assigned(Sender) and (Sender is TButton) then
begin
TButton(Sender).Caption := '1';
end;
If Assigned(Sender) and (Sender is TEdit) then
begin
TEdit(Sender).Text := '2';
end;
...
end;
Spero di non aver creato troppa confusione nella tua testa. ;D
Saluti
Ogni pulsante genera un evento se premuto.
Basta abbinare al pulsante nuovo un evento diverso dagli altri. Un evento non è niente altro che una procedura per il codice.
L'evento lo puoi creare semplicemente cliccando su un oggetto a DesignTime (ed è l'evento predefinito per quell'oggetto) oppure lo puoi scegliere dal "object inspector" dalle proprietà Eventi dell'oggetto stesso.
A Runtime definisci un procedura (simile a quella generata dal doppio click a design time ad esempio) e la assegni.
Esempio:
TForm1 = class(TForm)
................
................
................
//Questa dovresti gia averla
procedure FormCreate(Sender: TObject);
private
................
................
................
//LE DUE RIGHE SUCCESSIVE SONO QUELLE CHE DEVI AGGIUNGERE ALLA TUA FORM
Pulsante31: TButton;
procedure Pulsante31OnClik(Sender: TObject);
public
................
................
................
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Pulsante31OnClik(Sender: TObject);
var i: integer;
objctrl: TControl;
tag_obiettivo_di_cambio: integer;
begin
//CAMBIO il caption di chi ha il TAG con il valore 10
tag_obiettivo_di_cambio := 10;
//La riga successiva cambia la proria caption
//Pulsante31.Caption := 'Sono il pulsante 31';
for i := 0 to (self as TForm).ControlCount-1 do
begin
//usato per comodita
objctrl := (self as TForm).Controls[i];
if (objctrl is TButton) and (objctrl.Tag = tag_obiettivo_di_cambio) then
begin
(objctrl as TButton).Caption := 'TI HO CAMBIATO';
end;
end;
end;
//Da qualche parte (ad esempio nel FormCreate) inserisci:
//Assegnazione dell'evento OnClick alla procedura Pulsante31OnClick
procedure TForm1.FormCreate(Sender: TObject);
begin
Pulsante31 := TButton.Create(self);
Pulsante31.Name := 'Pulsante31';
(Self as TForm).InsertControl(Pulsante31);
Pulsante31.Caption := '... ???? ...';
Pulsante31.Top := 50;
Pulsante31.Left := 400;
Pulsante31.Width := 150;
Pulsante31.Height := 50;
Pulsante31.Visible := TRUE;
Pulsante31.Tag := 31;
Pulsante31.OnClick := @Pulsante31OnClik;
end;
Ciao