Newsgroup: it.comp.lang.delphi
Titolo: Azioni e Property su Form

Lo scopo e' usare le property su form MdiChild , come un Flag , e quindi 
evitare
le variabili globali, per Abilitare e Disabilitare i Buttons della ToolBar.
Su ogni ChildForm , esporto la property
property Modificato:Boolean read FModificato write SetModificato;
FModificato1, per child1 , FModificato2, per child2 , etc.
imposto FModificato:=False su FormCreate
e FModificato:=True su FormClose
nell'evento onUpdate dell'azione controllo cosi':
Button1.Enabled := (ActiveMDIChild as TForm2).Modificato;
questo puo' funziona se ci sono Child aperti , ed inoltre devo verificare
di essere sul Chil che mi interessa (per evitare errori TypeCast).
procedure TForm1.Action1Update(Sender: TObject);
begin
 if ActiveMDIChild<>Nil then
 begin
  if ActiveMDIChild.Name='Form2' then
  begin
   Button1.Enabled := (ActiveMDIChild as TForm2).Modificato;
  end;
 end
 else if not Button1.enabled then Button1.Enabled:=True;
end;
ma ancora non riesco a controllare le Azioni, in modo sicuro, come invece
avviene con una variabile globale, dove si puo' inpostare Flg_FormX:Boolean
e impostare True in Create e  False in Close.
qualche suggerimento ?

 e impostare True in Create e  False in Close.
Cosa significa "non riesco a controllare..."?
Qual è il problema che riscontri?
-- 
Marco «Alka» Breveglieri
(marco [@] abls [.] it )
  ABLS Team S.n.c. - Software & Web
  42019 Scandiano (Reggio Emilia)
 
http://www.abls.it


provo s piegare il comportamento :
Form1 (padre) con 2 Button collegati ad
Action1 e Action2 con Executre ed Update
e 2 child aperti (Form2 e Form3) , se chiudo
Form3 ed assegno sull'evento OnClose
 FModificato1:=True;
 Action:=caFree;
quando vado a controllare su Action Update, Form3 non
esiste piu' , essendo stato eliminato da caFree;
TAction passa da Action1Update e trova Form2 attivo e modifica
lo stato del Button1 ,
per il Button2 non posso controllare lo stato e resta Enabled:=false
quando chiudo anche Form2, i 2 Button si portano su Enabled:=true.
Forse serve una property non legata al Form come questa
Button1.Enabled := (ActiveMDIChild as TForm2).Modificato;
magari adesso sara' piu' chiaro casa succede.
// codice per controllo dei Button in base allo stato del property
procedure TForm1.Action1Update(Sender: TObject);
begin
 if ActiveMDIChild<>Nil then
 begin
  if ActiveMDIChild.Name='Form2' then
  begin
   Button1.Enabled := (ActiveMDIChild as TForm2).Modificato;
  end;
 end
 else if not Button1.enabled then Button1.Enabled:=True;
end;
procedure TForm1.Action2Update(Sender: TObject);
begin
 if ActiveMDIChild<>Nil then
 begin
  if ActiveMDIChild.Name='Form3' then
  begin
    Button2.Enabled := (ActiveMDIChild as TForm3).Modificato1;
  end;
 end
 else if not Button2.Enabled then Button2.Enabled:=True;
end;
// questo per la creazione dimamica
procedure TForm1.Action1Execute(Sender: TObject);
var ChildForm: TForm2;
begin
 Form2Att:=True;
 ChildForm := TForm2.Create (self);
 ChildForm.Caption :='F2';
 ChildForm.Show;
end;
// dichiarazione property
  { Public declarations }
property Modificato1:Boolean
   read FModificato1 write SetModificato1;
procedure TForm3.SetModificato1(const Value: Boolean);
begin
  FModificato1 := Value;
end; 

 quando chiudo anche Form2, i 2 Button si portano su Enabled:=true.
 > [...]
 > magari adesso sara' piu' chiaro casa succede.
Al di là di quello che succede, io non riesco ancora a capire *cosa* 
stai cercando di ottenere; quale meccanismo tenti di implementare? a 
cosa servono le azioni? quale operazione eseguono sui form attivi?
Una volta precisato il tuo scopo, allora possiamo analizzare come il 
comportamento del programma si discosta da tale obiettivo e vedere poi 
come risolvere i problemi, magari suggerendo strade che sono 
completamente diverse da quella che hai adottato tu.
Ciao! :-)


 ciao Maurizio

 ogni suggerimento sara' benvenuto
Io ci provo, ma ammetto di non aver ben chiara la situazione.
Ad ogni modo, supponendo che le azioni di cui fai uso servano per aprire 
e chiudere il "form figlio", allora nell'evento OnUpdate delle azioni ti 
basta inserire la clausola
   // Action: Activate
   ActivateAction.Enabled := not ChildForm.Visible;
   // Action: Deactivate
   DeactivateAction.Enabled := ChildForm.Visible;
