* * * *

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.
Aprile 19, 2024, 02:28:59 am

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

399 Visitatori, 0 Utenti

Autore Topic: Impostare chiamata ad un evento  (Letto 1119 volte)

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Impostare chiamata ad un evento
« il: Dicembre 16, 2021, 08:48:52 am »
Ciao a tutti,
avendo studiato a scuola Turbo Pascal, ed avendo "imparato" ad usare fpc/Lazarus da autodidatta, ci sono alcune cose che ho imparato meccanicamente, senza ben capire i meccanismi che ci sono dietro.

Ora, sto avendo un problema, che non riesco a risolvere, a causa di una di queste cose che non capisco.

Provo a spiegare il problema ...

Ho un oggetto dichiarato così:
Codice: [Seleziona]
PopupNotifier1: TPopupNotifier;

Dovendo far eseguire delle operazioni quando un utente chiude la finestrella del popup, ho scritto questo codice:
Codice: [Seleziona]
PopupNotifier1.OnClose:=@ChiudiPopup;

La procedura "ChiudiPopup", è stata dichiarata così:
Codice: [Seleziona]
procedure TForm1.ChiudiPopup(Sender: TObject; var CloseAction: TCloseAction);

Quello che non capisco è questo: quando assegno la "OnClose", scrivo solo il nome della procedura, senza dichiarare i parametri da passargli ... da dove li ricava ?????

Provo a rifare la domanda in un'altra maniera: visto che "CloseAction" è dichiarata come "var", se in un certo punto del programma dovessi testare il valore di quella variabile, come faccio ?

Grazie, Mario
« Ultima modifica: Dicembre 16, 2021, 08:57:45 am da bonmario »

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Impostare chiamata ad un evento
« Risposta #1 il: Dicembre 16, 2021, 09:13:16 am »
Quello che viene effettuata è una assegnazione di "puntatore", ossia assegni alla funzione OnClose (che è di fatto un puntatore e per default è nil) un nuovo puntatore a funzionne @ChiudiPopup.

In linea prettamente teorica, l'assegnazione potrebbe violare tutte le regole e il puntatore ad esempio non essere un puntatore a funzione ma ad una variabile o altro (e in questo caso a RUNTIME avresti un bel AV).

Però il compilatore PASCAL (tutti i compilatori PASCAL) DOVREBBE ESEGUIRE una verifica con la firma dei metodi, ossia con i parametri che le funziomi o le procedure dichiarano. Attenzione che non tutti i compilatori eseguono la verifica con la definizione del risultatoo (ad esempio integer o boolen) in caso di funzioni.

La definizione di OnClose la trovi nell'unità dove è definito TPopUpMenu:

Codice: [Seleziona]
  TPopupMenu = class(TMenu)
  private
    FAlignment: TPopupAlignment;
     ....................
  published
     ...............
    property OnClose: TNotifyEvent read FOnClose write FOnClose;
  end;

OnCLose è un TNotifyEvent, quindi la tua assegnazione è ERRATA .....

Codice: [Seleziona]
  TNotifyEvent = procedure(Sender: TObject) of object;

Ha un parametro in più, CloseAction non ci stà ....
Quindi se ti viene compilato il codice, desumo che il compilatore freePascal non esegue il controllo ma fà solo l'assegnazione della procedura .....

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Impostare chiamata ad un evento
« Risposta #2 il: Dicembre 16, 2021, 09:29:44 am »
Provo a rifare la domanda in un'altra maniera: visto che "CloseAction" è dichiarata come "var", se in un certo punto del programma dovessi testare il valore di quella variabile, come faccio ?

Intanto qui la definizione è errata, comunque in generale quella sarebbe una variabile di tipo TCloseAction.

Quindi può assumere uno dei valori seguenti.
Codice: [Seleziona]
TCloseAction = (caNone, caHide, caFree, caMinimize);

Per default avrà un valore (presumo caNone)  e la puoi testare con un IF ad esempio oppure la puoi assegnare ad uno dei valori consentiti.

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Impostare chiamata ad un evento
« Risposta #3 il: Dicembre 16, 2021, 10:15:18 am »
Scusami, ma credo che stiamo parlando di cose diverse: tu stai parlando di "TPopupMenu", io di "TPopupNotifier".

Probabilmente è questo il motivo per cui mi scrivi che la dichiarazione che ho fatto è errata.

