Newsgroup: it.comp.lang.delphi
Titolo: Creazione dinamica di più Form

E' una cosa che pensavo di saper fare, e invece... mi mancano i
fondamentali :((
Ho una form "tipo", a cui dopo la creazione vengono impostate delle
proprietą in base alle quali questa form fa qualcosa (downloada un file,
ma guarda te).
Supponiamo che questa form sia di tipo TDownloadForm e si chiami
DownloadForm1; a run-time se dovessi crearne una farei:
Application.CreateForm(TDownloadForm, DownloadForm1);
Bene, se io volessi creare un'altra TDownloadForm, ma chiamata
DownloadForm2, che cappero devo fare?
Grazie.
--
Jax

On Fri, 31 Jan 2003 08:17:17 GMT, "Jax" <rispo...@newsgroup.grazie> wrote:
Hai provato con 
Application.CreateForm(TDownloadForm, DownloadForm2);
Non va?
Morde.
morde [at] programmer [.] net

 Application.CreateForm(TDownloadForm, DownloadForm2);
Eh no, troppo semplice :)
Undeclared identifier.
--
Jax

 che non e' il massimo della vita.. :)


Rispondo a Morde che ha scritto:

Ma va ? ;-)
var
  DownloadForm2: TDownloadForm;
...
begin
  ...
  Application.CreateForm(TDownloadForm, DownloadForm2);
  ...
end;
esattamente come fa Delphi con DownloadForm1 (che è dichiarata nella
unit relativa al form).
-- 
Andrea Laforgia
#exclude <windows.h>

 Ma va ? ;-)
Che pirla che sono (stamattina è la mattina).
Bastava, giustamente, dichiarare una generica frmDownload: TDownloadForm
localmente nella procedura che crea la form...
Grazie a tutti.
--
Jax

 Grazie.
Prego
Andrea

 With TDownloadForm.Create( Self ) do
Why questo e non l'altro?
--
Jax

Ecco, e faresti male... :))))
Perché ?
Io cerco di evitare il "with" per quanto possibile.


 Why questo e non l'altro?
Perché con questo hai un controllo maggiore su
quello che crei e su come lo crei.
Almeno, imho.
Andrea

 Io cerco di evitare il "with" per quanto possibile.
I with andrebbero usati nel modo opportuno, ovviamente.
Imho, il miglior modo di usare il with è quello di mantenervi
dentro solo codice relativo alla entità che manipoli, nient'altro.
Del resto, come detto nell'altro post, io penso che con quel sistema
sia più semplice controllare COSA stai creando e soprattutto DOVE.
Ciao
Andrea

quello che crei e su come lo crei.
Non č vero, almeno non ci sono elementi per dirlo.


 Non è vero, almeno non ci sono elementi per dirlo.
Come no?
E se vuoi mettere una form che appartiene alla tua form
principale anziché ad Application, che fai?
Quando vuoi mettere una splash, che fai?
Se vuoi utilizzare un plug-in, che fai?
Vai ad usare la CreateForm, vai!!!!!!!!!
A parte che la CreateForm sostanzialmente usa questa
stessa tecnica per creare le forms, con in più il controllo
se la form principale è impostata, ed in caso non lo sia
imposta come principale la form che in quel momento sta
creando.
Ciao
Andrea

sia più semplice controllare COSA stai creando e soprattutto DOVE.
Potrei essere d'accordo se si volesse distruggere il form
contestualmente alla creazione, ma nel codice che riporti questo non
avviene e il tuo metodo equivale del tutto all'altro.  Il fatto è che
con CreateForm di TApplication c'è un controllo in più che
generalmente non serve.


Se vuoi utilizzare un plug-in, che fai?
Vedi sopra, non si sta parlando di questo.


 Vedi sopra, non si sta parlando di questo.
Si sta parlando( o meglio, io ho detto ) se l'utilizzo del with porta
vantaggi nel controllo della creazione delle form.
Io non ho detto "in questo caso si", io ho detto che porta vantaggi.
In generale, ovviamente.
Ah, ma forse è un livello di astrazione troppo alto per te <g>.
Andrea

