* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Maggio 05, 2024, 01:02:29 pm

Inserisci il nome utente, la password e la durata della sessione.

496 Visitatori, 1 Utente

Autore Topic: risposta ad evento TAction  (Letto 9450 volte)

Stefano

  • Newbie
  • *
  • Post: 35
  • Karma: +0/-0
risposta ad evento TAction
« il: Luglio 06, 2012, 10:04:41 pm »
da un form Menu chiamo un altro form GestioneContabileAffGiu (non modale),
va tutto bene, eccetto che vorei evitare la dichiarazione globale di frm_GestioneContabileAffGiu: Tfrm_GestioneContabileAffGiu;
ed averla solo nella procedure.

dovrei riuscire a passare l'istanza frm_GestioneContabileAffGiu a LiberaGestioneContabileAffGiu
qualcosa di simile

frm_GestioneContabileAffGiu.act_Uscita.OnExecute := @LiberaGestioneContabileAffGiu(frm_GestioneContabileAffGiu);

es: se modifico cosi' procedure Tfrm_MenuAree.LiberaGestioneContabileAffGiu(Sender: TObject; var Rifer: TObject);

frm_GestioneContabileAffGiu.act_Uscita.OnExecute := @LiberaGestioneContabileAffGiu(Sender, frm_GestioneContabileAffGiu);

in compilazione
Error: Incompatible type for arg no. 1: Got "<procedure variable type of procedure(TObject;var TCloseAction) of object;Register>", expected "<procedure variable type of procedure(TObject) of object;Register>"

spero in qualche suggerimento.

Codice: [Seleziona]
//Actcion act_Uscita seve ad intercettare la pressione di un tasto cui e' associata la TAction act_Uscita nel form Tfrm_GestioneContabileAffGiu
//
procedure Tfrm_MenuAree.GestioneContabileAffGiu;
var frm_GestioneContabileAffGiu: Tfrm_GestioneContabileAffGiu;
begin
  frm_GestioneContabileAffGiu := Tfrm_GestioneContabileAffGiu.Create(Self);
  frm_GestioneContabileAffGiu.Parent := Self;
  frm_GestioneContabileAffGiu.Top := 0;
  frm_GestioneContabileAffGiu.Left := 0;
  frm_GestioneContabileAffGiu.Width := Self.ClientWidth;
  frm_GestioneContabileAffGiu.Height := Self.ClientHeight;
  //
  //se uso la dichiarazione locale frm_GestioneContabileAffGiu: Tfrm_GestioneContabileAffGiu;
  //quando va ad eseguire LiberaGestioneContabileAffGiu  frm_GestioneContabileAffGiu e' = nil
  //
  frm_GestioneContabileAffGiu.act_Uscita.OnExecute := @LiberaGestioneContabileAffGiu;
  frm_GestioneContabileAffGiu.Show;
end;

il metodo close

Codice: [Seleziona]
procedure Tfrm_MenuAree.LiberaGestioneContabileAffGiu(Sender: TObject);
begin
  //mi serve ricevere il riferimento frm_GestioneContabileAffGiu
  //
  frm_GestioneContabileAffGiu.Close;
  //FreeAndNil(frm_GestioneContabileAffGiu);
end;           

Maverich

  • Scrittore
  • Full Member
  • *****
  • Post: 134
  • Karma: +0/-0
Re:risposta ad evento TAction
« Risposta #1 il: Luglio 07, 2012, 12:02:09 pm »
direi che non serve dichiarare un'istanza frm_GestioneContabileAffGiu,
se come penso si tratta di una scelta del tipo:

Form1 -> form base; Form2 -> formchild

dopo la Interface, nelle uses basta aggiungere la unit relativa a <frm_GestioneContabileAffGiu>

unit <MenuAree>;

{$mode objfpc}{$H+}

interface

uses
 Classes, SysUtils ....., <unit relativa a frm_GestioneContabileAffGiu> ...