ammesso che tu non distrugga il form MDIChild.
Se lo distruggi, dovresti avere l'accortezza di impostare la variabile 
di riferimento al valore *nil*, in modo da poter scrivere qualcosa di 
simile al seguente:
   // Action: Activate
   ActivateAction.Enabled := (ChildForm = nil);
   // Action: Deactivate
   DeactivateAction.Enabled := (ChildForm <> nil);
A questo punto, non capisco ancora in quale frangente si inserisci il 
flag /FModificato/; se indica uno stato di modifica attivo sui dati dei 
singoli form, allora intercetta l'evento /OnCloseQuery/ dei form figli 
stessi e, al suo interno, fai in modo che vengano richieste azioni 
all'utente affinchè si possa prendere provvedimenti e, in caso di esito 
positivo del processo, consentire la chiusura dei form.


 grazie :)

Ho letto tutto e mi ricordo che sei partito dicendo ...per evitare variabili
Globali. (Pardon Public ).
Credo che il gioco non valga la candela.
Le variabili Public non si devono usare in grande numero perchè in qualche
parte del programa può esistere (o venire creata da altro programmatore) una
altra variabile con lo stesso nome che interferirebbe con la prima
Ti do questa parte di codice per vedere cosa accade nell'uso di public e la
puoi provare sulla tua macchina :
...
  public
    a : Integer ;
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormActivate(Sender: TObject);
begin
  Inc (A) ;
  ShowMessage (IntToSTr (a)) ;
end;
procedure TForm1.FormCreate(Sender: TObject);
Var A : Integer ;
begin
    Inc (A) ;
  ShowMessage (IntToSTr (a)) ;
end;
...
Ora se pero il problema è quello che dici (ed anch'io non l'ho ben capito )
mi sembra che
le variabili Public si possano usare tranquillamente. Soprattutto se 2 o 4.
Ciao
Mario - (
mari...@inwind.it
)
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 figlio (Vero o Falso) , da poter intercettare e leggere sul Form1
Credo che quella variabile non serva a nulla. Come fai ad abilitare 
un'azione solo se un form può essere creato nel caso in cui, nel 
determinare questa condizione, fai riferimento al form stesso (che non 
dovrebbe appunto esistere). Tra l'altro, il nome che hai attribuito al 
flag, /FModificato/, non è molto significativo rispetto allo scopo che 
gli hai assegnato.
Secondo me, dovresti semplicemente delegare la costruzione e la 
distruzione del form secondario figlio alle azioni che hai disposto 
sulla finestra principale.
Alla classe del form principale, aggiungi un campo privato in cui 
memorizzi il riferimento al form secondario che vai a creare.
   TMainForm = class(TForm)
   private
     FChildForm: TChildForm;
   end;
Nell'evento /OnExecute/ dell'azione di "apertura" del form secondario, 
scrivi qualcosa di simile al seguente
   FChildForm := TChildForm.Create(nil);
In questo modo, crei il form secondario e ne memorizzi il riferimento 
all'interno del campo privato del tuo form principale.
Nell'evento /OnExecute/ dell'azione di "chiusura" del form secondario, 
scrivi
   if FChildForm <> nil then
     FreeAndNil(FChildForm);
In questo modo, distruggi l'oggetto corrispondente al form e imposti a 
*nil* il riferimento.
Siccome /FChildForm/ è l'unico riferimento al form secondario, puoi 
sfruttarlo per aggiornare le tue azioni, abilitando quella di "apertura" 
solo quando tale campo è uguale a *nil*, quindi non c'è alcun form 
secondario aperto, abilitando la "chiusura" solo nel caso contrario, 
cioè quando il form è stato creato.
Non so se è la soluzione migliore e più pulita per risolvere il 
problema, ma forse è la più semplice che tu possa implementare rapidamente.
Dovrai comunque prendere qualche accorgimento quando il form secondario 
viene chiuso affinchè il form principale lo venga a sapere e pertanto 
imposti a *nil* il proprio riferimento interno, mantenendo integro il 
proprio stato di validità.
Cosa ne pensi?


 Ciao! :-) 

 Maurizio 

 cosa suggerisci di fare ?
Forse documentarsi un po' sui principi fondamentali di Delphi prima di 
avviare anche il progetto più semplice(?) :-)


 ciao :) , porta pazienza.

 documento in merito ?
Non trovi spiegazioni specifiche al tuo problema, ma sicuramente trovi 
spiegazioni esaustive sui singoli strumenti che stai utilizzando, in 
modo errato perchè probabilmente non hai compreso bene il loro scopo e 
come si impiegano nel modo corretto.
E' proprio per questo che ti ho suggerito di documentarti: se scrivi 
qualcosa e non riesci a spiegarti per quale motivo non funziona o non 
sei in grado di attribuire un senso ad un pezzo di codice, allora 
significa che hai ancora qualcosa da studiare... :-)