Detto questo, questa è parte del codice che non mi compila:
Codice: [Seleziona]
      PopupNotifier1:=TPopupNotifier.Create(nil);
      try
        PopupNotifier1.Icon.Assign(Form1.Icon);
        PopupNotifier1.Title:=Titolo;
        PopupNotifier1.Text:=MsgDaEme;
        PopupNotifier1.TextFont.Color:=clBlack;
        PopupNotifier1.OnClose:=@ChiudiPopup;
     
        qui c'è un ciclo while in cui ogni secondo vorrei capire se l'utente ha chiuso o meno la finestrella di notifica, al cui interno
        ho l'istruzione qui sotto:
        if (CloseAction <> caFree) then begin

Il compilatore mi dice che quella variabile non esiste ...

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Impostare chiamata ad un evento
« Risposta #4 il: Dicembre 16, 2021, 03:16:46 pm »
Pardon, stamane ero di fretta e mi era sfuggito il dettaglio.

Comunque la definizione proviene parai pari da:

Codice: [Seleziona]
  TCloseEvent = procedure(Sender: TObject; var CloseAction: TCloseAction) of object;

CloseAction non è una variabile appartenente alla classe, ed è usabile SOLO all'interno dell'evento ossia nella tua procedura "ChiudiPopUP".

OVVIAMENTE LA TUA PROCEDURA che hai abbinato a OnClose deve avere lo stessa definizione:

Codice: [Seleziona]
procedure TFormxxx.ChiudiPopUP(Sender: TObject;  var CloseAction: TCloseAction);
begin
  //qui puoi usare CloseAction
end; 

CloseAction non riporta cosa l'utente ha deciso di fare, ma cosa il tuo codice vuole fare quando avviene l'evento. Sinceramente non conosco quella classe, e non riesco ad abbinare questo dato logicamente (es. caMinimize cosa fà su un popup).