Ah, ma forse è un livello di astrazione troppo alto per te <g>.
E certo, guarda caso finora gli argomenti su cui hai discusso (evita
di farmi elencare i vecchi thread) sono talmente astratti da risultare
addirittura errati.
Te lo ribadisco: fai più attenzione a quanto scrivi.


risolvere, ne capitano continuamente.
Provengo da anni di programmazione c++, il with del pascal l'ho conosciuto con delphi: mi sembrava 
comodo all'inizio (come per il mitico "?:" che a te non piace :-)), ma poi ho incontrato inconvenienti 
come quello di cui parli tu. 
Ho deciso di non usarlo proprio per diminuire le probabilita' di bug.
Perferisco quindi scrivere:
tbCurrentSeason.open;
tbCurrentSeason.Edit;
tbCurrentSeason.fieldbyname('IdStagioneAttiva').value := tbStagioni.fieldbyname('fldStgCodice').asinteger;
tbCurrentSeason.Post;
tbCurrentSeason.Close;
Che :
with tbCurrentSeason do begin
   Open;
   Edit;
   fieldbyname('IdStagioneAttiva').value := tbStagioni.fieldbyname('fldStgCodice').asinteger;
   Post;
   Close;
end;
Non nego che la seconda forma sia piu' leggibile e chiara della prima, ma alla fine ne guadagno
in tempo di debugging. (per costrutti piu' complessi)
Almeno, questa è la mia breve esperienza di delphi (sviluppo da circa un anno con il rad di borland).
Posso anche aggiungere che di tutte le ore perse debuggando i programmi che scrivo, un buon 40% e' dovuto
a sviste di questo tipo. Come dici tu "a volte le banalità fanno perdere un sacco di tempo".
Ciao,


   Open;
<...>
Anch'io.  
I programmatori sono gente strana, a volte gli piace scrivere cose del
tipo:
with TTable.Create(nil) do
begin
  TableName := 'pippo';
  Open;
  with TTable.Create(nil) do
  begin 
    TableName := 'pluto';
    Open;
    with TTable.Create(nil) do  
    begin
      TableName := 'Topolino';
      Open;
      ...
    end;
    ...
  end;
  ...
end;
...e questi sono errori _logici_ equivalenti, in tutto e per tutto,
dal mio punto di vista, a veri e propri errori fatali nel codice.
Cioč, dal mio punto di vista, un linguaggio č tanto _migliore_ quanto
impedisce al _peggior_ programmatore di fare danni.


Provengo da anni di programmazione c++, il with del pascal l'ho conosciuto con delphi:
Per chiarire perche' ho parlato di c++.
Ero abituato a scrivere codice cosi':
   GraphicBundle.setFillPattern(m_pSectorSet[iCurrentSector].m_ulFillMode)
                .setBackgroundColor(m_pSectorSet[iCurrentSector].m_cColor)
                .setFillColor(IColor::black)
                .setBackgroundMixMode(IGraphicBundle::backOr);
Da qui il paragone con il with.


 Se non si usassero sarebbe meglio.
Io non sarei così caustico. I with, IMHO, non sono così astrusi come i
Goto, soprattutto perché si usano per brevissimi spezzoni di codice.
Per esempio, with FormCreata do... non crea confusione, perché le righe
di codice interessate sono pochissime, e io lo uso spessissimo così.
Certo, se ci lasci 100 righe di codice dentro il with, è ovvio che alla
fine fai casino.
Oltretutto con la ListView ti risparmia la rottura di doverti definire
un ListItem ogni volta che ne crei uno, usando
with ListView1.Items.Add do
begin
    Caption := '...';
    SubItems.Add('...');
end;
L'ho sempre usato così e direi che non è una bruttissima cosa, neanche
stilisticamente. Tutto questo ovviamente IMHO.
--
Jax

"Jax"

Oltre ai diversi suggerimenti, aggiungo i miei <g>
a) se ti servono piu' istanze (magari contemporanee) di una classe
*elimina* la variabile dichiarata automaticamente da Delphi (se non
fisicamente, almeno non usare mai il riferimento)
b) se la form e' modale puoi semplicemente passare nil come owner e
assicurarti che sia chiamato Free quando showModal ritorna
c) se e' modeless, passare un Owner valido assicura, oltre alla
liberazione al termine della applicazione, che alla form sia assegnato
un nome univoco; inoltre, puoi accedervi grazie alla proprieta'
Components dell'Owner
d) se ne devi usare _tante_, fai una lista a parte dedicata a contenerle
(v.esempio)
e) ricorda che, comunque, puoi anche contare sulla variabile globale
Screen per avere la lista di tutte le form in giro per l'applicazione
(Screen.AddForm e' chiamato dal constructor, Screen.RemoveForm dal
destructor di TCustomForm).
Saluti
Paolo Arosio
Esempio (solo esplicativo, non da prendere as-is: il codice in
FormClose, ad esempio, non serve)
main form: 1 bottone, 1 memo; private fFormsList: TObjectList;
(contnrs.pas)
formchild: Position = poDefaultPosOnly
procedure TfrmMain.FormCreate(Sender: TObject);
begin
  fFormsList := TObjectList.Create(False);
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  fFormsList.Free;
end;
procedure TfrmMain.Button1Click(Sender: TObject);
var aFrm: TForm;
begin
  aFrm := TfrmChild.Create(Self);
  Memo1.Lines.Add('Created form: ' + aFrm.Name);
  fFormsList.Add(aFrm);
  aFrm.OnClose := ChiusuraForm;
  afrm.OnDestroy := DistruzioneForm;
  aFrm.Show;
