Visualizzazione dei risultati da 1 a 6 su 6
  1. #1

    [DELPHI] - Problema variabili in form fsMDIChild multipli.

    Salve a tutti, vorrei alcuni consigli su un problema che potrebbe essere generale ma che, nel mio specifico, applico a Delphi.

    Ho un'applicazione composto da un MDI padre e una serie di MDI child. La struttura è la seguente:

    - MDI Padre [0] che contiene i menu;
    - MDI Child generico [1], che contiene una TDBGrid che fa riferimento a testate documenti, questo MDI Child permette la modifica e la creazione di nuovi documenti.
    - MDI Child [2] che è la form con cui creo/modifico i documenti.

    Il problema nasce nel momento in cui vado ad aprire la form [2] per andare in modifica: se ho due record da modificare: ID1 ed ID2, e li apro contemporaneamente (in pratica ho due form [2] una con i riferimenti a ID1 e l'altra con i riferimenti ad ID2) non importa su quale form io stia lavorando ma l'applicazione fa sempre riferimento all'ultima aperta. E' come se le variabili in memoria venissero sovrascritte piuttosto che duplicate.

    Le ragioni del problema le comprendo, ma come risolverlo non so.

    Ps. la form la creo con il comando Application.createform(Tform, frm)

    Qualche consiglio?
    Chi salva una vita salva il mondo intero.

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,288
    E' probabile che l'effetto riscontrato sia dovuto al fatto che nel codice delle Form che fanno parte dell'applicazione tu faccia uso direttamente delle variabili che contengono il riferimento al Form creato.

    Se utilizzi la variabile globale che Delphi inserisce in ciascuna unit che contiene un Form, ogni volta che usi l'istruzione Application.CreateForm, questa provvederà a creare una nuova finestra e a memorizzarne il riferimento nella variabile specificata; se questa variabile faceva precedentemente riferimento ad un'altra finestra, tale valore verrà perduto e tutto quanto si riferirà da quel momento in poi alla nuova istanza creata.

    Un ulteriore suggerimento che posso dare, visto anche l'approccio seguito nell'architettura dell'applicazione, è quello di usare una finestra modale, e non una MDI Child, per modificare i dati di un record, anche perché - se hai fatto uso di controlli "data aware" con relativo TDataSource - sarà difficile separare le finestre dei dettagli in modo che si sincronizzino con quella principale (che contiene la griglia di tutti gli elementi) ma modificando ciascuna un record diverso di quella griglia.

    Chiaramente, per poter essere più specifico, servirebbe una quantità maggiore di codice da analizzare.

    Come primo suggerimento drastico, ti suggerisco di rimuovere le variabili che Delphi inserisce automaticamente nelle unit appartenenti al tipo del Form definito nel file; in questo modo, ti garantirai di non fare riferimento nel codice a istanze specifiche di quelle finestre.

    Infine, se si tratta di un'applicazione nuova, onestamente abbandonerei l'approccio MDI e cercherei di orientarmi su un'architettura visuale più moderna e funzionale, visto che MDI è deprecata da tanto tempo e non utilizzata più dalla maggior parte dei programmi più recenti.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Originariamente inviato da alka
    E' probabile che l'effetto riscontrato sia dovuto al fatto che nel codice delle Form che fanno parte dell'applicazione tu faccia uso direttamente delle variabili che contengono il riferimento al Form creato.
    Hai centrato in pieno.

    Se utilizzi la variabile globale che Delphi inserisce in ciascuna unit che contiene un Form, ogni volta che usi l'istruzione Application.CreateForm, questa provvederà a creare una nuova finestra e a memorizzarne il riferimento nella variabile specificata; se questa variabile faceva precedentemente riferimento ad un'altra finestra, tale valore verrà perduto e tutto quanto si riferirà da quel momento in poi alla nuova istanza creata.

    Un ulteriore suggerimento che posso dare, visto anche l'approccio seguito nell'architettura dell'applicazione, è quello di usare una finestra modale, e non una MDI Child, per modificare i dati di un record, anche perché - se hai fatto uso di controlli "data aware" con relativo TDataSource - sarà difficile separare le finestre dei dettagli in modo che si sincronizzino con quella principale (che contiene la griglia di tutti gli elementi) ma modificando ciascuna un record diverso di quella griglia.

    Chiaramente, per poter essere più specifico, servirebbe una quantità maggiore di codice da analizzare.

    Come primo suggerimento drastico, ti suggerisco di rimuovere le variabili che Delphi inserisce automaticamente nelle unit appartenenti al tipo del Form definito nel file; in questo modo, ti garantirai di non fare riferimento nel codice a istanze specifiche di quelle finestre.
    Questo l'ho pensato anche io, ma anche se dichiaro la variabile form nella procedura di apertura della form stessa il problema si ripropone. E' come se dovessi dichiarare le variabili degli enne form (identici) con enne nomi diversi del tipo frm1, frm2...,frmn.

    Infine, se si tratta di un'applicazione nuova, onestamente abbandonerei l'approccio MDI e cercherei di orientarmi su un'architettura visuale più moderna e funzionale, visto che MDI è deprecata da tanto tempo e non utilizzata più dalla maggior parte dei programmi più recenti.
    Uso gli MDI perché mi permettono di aprire più form contemporaneamente, in questo modo se sto facendo una cosa e ho bisogno di leggere un dato da un'altra parte lo posso fare senza dover chiudere la form in questione.

    Cosa mi consiglieresti in questo senso?

    Ciao!
    Ciao a te e grazie infinite, mi sei stato di molto aiuto.
    Chi salva una vita salva il mondo intero.

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,288
    Originariamente inviato da domdin
    Hai centrato in pieno.
    Ci siamo passati tutti...

    Originariamente inviato da domdin
    Questo l'ho pensato anche io, ma anche se dichiaro la variabile form nella procedura di apertura della form stessa il problema si ripropone. E' come se dovessi dichiarare le variabili degli enne form (identici) con enne nomi diversi del tipo frm1, frm2...,frmn.
    In questo caso allora c'è un problema diverso, anche se non riesco a capire come possa riproporsi il caso dato che tu rimuovi variabili globali che utilizzi erroneamente, quindi non dovresti più potervi accedere, e lo stesso vale per le variabili locali delle procedure che creano e aprono il Form, a meno che non siano queste procedure a memorizzare da qualche parte o inizializzare nel modo errato il Form che vanno a creare.

    Tutto il codice che riguarda e opera sul Form che viene aperto va spostato nella classe del Form stesso: la procedura che effettua la creazione si dovrebbe limitare - appunto - a creare la finestra e passare solo i parametri indispensabili che consentono a essa di inizializzarsi.


    Originariamente inviato da domdin
    Uso gli MDI perché mi permettono di aprire più form contemporaneamente, in questo modo se sto facendo una cosa e ho bisogno di leggere un dato da un'altra parte lo posso fare senza dover chiudere la form in questione.
    Cosa mi consiglieresti in questo senso?
    Immaginavo che l'uso dipendesse da questa esigenza. Ad ogni modo, vi sono altre soluzioni (benché richiedano qualche conoscenza in più) che ottengono lo stesso effetto.

    Ad esempio, sfruttando i Frame, puoi creare un'interfaccia che si occupa specificatamente di modificare i dettagli di un elemento: questa interfaccia non è legata da una finestra ma può essere creata ovunque, senza duplicarne il codice s'intende, consentendo di realizzare architetture molto più flessibili.

    Dai un'occhiata ad esempio a questa pagina (è un articolo tratto da un esempio pubblicato da me e dovrebbe essere abbastanza semplice).

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    In questo caso allora c'è un problema diverso, anche se non riesco a capire come possa riproporsi il caso dato che tu rimuovi variabili globali che utilizzi erroneamente, quindi non dovresti più potervi accedere, e lo stesso vale per le variabili locali delle procedure che creano e aprono il Form, a meno che non siano queste procedure a memorizzare da qualche parte o inizializzare nel modo errato il Form che vanno a creare.

    Tutto il codice che riguarda e opera sul Form che viene aperto va spostato nella classe del Form stesso: la procedura che effettua la creazione si dovrebbe limitare - appunto - a creare la finestra e passare solo i parametri indispensabili che consentono a essa di inizializzarsi.
    Credo di aver compreso il problema, quando ho iniziato il progetto, per mia incompetenza passavo l'ID del documento da aprire come variabile globale, in pratica allo stesso livello della variabile Form che Delphi crea in automatico e che ho dovuto eliminare.

    Questo, sicuramente pregiudica il corretto funzionamento dell'applicazione. A questo punto, se il ragionamento fila, devo spostare la variabile ID allo stesso livello della classe TFORM, magari Public e dovrei riuscire a risolvere.

    Ci provo subito e ti faccio sapere.

    Ad esempio, sfruttando i Frame, puoi creare un'interfaccia che si occupa specificatamente di modificare i dettagli di un elemento: questa interfaccia non è legata da una finestra ma può essere creata ovunque, senza duplicarne il codice s'intende, consentendo di realizzare architetture molto più flessibili.

    Dai un'occhiata ad esempio a questa pagina (è un articolo tratto da un esempio pubblicato da me e dovrebbe essere abbastanza semplice).

    Ciao!
    La gestione a frame non è male ma, purtroppo, io sviluppo plugin su un'applicazione che è gestita con MDI form, quindi, per uniformità, mi trovo costretto a lavorare così.

    Per le nuove applicazioni, però seguirò il tuo consiglio.

    Ciao e grazie.
    Chi salva una vita salva il mondo intero.

  6. #6

    Risolto.

    Problema risolto anche se la soluzione non mi sembra molto elegante.

    Inizialmente, la form [2] era definita come MDIChild, e se spostavo le variabili nella sezione Public invece che globali avevo il problema del passaggio dalla variabili dalla form [1] alla form [2], questo perché prima di poter passare le variabili dovevo CREARE la form. Solo che nella creazione, la form viene anche mostrata (LO SHOW) e quindi, le eventuali variabili passate successivamente al create, non venivano lette né nel create né nello show.

    Quindi, oltre a spostare le variabili ho dovuto anche ridefinire il FORMSYLE a fsNormal, per poi passarlo in runtime in fsMdiChild. In questo modo, al create non ho ancora lo show, quindi passo le variabili e successivamente richiamo lo show. A questo punto, leggo le variabili passate da form [1] a form [2] nell'evento OnShow della form [2].

    A funzionare funziona, ma mi sembra davvero una bella confusione.

    Ps. ci tengo a ribadire la necessita di avere un MDIChild, infatti, usando una FsNorma, la Form si comporta in modo anarchico: in pratica sembra non essere figlia a nessuno, nel massimizzarla si prende tutto lo schermo, invece che l'area disposta dall'MDIform padre. Inoltre, nel ridurre ad icone le altre form, la mia bella form [2] spariva mettendosi ad di sotto di tutti. Insomma una gran confusione per una cosa che sembra, invece, SEMPLICISSIMA.

    Grazie infinite per i consigli e se hai ulteriori suggerimenti non esitare.
    Chi salva una vita salva il mondo intero.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.