type
  { Tfrm_MenuAree }

  Tfrm_MenuAree = class(TForm)

l'istanza frm_GestioneContabileAffGiu e' già dichiarata nella
unit tramite la var  frm_GestioneContabileAffGiu: Tfrm_GestioneContabileAffGiu;
tipicamente in modo simile
Codice: [Seleziona]
  Tfrm_GestioneContabileAffGiu = class(TForm)
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  frm_GestioneContabileAffGiu: Tfrm_GestioneContabile

implementation

{$R *.lfm}

end.

di conseguenza non serve dichiarare altro, naturalmente il form non deve essere presente
nella creazione automatica dei Form
verifca Opzioni Progetto->Form  e se presente sposta tramitye la freccia => sul pannello Form Disponibili;
in caso contrario avrai un doppione quello creato all'avvio e quello creato a runtime

Codice: [Seleziona]
//
procedure Tfrm_MenuAree.GestioneContabileAffGiu;
begin
  frm_GestioneContabileAffGiu := Tfrm_GestioneContabileAffGiu.Create(Self);
  frm_GestioneContabileAffGiu.Parent := Self;
  frm_GestioneContabileAffGiu.Top := 0;
  frm_GestioneContabileAffGiu.Left := 0;
  frm_GestioneContabileAffGiu.Width := Self.ClientWidth;
  frm_GestioneContabileAffGiu.Height := Self.ClientHeight;
  frm_GestioneContabileAffGiu.act_Uscita.OnExecute :=@LiberaGestioneContabileAffGiu;
  frm_GestioneContabileAffGiu.Show;
end;

quando eseguira' questa parte, l'instanza sara' ancora visibile
Codice: [Seleziona]
procedure Tfrm_MenuAree.LiberaGestioneContabileAffGiu(Sender: TObject);
begin
  frm_GestioneContabileAffGiu.Close;
  FreeAndNil(frm_GestioneContabileAffGiu);
end;

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:risposta ad evento TAction
« Risposta #2 il: Luglio 08, 2012, 11:15:39 pm »
Ciao a tutti.
Scusate se mi intrometto.
Per me basta solo gestire correttamente gli eventi della form e giocare con la struttura della LCL/VCL.
Allora, CloseAction permette di imposatare il comportamento alla richiesta di chiusura.
E' utile intercettarlo per sapere cosa succede, ma non indispensabile.

Allora Stefano, dichiari la form come child di un'altra form.
Vuoi intercettare correttamente la chiusura, per poter annullare il riferimento esterno alla form secondaria. (Ricapitolo solo per vedere se ho capito il problema).

Se sì, scatta la proposta oscena.
1) Dichiari una variabile nella form primcipale per la form secondaria come TForm.
2) Registri per l'eliminazione del componente il controllore (la form principale) con FreeNotification.
3) Sovrascrivi il metodo notification.
Occhio che questo metodo ha una marea di chiamate. Devi filtare per gli eventi di tipi "eliminazione" e mirare alla componente che ha indirizzo in memoria come la tua form.
Un if banalissimi, spiegato in termini astrusi ;)
Codice: [Seleziona]
if (Operation=...) and (Component = fFormSecondaria) then fFormSecondaria = null;
In questo modo lasci liberi i callback (eventi) della form (il sistema pemette di avere un solo callback nativo, il broad cast degli eventi è sempre fai-da-te-sperando-non-faccia-casini).
Questo è anche un modo molto comodo per fare il broad cast della creazione ed eliminazione dei componenti.
Quando accedi alla fFormSecondaria devi castare il riferimento al tipo della tua form.
Codice: [Seleziona]
  
  Tfrm_GestioneContabileAffGiu(fFormSecondaria).xxxxx
O ti fai una funzioncina che ti semplifici il codice. Ma è esteticamente una pessima idea ;)
Stedano, se hai capito è un miracolo. Penso di essermi espesso malissssssssimo.
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