certo tutti abbiamo da studiare , ma io ho risolto con delle semplici
function dichiarate pubbliche,  poste su un Form Datamodule , che e'
visibile da tutti i Form Padre e Figli.
riguardo libri come Mastering Delphi , non e' prorpio il testo che ti spiega
classi , ereditarieta' etc..
dal momento che il mio scopo era evitare variabili pubbliche , interrogando
le funzioni , riesco a controllare lo stato dei pulsanti , quando trovero' 
del
materiale che mi spiega bene le classi  , lo convertiro'.
ciao :) 

 del materiale che mi spiega bene le classi  , lo convertiro'.
Sinceramente, tutt'ora trovo ancora oscuro e contorto il problema che 
stai cercando di affrontare...e ancora più misteriosa la soluzione che 
si intende adottare.
Leggendo le tue spiegazioni, non capisco se c'è confusione oppure una 
difficoltà nella descrizione del problema...o entrambe.
Credo di aver esemplificato a sufficienza gli esempi che ti ho proposto, 
ma li hai completamente stravolti perchè li hai volutamente riadattati e 
utilizzati in modo diverso da quello originale, ottenendo codice che 
ovviamente viene compilato ma che non fa più quello per cui è stato 
progettato e scritto.
Non so più che pesci pigliare, né come comportarmi... :-)



Dal momento che lo scopo era Accendere un pulsante quando un dato
Form non eiste e  Spegnere il pulsante quando lo stesso Form esiste.
Ho pensato che si potesse ricorrere a delle funzioni , per verificare se il
Form esiste o meno.
Non sara' elegante , cole la tua idea , ma e' semplice e raggiunge lo scopo.
I tuoi suggerimenti non andranno comunque persi , ma senza avere confidenza
con le indicazioni da te indicate , ho per forza di cose dovuto cambiare
strada.
Ciao :-)
quindi in un modulo TDatamodule ho inserito 2 varibili locali e 2 funzioni
per verificare lo stato di un Form.
Oltre questo mio serviva passare 2 valori , ed allo scopo ho inserito una
procedura     procedure StatoFormFiglio(var Stato:Boolean; Nome:String);
per passare i 2 valori
Esistono 3 Form , Form1 padre e Form2 / Form3 figli , tutti accedono a
datamodule4.
// Sezione Pubblica
type
  TDataModule4 = class(TDataModule)
  private
    { Private declarations }
    StatoFormChild:Boolean;
    NomeChildAttivo:String;
  public
    { Public declarations }
    procedure StatoFormFiglio(var Stato:Boolean; Nome:String);
    function StatoFormAttivo:Boolean;
    function NomeFormAttivo:String;
  end;
// Alla pressione di un Pulsante sul Form Padre
// ---------------------------------------------
procedure TForm1.Action1Execute(Sender: TObject);
var Stato:Boolean;
begin
 ChildF2:=TForm2.Create(nil);
 ChildF2.Caption :='F2';
 ChildF2.Show;
 Stato:=False;
//
//Passo il valore False per indicare che il Form sara' creato
//               "      Name che rappresenta il nome del Form
//
 DataModule4.StatoFormFiglio(Stato,Name);
 Action1.Enabled:=False;
end;
// riceve Stato=False e Nome del Form
procedure TDataModule4.StatoFormFiglio(var Stato:Boolean; Nome:String);
begin
 NomeChildAttivo:=Nome;
 if Stato then StatoFormChild:=True
 else StatoFormChild:=False;
end;
// Vado a verificare il Form
procedure TForm1.Action1Update(Sender: TObject);
begin
 VerificaChild;
end;
// nel Form Padre
procedure TForm1.VerificaChild;
var NomeChild:String;
    Stato:Boolean;
begin
  with DataModule4 do
  begin
   // Vado a leggere il nome del Form aperto e se True o False
   NomeChild:=NomeFormAttivo;
   Stato:=StatoFormAttivo;
   // in base al Nome del Form e se True o False Accendo il Pulsante
   //-----------------------------------------------------------------
   if (Stato) and (NomeFormAttivo='Form2') then Action1.Enabled:=True
   else if (Stato) and (NomeFormAttivo='Form3') then Action2.Enabled:=True;
  end;
end;
function TDataModule4.NomeFormAttivo:String;
begin
 NomeFormAttivo:=NomeChildAttivo;
end;
Alla chiusura del Form Child , chiamo la funzione
StatoFormFiglio(Stato,Name); passando Stato=True e
Nome del Form.
In questo modo non sono piou' subordinato al fatto che il Form
sia stato distrutto , in quanto tramite la procedura ho passato i
valori che servivano alla verifica.
// Chiusura del Form Figlio
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
var Stato:Boolean;
begin
 Stato:=True;
 // Passo il valore False per indicare che sara' distrutto e Nome del Form
//
 DataModule4.StatoFormFiglio(Stato,Name);
 Action:=CaFree;
end;
function TDataModule4.StatoFormAttivo:Boolean;
begin
 if StatoFormChild then StatoFormAttivo:=True
 else StatoFormAttivo:=False;
end;