Non ha quindi senso testarla con l'IF se il tuo codice non l'ha a sua volta già impostata (per default dovrebbe essere sempre caNone all'ingresso della procedura).

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2870
  • Karma: +20/-4
Re:Impostare chiamata ad un evento
« Risposta #5 il: Dicembre 16, 2021, 03:21:08 pm »
In pratica le proprietà che iniziano con "On" sono dei puntatori a metodo (cioè a procedura/funzione di una istanza).
Quando le assegni, assegni l'indirizzo che la procedura deve andare in esecuzione quando si verifica quell'evento.

Come dice DragoRosso è all'interno di quella procedura che puoi usare le variabili che trovi nella definizione dell'evento.
Imagination is more important than knowledge (A.Einstein)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Impostare chiamata ad un evento
« Risposta #6 il: Dicembre 16, 2021, 04:08:30 pm »
Oggi era una giornata buona per rimanere a dormire.

Forse ho compreso cosa intendeva chiedere @bonmario.

La visualizzazione di un PopUP non è bloccante, ossia il codice non viene bloccato dopo la sua visualizzazione.

Quando l'utente deciderà di chiudere il PopUP, viene generato l'evento OnClose, evento che tu hai fatto puntare alla tua procedura e che quindi verrà eseguita.

Se vuoi nel tuo codice (ESTERNO ALL'EVENTO OnClose, quindi esterno alla tua procedura ChiudiPopUP) sapere quando questo è avvenuta, semplicemente usa una varibiale boolean definita globalalmente o nella tua classe Form per settarla nell'evento. Poi la puoi testare con tutta calma.

Esempio:
Codice: [Seleziona]
var PopUPChiuso: boolean;
//Da qualche parte lo inizializzi a false
// PopUPChiuso := false;

///Da qualche parte lo testi e lo rimetti a false
// If PopUPChiuso then
//   begin
//      ..... fai qualcosa
//      PopUPChiuso := false;
//   end;

procedure TForm1.ChiudiPopUP(Sender: TObject;  var CloseAction: TCloseAction);
begin
   PopUPChiuso := True;
end; 

EDIT: Nota che il ".......fai qualcosa" lo potresti fare anche nell'evento ChiudiPopUP, compatibilmente con la tua logica e il tuo codice ....

Ciao
« Ultima modifica: Dicembre 16, 2021, 04:12:34 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Impostare chiamata ad un evento
« Risposta #7 il: Dicembre 16, 2021, 04:57:42 pm »
Grazie @DragoRosso, ho fatto come dici tu, usando "PopUPChiuso" e va bene, ma c'è una cosa che continuo a non capire ...

Se la dichiarazione è questa:
Codice: [Seleziona]
procedure TForm1.ChiudiPopUP(Sender: TObject;  var CloseAction: TCloseAction);

la variabile "CloseAction", nonostante sia stata dichiarata con la clausola "var", perderà il suo valore all'uscita della procedura "ChiudiPopUP" ?

Se così fosse, che senso ha dichiararla come "var" ??

Grazie, Mario

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Impostare chiamata ad un evento
« Risposta #8 il: Dicembre 16, 2021, 05:24:04 pm »
Grazie @DragoRosso, ho fatto come dici tu, usando "PopUPChiuso" e va bene, ma c'è una cosa che continuo a non capire ...

Se la dichiarazione è questa:
Codice: [Seleziona]
procedure TForm1.ChiudiPopUP(Sender: TObject;  var CloseAction: TCloseAction);

la variabile "CloseAction", nonostante sia stata dichiarata con la clausola "var", perderà il suo valore all'uscita della procedura "ChiudiPopUP" ?

Se così fosse, che senso ha dichiararla come "var" ??

Grazie, Mario

Perchè è una variabile che nell'evento può essere settato. Il suo valore definisce come si comporterà il componente che riceve il messaggio WM_CLOSE di Windows.

EDIT: Ovviamente CloseAction verrà usato dal chiamante per fare qualcosa.

Con il PopUP non comprendo come possa essere di utilità, ma in una Form, se assegni l'evento OnClose vedrai che viene create la stessa identica procedura come evento.

In quel caso se assegni ad esempio a CloseAction il valore ca_Hide, la Form si "nasconderà" cioè diventerà invisibile. Se usi caFree, la Form verrà distrutta.

La definizione di VAR indica che il parametro viene passato come riferimento (puntatore in memoria) e non come valore (nello stack o nei registri CPU).

E' normale definire un parametro con "var" quando si hanno a che fare con metodi legati ad eventi o altro (callback ad esempio).

Ciao
« Ultima modifica: Dicembre 16, 2021, 05:27:53 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Impostare chiamata ad un evento
« Risposta #9 il: Dicembre 16, 2021, 06:10:23 pm »
EDIT: Ovviamente CloseAction verrà usato dal chiamante per fare qualcosa.

Era quello che mi interessava !!! Se fossi riuscito a capirlo, avrei usato direttamente qual valore, senza usare una variabile mia.

Con il PopUP non comprendo come possa essere di utilità, ma in una Form, se assegni l'evento OnClose vedrai che viene create la stessa identica procedura come evento.

L'oggetto che uso, TPopupNotifier, permette di emettere dei messaggi, è molto simile ai messaggi che sembrano un fumetto di Windows 10.
Ci sono alcune cose che mi devo ricordare durante la giornata, e per ricordarmele faccio uscire il messaggio tramite quell'oggetto.

In determinati casi, mi serve capire quando l'utente chiude il messaggio, in modo da poter fare altre operazioni.

Grazie, Mario

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Impostare chiamata ad un evento
« Risposta #10 il: Dicembre 16, 2021, 06:56:26 pm »
EDIT: Ovviamente CloseAction verrà usato dal chiamante per fare qualcosa.

Era quello che mi interessava !!! Se fossi riuscito a capirlo, avrei usato direttamente qual valore, senza usare una variabile mia.

Quella variabile ha "vita" esclusivamente in quella procedura, valore di default all'inizio e valore eventualmente settato da te entro la fine della procedura.

Non la si può "chiamare" da nessun altra parte, o meglio anche se definisci una varibaile globale con lo stesso nome, NON SARA' QUELLA COMUNQUE.

E' appunto una "var" perchè il chiamante (il thread principale del tuo programma, che genericamente ti è nascosto) deve poterla usare, ma la usa solo lui al di fuori della tua procedura.

EDIT: il thread principale usa il valore ritornato dalla variabile, ovviamente non la variabile ....

Ciao.
« Ultima modifica: Dicembre 16, 2021, 07:48:24 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Impostare chiamata ad un evento
« Risposta #11 il: Dicembre 17, 2021, 08:03:24 am »
Ok, forse ora ho capito.

Grazie, Mario

 

Recenti

How To

Utenti
  • Utenti in totale: 785
  • Latest: gmax
Stats
  • Post in totale: 18771
  • Topic in totale: 2233
  • Online Today: 404
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 399
Total: 399

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.