Stefano

  • Newbie
  • *
  • Post: 35
  • Karma: +0/-0
Re:risposta ad evento TAction
« Risposta #3 il: Luglio 10, 2012, 08:07:46 am »
Altroche intromissione, e' proprio avere idee diverse, che aiuta.
Sicuramente per colpa mia, ma non ho capito molto, magari due righe di codice per chiarire meglio il concetto.

Citazione
tu scrivi  Quando accedi alla fFormSecondaria devi castare il riferimento al tipo della tua form.
Tfrm_GestioneContabileAffGiu(fFormSecondaria).xxxxx

ma Tfrm_GestioneContabileAffGiu e' la form secondaria, chiamata dalla form Tfrm_ManuAree (form primaria)
che io chiamo cosi'

procedure Tfrm_MenuAree.GestioneContabileAffGiu;
begin
  frm_GestioneContabileAffGiu := Tfrm_GestioneContabileAffGiu.Create(Self);
  frm_GestioneContabileAffGiu.Parent := Self;
  frm_GestioneContabileAffGiu.act_Uscita.OnExecute := @LiberaGestioneContabileAffGiu;
  frm_GestioneContabileAffGiu.Show;
end;

//vado a naso non ho il codice sottomano
dovrei fare:

Tfrm_MenuAree(frm_GestioneContabileAffGiu).Create   .... o Create(Self)

if (Operation = CloseAction) and (Component = frm_GestioneContabileAffGiu) then frm_GestioneContabileAffGiu = null

altra cosa, esiste un modo per verificare se ci sono eventi sospesi (in seguito a chiamate non gestite) , oppure se la memoria ' stata liberata.

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2873
  • Karma: +20/-4
Re:risposta ad evento TAction
« Risposta #4 il: Luglio 10, 2012, 09:57:11 am »
altra cosa, esiste un modo per verificare se ci sono eventi sospesi (in seguito a chiamate non gestite) , oppure se la memoria ' stata liberata.

nel senso: in seguito a chiamate *non ancora* gestite a causa del fatto che il main-thread è occupato?
Credo sia necessario andare a vedere cosa fa Application.ProcessMessages.
E comunque anche la chiusura di un form avviene come risposta ad un evento, probabilmente l'esaurimento della coda avviene naturalmente :)
Imagination is more important than knowledge (A.Einstein)

Stefano

  • Newbie
  • *
  • Post: 35
  • Karma: +0/-0
Re:risposta ad evento TAction
« Risposta #5 il: Luglio 10, 2012, 11:36:22 am »
si' un qualcosa che mi permetta di verificare cosa sta succedendo dietro il codice

In Delphi XE2 attivando Finestra Debug - Local Variable dove e' possibile seguire ogni operazione di assegnazione.

In Lazarus inestre Debub -> Variabili Locali, non produce alcun risultato
vedo sempre il messaggio Self <error reading variable>, qualunque sia l'istruziuone in esecuzione in un dato momento.

Cosi' se per ipotesi frm_GestioneContabileAffGiu dovesse continuare ad essere presente, anche dopo le operazioni di chiusura
sarebbe facile capire che e' stato commesso qualche errore.

Magari l'equivalente esiste anche in Lazarus, ma al momento non  l'ho ancora trovata.

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2873
  • Karma: +20/-4
Re:risposta ad evento TAction
« Risposta #6 il: Luglio 10, 2012, 01:21:02 pm »
ops, pensavo intendessi a runtime in generale invece si trattava di debug :P

in opzioni progetto -> opzioni compilatore -> linking
c'è la spunta su "genera informazioni di debug per GDB"?
Imagination is more important than knowledge (A.Einstein)

Stefano

  • Newbie
  • *
  • Post: 35
  • Karma: +0/-0
Re:risposta ad evento TAction
« Risposta #7 il: Luglio 10, 2012, 03:46:09 pm »
opzione gia' attivata;
Choose type of debug info -> Automatico (-g)