end;
procedure TfrmMain.ChiusuraForm(Sender: TObject; var Action:
TCloseAction);
var i: integer;
begin
  Memo1.Lines.Add(Format('Form %s closed', [TForm(Sender).Name]));
  i := Random(10);
  if i > 4 then
    Action := caFree;
end;
procedure TfrmMain.DistruzioneForm(Sender: TObject);
var Index: Integer;
begin
  if Application.Terminated then
    Exit;
  Memo1.Lines.Add(Format('Form %s destroyed', [TForm(Sender).Name]));
  Index := fFormsList.IndexOf(Sender);
  if Index >= 0 then
    fFormsList.Delete(Index);
end;
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
var msg: String;
begin
  msg := 'Deleting remaining forms:'#13;
  while fFormsList.Count > 0 do begin
    msg := msg + TForm(fFormsList[0]).Name + #13;
    TForm(fFormsList[0]).Free;
  end;
  ShowMessage(msg);
end;

<...>
Non c'è un vincolo preciso su quanto debba essere lungo il codice
contenuto in un with, quindi quanto affermi non è necessariamente
vero.  Si può usare un with (o addirittura più width nidificati) in
codici chilometrici ed è terrificante, a quel punto, fare il debug.
Ovviamente sto volutamente escludendo le orrende situazioni del tipo:
var
  RecordA: record
             p, q: Integer;
           end;
  RecordB: record
             m, n: Integer;
           end;
procedure TForm1.Button1Click(Sender: TObject);
begin
  with RecordA, RecordB do
  begin
    p := m*n + q;
  end;
end;
...del tutto lecite in Delphi e, secondo me, sconfinanti
nell'aberrazione mentale.
Ripeto quello che penso: secondo me un linguaggio dovrebbe impedire
(per quanto possibile) al _peggior_ programmatore di fare cazzate, pur
togliendo qualche comodità in più al _miglior_ programmatore.  
D'altronde, se parliamo di comodità, i "goto" erano _molto_ comodi.


 D'altronde, se parliamo di comodità, i "goto" erano _molto_ comodi.
Ok, per una volta sono d'accordo con te ;)
--
Jax

                .setBackgroundColor(m_pSectorSet[iCurrentSector].m_cColor)
<...>
Che però non è standard C++, ma un'estensione del caro Zio Bill.


 Che però non è standard C++, ma un'estensione del caro Zio Bill.
Neanche, Andrea: si tratta di codice scritto per il compilatore c++
visualage di IBM per OS/2 (imho gran sistema operativo) , appoggiato
su libreria OpenClasses.
Speravo che IBM aprisse i sorgenti di OS/2, ma sembra lo destinino
all'oblio...
Ciao
Morde