ciao
se ci mostri anche il codice che ti da errore ci aiuti ad aiutarti ;)
da quello che leggo usi la form modale per inserire un elemento nella listbox contenuta nella form principale...
probabilmente l'errore lo ottieni perché nella unit della form modale non hai messo in uses la form principale
mettere comunque la uses di cui sopra ti darà quasi sicuramente un altro errore (referenza circolare)
nel senso che se UnitB dipende da UnitA, allora UnitA non può dipendere da UnitB
generalmente i dialog usati per inserire i dati non dovrebbero avere in uses la unit del chiamante
quindi il suggerimento è quello di predisporre un metodo nella classe della form principale che:
- istanzia la form secondaria (quella modale) per inserire i dati
- se la form modale è confermata, si prelevano i dati dalla form modale e li si processa
- si distrugge l'istanza della form modale
prova in questo modo che riduci le dipendenze ed isoli le form per l'inserimento dati
ciao
nomorelogic
Edit:
esempio (non compilato)
implementation
uses FormPerDati;
procedure TForm1.AddElementInListBox;
var x: TFormPerDati;
begin
x:=TFormPerDati.Create(self);
try
x.Caption :='Inserisci qualcosa';
if x.ShowModal = mrOk then begin
ListBox1.Items.Add(x.Edit1.Text);
end;
finally
FreeAndNil(x);
end;
end;
prova a dichiarare in Tf_ins_cla un puntatore di tipo TListBox
unit u_ed_cla;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, Buttons,
ComCtrls ;
type
{ Tf_ins_cla }
Tf_ins_cla = class(TForm)
bok: TBitBtn;
bcal: TBitBtn;
e_cla: TLabeledEdit;
sb: TStatusBar;
procedure bcalClick(Sender: TObject);
procedure bokClick(Sender: TObject);
procedure e_claChange(Sender: TObject);
private
public
riferimento_lb: TListBox: // <---- aggiunta questa dichiarazione
end;
var
f_ins_cla: Tf_ins_cla;
implementation
{$R *.lfm}
{ Tf_ins_cla }
procedure Tf_ins_cla.e_claChange(Sender: TObject);
begin
if ( e_cla.text = '' ) then
bOk.enabled := false
else
bOk.enabled := true ;
end;
procedure Tf_ins_cla.bcalClick(Sender: TObject);
begin
//f_ins_cla.close ;
end;
procedure Tf_ins_cla.bokClick(Sender: TObject);
begin
riferimento_lb.items.Add ( e_cla.text ) ; // <- usi la listbox del form principale tramite il puntatore
f_ins_cla.close ;
end;
end.
poi, nel sorgente della form principale:
procedure Tf_cla.bInsClick(Sender: TObject);
begin
f_ins_cla.riferimento_lb := self.lb ; // <--- prima di lanciare la form secondaria, valorizzi il puntatore alla TListBox
f_ins_cla.showModal ;
f_ins_cla.free ;
end;
non ho provato il codice ma penso che sia semplice da capire come sistemare
resta comunque valido il consiglio della prima risposta ;)
Edit:
credo che se clicchi per la seconda volta sul bottone, dovresti ottenere un errore in quanto al primo passaggio distruggi l'istanza con la Free
mettere comunque la uses di cui sopra ti darà quasi sicuramente un altro errore (referenza circolare)
nel senso che se UnitB dipende da UnitA, allora UnitA non può dipendere da UnitB
Per evitare quello che dici, basta mettere le Uses nella sezione implementation. In quel caso non vengono generati riferimenti circolari, in quanto viene usata la unit esclusivamente per riferimento in compilazione. Nella sezione Interface non possono esserci riferimenti circolari.
Se uso una unità in Interface, l'altra unità può riferirsi alla prima solo nella sezione IMPLEMENTATION.
In genere, se il progetto viene ben costruito, ben poche unità del progetto andranno nella sezione Interface di altre, in genere solo perchè queste unità definiscono ad esempio tipi nuovi comuni nell'intero progetto, oppure costanti ad uso globale.
L'unità di riferimento di una "dialog" o una "form modale" non è detto che debba essere inserita nella sezione Interface, anzi in genere non ha molto senso.
E non serve neanche "distruggere" le istanze, a meno che l'occupazione di memoria non sia un problema. L'istanza della Form2 ad esempio esiste sempre, solo che viene nascosta alla chiusura. Ad ogni chiamata non ne vengono istanziate di nuove.
L'unica accortezza è che nell'evento Show della Form2 "form modale" è utile andare ad "azzerare" tutti i campi testuali o di immissione che sono eventualmente presenti al fine di non visualizzare dati magari presenti dalla precedente chiamata non coerenti.
Unit1
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
Uses Unit2;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.ShowModal;
end;
end.
Unit2
unit Unit2;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm2 }
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form2: TForm2;
implementation
{$R *.lfm}
Uses Unit1;
{ TForm2 }
procedure TForm2.Button1Click(Sender: TObject);
begin
Form1.ListBox1.AddItem('Pippo', self);
Close;
end;
end.
In genere, quello che viene fatto nella Unit2 non è proprio il massimo, è sempre bene evitare di aggiornare un componente del chiamante con chiamata diretta (anche se è consentito e lecito) quando si è in modalità modale ... possono accadere delle cose non proprio bellissime.
Questo perchè il "motore dei messaggi di Windows", chiamata anche "pompa" ... qui sono grezzo al massimo ... rimane parzialmente "inchiodata" quando si è in modalità modale (la Form2 comanda, la Form1 è in una specie di stasi) e quindi qualsiasi interazione con la Form1 potrebbe non produrre i risultati attesi.
Anche per il tramite del "puntatore" come indicato da @nomorelogic si soffre della stessa "problematica".
Sarebbe cosa buona in realtà che le due form si scambino ad esempio delle "aree" di memoria (di qualsiasi tipo: record, array, etc ..) e la Form1 con la risposta OK della Form2 esegua l'elaborazione dei dati.
Spero di essere stato esauriente.
Ciao