l'unica Finestra che somiglia a quella citata di Delphi e' : Stack Chiamata

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:risposta ad evento TAction
« Risposta #8 il: Luglio 10, 2012, 10:51:32 pm »
Ciao Stefano.
Ho allegato un esempio.
Come vedrai è di una banalità disarmante.
Diciamo che questo è un buon sistema per tenere il riferimento alle istanza di altri componenti.

PS:
Se hai dei thread che lavorano in back ground, è bene che crei una sorta di monitor.
Anche una cosa semplice semplice del tipo "E' vivo/è defunto" nulla di complesso.
Per quanto riguarda le chiamate in Single Thread ... in genere non sono rientranti, ma bloccanti. Quindi se nella chiusura della Form Secondria gli spari un loop infinito ... blocchi l'applicazione.
Non fatevi confondere dal nome "eventi"... :D Non sono affatto eventi, sono call back. 
Riciao
« Ultima modifica: Luglio 10, 2012, 10:53:04 pm da Stilgar »
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

Stefano

  • Newbie
  • *
  • Post: 35
  • Karma: +0/-0
Re:risposta ad evento TAction
« Risposta #9 il: Luglio 11, 2012, 10:39:12 am »
Ho scaricato l'esempio, e risulta piu' semplice del mio sistema.

Partendo dal tuo esempio, provo a creare una routine generica (CreaForm), passando il Form da creare,
pero' non accetta aForm
Error: Incompatible type for arg no. 1: Got "TForm", expected "TComponentClass"

per creare chiamo CreaForm , invece di Application.CreateForm(TForm2, FChild)
Codice: [Seleziona]
procedure TForm1.Button3Click(Sender: TObject);
begin
  CreaForm(Form2);
  //passo Form2 che e' un TForm
end; 
ciclo generale di creazione
Codice: [Seleziona]
procedure CreaForm(sForm: TForm);
begin
  //Error: Incompatible type for arg no. 1: Got "TForm", expected "TComponentClass"
  Application.CreateForm(aForm, FChild);  //errore in compilazione, nel parametro aForm

  //se invece
  Application.CreateForm(TForm2, FChild);  //va bene
end;

Stefano

  • Newbie
  • *
  • Post: 35
  • Karma: +0/-0
Re:risposta ad evento TAction
« Risposta #10 il: Luglio 11, 2012, 11:09:21 am »
ho modificato cosi':
Codice: [Seleziona]
procedure CreaForm(aForm: TComponentClass);
begin
  Application.CreateForm(aForm, FChild);
  FChild.Parent := Self;
  FChild.Top := 0;
  FChild.Left := 0;
  FChild.Show;
  FChild.FreeNotification(Self);
end;

e chiamo con  CreaForm(<form da gestire>);

es: CreaForm(TForm2); 

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:risposta ad evento TAction
« Risposta #11 il: Luglio 11, 2012, 11:22:37 am »
Puoi dichiarare un tipo :
Codice: [Seleziona]
  TFormClass = class of TForm;
e usare questo come tipo del parametro.
Altrimenti la tua routine accetterebbe anche un ... TConnection. (Ad esempio)
EDIT:
Quello che non andava bene nella prima versione è che stavi dicendo al compilatore che deve attendersi una chiamata con passaggio d'istanza.
Codice: [Seleziona]
procedure CreaForm(aForm: TComponentClass); begin   Application.CreateForm(aForm, FChild);
Qui, invece, stai dicendo che vuoi passare una classe, un tipo.
« Ultima modifica: Luglio 11, 2012, 11:24:38 am da Stilgar »
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

Stefano

  • Newbie
  • *
  • Post: 35
  • Karma: +0/-0
Re:risposta ad evento TAction
« Risposta #12 il: Luglio 11, 2012, 07:39:50 pm »
ho provato la nuova versione, e tutto bene, eccetto il controllo dei componenti interni al Form

  type TFormClass = class of TForm;  //dichiarazione

