Nella classe Form master, devi dichiare e aggiungere una proprietà alla stessa classe:
PRIVATE $forms AS NEW Object[]
L'istruzione deve essere interna al file di classe, ma esterna da qualsiasi metodo o funzione. In teoria devi collocarla ad inizio file classe.
Quindi dichiari un tuo metodo:
PUBLIC SUB ChildClosing(child AS Object)
DIM n AS Integer
FOR n = 0 TO $forms.Max
IF ($forms[n] = child) THEN
$forms.Remove(n)
BREAK
END IF
NEXT
END
il metodo sarà poi utilizzato dalle form figlie per comunicare alla master la loro chiusura.
Quando apri una nuova Form figlia, ad esempio tramite un pulsante ad-hoc, basta che nel metodo Click() del pulsante, aggiungi queste istruzioni:
PUBLIC SUB Button_Click()
DIM newForm AS NEW Form()
$forms.Add(newForm)
newForm.Show()
END
Ovviamente io ho usato un oggetto Form generico, che può essere sostituito da una tua Form, l'importante è che l'aggiungi all'array $forms.
Nelle Form figlie, dovresti implementare alcune istruzioni, sia nel metodo _new() che nella Close() di ciascuna, in modo da definire nella figlia chi sia il padre, e notificare alla master la chiusura della sua figlia:
PRIVATE $master AS Object
PUBLIC _new(master AS Object)
$master = master
END
PUBLIC Form_Close()
$master.ChildClosing(ME)
END
Come vedi, nelle figlie è necessario utilizzare il costruttore nascosto di ogni oggetto, o classe, gestito da Gambas: _new().
Questo per poter definire un nuovo parametro "master", con cui gli viene passato il riferimento alla Form master, e che viene salvato nella proprietà $master della form. La proprietà $master sarà poi utilizzata per chiamare un metodo della form master, appunto ChildClosing(), con cui notificare della sua chiusura la form master.
A parte i giri di parole, che spero siano state chiare, tu puoi far interagire le varie Form in modo anche più complesso; ad esempio potresti impedire la chiusura delle form figlie, bloccando l'evento tramite il metodo ChildClosing(), oppure creare un link di comunicazione tra le finestre a prescidere dalla gerarchia padre/figlia, e via dicendo...
Spero sia stato tutto chiaro, in caso contrario, fammi sapere.
Bye
Sì, il repository è quello della versione che stò sviluppando.
Ad ogni modo, se leggi la doc ufficiale, per ogni oggetto descritto, derivante da Control, è obbligatorio il passaggio di un parametro, che corrisponde all'oggetto che lo contiene (Container).
Tutto ciò è valido, ad eccezione della classe Form.
Però la cosa è possibile comunque realizzarla per le classi Form, utilizzaando il metodo costruttore "_new()", nel quale puoi definire zero o più parametri a tua scelta, che verranno passati nella creazione dell'oggetto.
Ti faccio un semplice esempio...
Ammettiamo che tu abbia creato un oggetto Form, una bella finestrina vuota, su cui lavorare, inserendo poi gli oggetti che ti servono.
All'inizio della classe (praticamente la parte sorgente della Form), dichiari il metodo costruttore, inserendo alcuni parametri:
PUBLIC SUB _new( parent AS Object, OPTIONAL titolo AS String = "" )
...
END
Il metodo costruttore così creato, permette il passaggio di ulteriori nuovi parametri (la Form, come detto, non ne ha manco uno).
Nell'esempio ho definito un parametro Object, e un parametro opzionale di tipo String.
Se, ammettiamo il caso, tu voglia definire la Form come una finestra figlia di un padre noto (di solito la madre è sicura, il padre no...), quando crei l'oggetto, gli passi il "parent", che corrisponde alla Form padre, o qualsiasi altra cosa che ti serve per la sua gestione.
...Il secondo parametro è, ovviamente, un esempio non utile al nostro discorso...
Quindi, nella creazione della tua Form, ad esempio tramite un pulsante, tu avresti questo codice:
PUBLIC SUB Button_Click()
DIM formFiglia AS NEW TuaForm( ME, "Titolo" )
formFiglia.Show()
END
dove con "ME" identifichi la finestra padre.
La logica è applicabile a qualsiasi oggetto, o classe, che tu definisci nella tua applicazione, indipendentemente se grafico o meno.
Ricorda che, comunque, Gambas esegue in sequenza:
1) il costruttore della classe superiore, ovvero la classe Window con cui è struttura Form, e da cui è derivata;
2) il costruttore della tua form.
Nel caso il costruttore della classe superiore preveda parametri, questi devono essere passati come gli ultimi parametri, durante la costruzione della classe.
Un esempio può essere un oggetto Control, che ha come parametro, appunto, l'oggetto che lo contiene:
PUBLIC SUB _new(parent AS Container) 'costruttore di Control
PUBLIC SUB _new(parent AS Object, title AS String, superParent AS Container) 'costruttore della tua Form
Comunque, io direi che un'occhio al wiki, su cui ho scritto qualcosa in merito, non guasterebbe...
Bye
@md9327
dopo varie prove ho optato per il tuo primo consiglio "l'array"
ho creato una classe
' Gambas class file
STATIC PUBLIC MyForm AS Object[20]
STATIC PUBLIC FUNCTION InsForm() 'inserisce i form nell'array
DIM i AS Integer
i = 0
IF (NOT Object.IsValid(MyForm) OR IsNull(MyForm)) THEN
MyForm[0] = m1.MyNaF
ELSE
FOR EACH MyForm
IF MyForm[i] = NULL THEN
MyForm[i] = m1.MyNaF
STOP EVENT
RETURN
END IF
INC i '
NEXT
END IF
m1.MyNaF = NULL
CATCH
Message.Error(Error.Text)
END
STATIC PUBLIC FUNCTION DelForm() 'cancella i form nell'array
DIM i AS Integer
i = 0
IF (Object.IsValid(MyForm) OR NOT (IsNull(MyForm))) THEN
FOR EACH MyForm
IF MyForm[i] = m1.MyNaF THEN
MyForm[i] = NULL
END IF
INC i '
NEXT
END IF
m1.MyNaF = NULL
CATCH
Message.Error(Error.Text)
END
STATIC PUBLIC FUNCTION IcoForm() 'nasconde i form
DIM i AS Integer
i = 0
IF (NOT Object.IsValid(MyForm) OR IsNull(MyForm)) THEN
FMain.Minimized = TRUE
ELSE
FOR EACH MyForm
IF MyForm[i] <> NULL THEN
MyForm[i].hide
END IF
INC i '
NEXT
FMain.Minimized = TRUE
END IF
CATCH
Message.Error(Error.Text)
END
STATIC PUBLIC FUNCTION MaxForm() 'mostra i form
DIM i AS Integer
i = 0
IF (NOT Object.IsValid(MyForm) OR IsNull(MyForm)) THEN
FMain.Minimized = FALSE
FMain.Maximized = TRUE
ELSE
FOR EACH MyForm
IF MyForm[i] <> NULL THEN
MyForm[i].show
END IF
INC i '
NEXT
FMain.Minimized = FALSE
FMain.Maximized = TRUE
END IF
CATCH
Message.Error(Error.Text)
END
STATIC PUBLIC FUNCTION CloForm() 'prima della chiusura controlla i form
DIM ret AS Integer
DIM i AS Integer
DIM MyCoF AS Boolean
IF (NOT Object.IsValid(MyForm) OR IsNull(MyForm)) THEN
QUIT
ELSE
MyCoF = FALSE
i = 0
FOR EACH MyForm
IF MyForm[i] <> NULL THEN
IF MyForm[i].fasmod = TRUE THEN MyCoF = TRUE 'controlla i form in fase di modifica
END IF
INC i '
NEXT
IF MyCoF = FALSE THEN 'se nessun form è in fase di modifica chiude
QUIT
ELSE
i = 0
FOR EACH MyForm
IF MyForm[i] <> NULL THEN
IF MyForm[i].fasmod = TRUE THEN
IF Message.Error(m1.MyNamA & " Hai un form in fase di modifica!!", "Apri Form", "Chiudo") = 1
MyForm[i].show
STOP EVENT
RETURN
ELSE
QUIT
END IF
END IF
END IF
INC i '
NEXT
END IF
END IF
CATCH
Message.Error(Error.Text)
END
nei form
PUBLIC SUB Form_Open()
m1.MyNaF = Form1
FMdi.InsForm
END
PUBLIC SUB Form_Close()
m1.MyNaF = Form1
FMdi.delForm
ME.close
CATCH
Message.Error(Error.Text)
END
il tutto funziona, ora devo solo inserire nell'evento iconize del main.
il problema è che non riesco a trovare l'evento iconize, ho provato nel resize ma non funziona mi arriva in ritardo, e cioè quando riduco a icona non succede nulla, quando riapro il main mi nasconde le form.
io uso il main a pieno schermo e non ridimensionabile.