se dentro un Form ho un TPageControl con varie Pagine o un TPanel, non posso accedervi

  CreaForm(TFrm_Prova);   //creo il Form, ma non ho istanze per Tfrm_Prova
  .... come accedo a TPanel o altro ?
  <istanza>.pnlComunicazione.Visble := False;  //per <istanza> non ho riferimenti

con il metodo "tradizionale" ho un'istanza frm_Prova

Codice: [Seleziona]
  frm_Prova := Tfrm_Prova.Create(Self);
  frm_Prova.pnlComunicazioni.Visible := False;  //nasconde TPanel

  //visualizzo le pagine che interessano
   for i := 0 to frm_Prova.PageControl1.PageCount -1 do
       begin
         frm_Prova.PageControl1.Pages[i].TabVisible := True;
         if i > 3 then frm_Prova.PageControl1.Pages[i].TabVisible := False;
       end;
nuova versione
Codice: [Seleziona]
Tfrm_MenuAree = class(TForm)
  procedure CreaForm(aForm: TFormClass);
  procedure Notification(AComponent: TComponent; Operation: TOperation); override;

procedure Tfrm_MenuAree.CreaForm(aForm: TFormClass);
begin
  Application.CreateForm(aForm, FChild);
  FChild.Parent := Self;
  FChild.Top := 0;
  FChild.Left := 0;
  FChild.Show;
  FChild.FreeNotification(Self);
end;

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2382
  • Karma: +10/-0
Re:risposta ad evento TAction
« Risposta #13 il: Luglio 11, 2012, 10:13:36 pm »
O usi un'interfaccia.
In questo modo la form secondaria l'implementa, ma le cose si complicano un attimino...
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

Stefano

  • Newbie
  • *
  • Post: 35
  • Karma: +0/-0
Re:risposta ad evento TAction
« Risposta #14 il: Luglio 12, 2012, 08:18:45 am »
un'interfaccia di per se espone dei metodi;
anche implementando l'interfaccia, senza un'istanza specifica ad un Form non sara' possibile
controllare gli elementi interni (forse).

prova a dare un'occhiata al codice

Codice: [Seleziona]
unit unt_InterfaceTest;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms;

  type TFormClass = class of TForm;

  type IEventHandler = Interface
    ['{3D1B55A3-F2BD-422C-869B-BD63AF8FBDEF}']
    procedure CreaForm(aForm: TFormClass);
  end;
quindi implemento una classe che usi l'interface
Codice: [Seleziona]
  type

    { TGenerale }

      TGenerale = class(TInterfacedObject, IEventHandler)
    private
      FChild: TForm;

      procedure CreaForm(aForm: TFormClass);

    public
  end;

type
  { Tfrm_MenuAree }

  Tfrm_MenuAree = class(TForm)
....
  private
    { private declarations }
      clGenerale: TGenerale;  //istanza alla classe TGenerale

...
procedure Tfrm_MenuAree.FormCreate(Sender: TObject);
begin
  TFormClass.Create(Self);

  try
    clGenerale := TGenerale.Create;
end;         
ora resta da sostituire Self con un riferimento diretto
Codice: [Seleziona]
procedure TGenerale.CreaForm(aForm: TFormClass);
begin
  Application.CreateForm(aForm, FChild);

  //TGenerale non e' la classe che gestisce i Form, non conosce Self
  {FChild.Parent := Self; }

  FChild.Parent := frm_MenuAree.PanelAppoggio;
  FChild.Top := 0;
  FChild.Left := 0;
  FChild.Show;
  {FChild.FreeNotification(Self);} //non ancora implementato nell'Interface
end;
vado a richiamare ilo metodo
Codice: [Seleziona]
clGenerale.CreaForm(TForm2);

 

Recenti

How To

Utenti
Stats
  • Post in totale: 18797
  • Topic in totale: 2238
  • Online Today: 516
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 1
Guests: 496
Total: 497

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.