La Procedura


Per iniziare cominceremo a osservare più da vicino una procedura, magari scrivendone una per conto nostro.

Visualizziamo il codice del nostro progetto e in alto, dopo la scritta “{$R *.dfm}” scriviamo la nostra prima procedura:

PROCEDURE MiaPrima;

Begin

End;

Lanciando il programma non succede nulla perché abbiamo si costruito una procedura ma non fa niente, non è scritto nessuna riga di codice. Continuiamo scrivendo al suo interno un piccolo comando “Beep;”. Anche così se lanciamo il programma non succede nulla, infatti la procedura c’è e anche una riga di comando, ma non è chiamata ossia non viene lanciata da nessun evento. Come si chiama una procedura? Ma con il suo nome! E’ ovvio. Allora proviamo così: facciamo doppio clic sul secondo pulsante Button1 (dove modifichiamo la caption della label) e aggiungiamo una linea di codice scrivendo il nome della nostra procedura.

 

 

Se mentalmente seguiamo passo passo quello che succede quando premiamo il pulsante, noi avremo questo:

  1. Alla pressione del pulsante viene richiamato il codice scritto nell’evento OnClick

  2. Il primo comando modifica la caption della label

  3. Il secondo comando richiama la nostra prima procedura

  4. Viene eseguito un beep grazie al comando scritto nella nostra procedura

 

 

  5. Se esistesse un’altro comando dopo la chiamata alla nostra procedura questo verrebbe eseguito subito dopo

Volendo possiamo farlo. Nell’evento “CheckBox1Click” tagliate (Edit\Cut) il codice che abbiamo scritto prima e copiatelo (Edit\Paste) nell’evento “Button1Click”, subito dopo la chiamata alla nostra procedura.

 

 

Se provate ora vedrete che con una sola pressione del pulsante verranno eseguiti tre differenti comandi, inoltre abbiamo scoperto che l’editor di Delphi ha automaticamente rimosso l’evento vuoto (quello che vedete nell’ultima immagine), infatti non ha nessun comando e quindi è inutile. La nostra prima procedura contiene solo un comando, che potremmo benissimo spostare al posto della sua chiamata.

 

 

Facciamolo,da così:             

 

           A così:

 

 

In pratica ho spostato il comando dalla nostra procedura direttamente nella riga di comando dove veniva chiamata, ora “MiaPrima” è di nuovo inutile. Lanciamo e controlliamo se è cambiato qualcosa.

Dopo il primo clic sul pulsante “Button1” non succede più niente, si sente solo il beep, però possiamo pensare di creare un altro pulsante che ripristini le condizioni iniziali, così potremo di nuovo vedere l’effetto che fa. Allora ecco il primo esercizio:

  1. Modificate la caption del pulsante “Button1” e scrivete “Start”

  2. Mettete un altro pulsante sulla form, sotto “start”, e la scritta deve essere “Reset”

  3. Modifichiamo il nome della nostra procedura in “ResetOggetti”

  4. Il resto lo facciamo insieme. Nella nostra procedura scriviamo il codice per ripristinare i valori com’erano all’inizio. Eccoli:

        1. Label1.Caption := ‘Progetto 1’;

        2. Btn1.Parent := FormProva1;

  5. Doppio clic sul pulsante Reset e scrivete la chiamata alla nostra procedura “ResetOggetti;”

Tutto fatto, ma ci siamo accorti subito che qualcosa non va, sono comparsi segni rossi sotto i comandi nella nostra procedura, e se lanciamo Delphi compare una riga rossa dove incontra il problema e in basso ci dice anche quello che non va, abbiamo sbagliato qualcosa.

 

                  

 

Delphi non riconosce “Label1” eppure sulla form c’è. Se proviamo a spostare tutto il codice (taglia e incolla) al posto della chiamata alla procedura:

prima

 

 

dopo

 

 

vedrete che tutto torna alla normalità e se lanciate finalmente il programma, funziona. Cosa è cambiato? Perche il codice contenuto nella nostra procedura non va mentre inserito nella procedura creata da Delphi, funziona? Guardando l’ultima immagine e paragonando i due blocchi di codice ci rendiamo conto di qualcosa però, entrambe sono delle procedure, ma i nomi sono differenti e devono esserlo, però “Button2Click” è preceduto da un identificativo (per ora ignoriamo il contenuto delle parentesi), perche?

Precedentemente abbiamo parlato delle parentele tra oggetti, per rinfrescarci le idee ribadiamo che nel nostro caso “Label1” ha come proprietario “FormProva1”. Abbiamo anche detto che all’interno del proprietario (nel nostro caso la form) per riferirci agli oggetti basta chiamarli per nome e indicare la proprietà (esempio “Button1.Caption” oppure “Label1.Caption”), mentre se siamo fuori dal proprietario bisogna chiamarli ponendo all’inizio il nome appunto del proprietario (esempio “FormProva1.Button1.Caption” oppure “FormProva1.Label1.Caption”). Allora è evidente che la procedura creata da noi non appartiene alla form, pertanto se vogliamo che il nostro codice funzioni nella nostra procedura, bisogna che indichiamo anche dove sono locati gli oggetti che vogliamo modificare. Pertanto il tutto andrebbe scritto in questo modo:

 

 

provate, ora tutto dovrebbe funzionare a dovere.

Chiariamoci un poco le idee. Quando facciamo doppio clic con il mouse su un pulsante oppure facendo sempre doppio clic nella lista degli eventi (Object Inspector\Events) l’editor crea in automatico una procedura vuota.

procedure TFormProva1.CheckBox1Click(Sender: TObject);

begin

end;

Questa procedura è creata in modo che faccia parte dell’oggetto FormProva1, perché la CheckBox1, a cui si riferisce, appartiene a FormProva1. Noi possiamo creare procedure che appartengono alla nostra form, ma dobbiamo scriverle in modo diverso da come lo abbiamo fatto, imitando il modo di scriverle dell’editor. Con questo ultimo concetto abbiamo scoperto un altro lato di un oggetto, cioè quello di avere come proprietà anche delle procedure, e allo stesso modo anche delle funzioni.

 

 

Il prossimo passo sarà quello di rendere la nostra procedura proprietà di FormProva1, ma prima bisogna spiegare un nuovo concetto. Nell’immagine vista poco prima si possono notare due scritte in rosso (le scritte racchiuse dentro le parentesi graffe sono dei commenti e non incidono sul programma):

Letteralmente indicano che al loro posto si può scrivere qualcosa che farà parte della form, ma nel primo caso sarà trattata come privata (che può essere usata solo dagli oggetti presenti nella form) mentre nel secondo diverrà una cosa pubblica, accessibile a tutti. Questo si chiama visibilità. Per ora consideriamo solo il fatto che in questi due posti possiamo scriverci il nome delle nostre procedure, così da indicare al programma che fanno parte della form.

Per assimilare meglio questo concetto conviene fare degli esempi, così si capiscono le differenze e le peculiarità di ognuna di esse. La nostra nuova procedura si chiamerà “PrimaPriv” e sarà del tipo privato, scriveremo il suo nome nelle dichiarazioni per le private e poi implementeremo il codice dopo la nostra prima procedura “ResetOggetti”. Quindi alla fine di tutto dovremo avere questo:

 

             qui la dichiarazione

             qui l’implementazione

 

Se copiamo il codice che abbiamo scritto in “ResetOggetti” anche in “PrimaPriv”, ora possiamo evitare di scrivere il proprietario in quando la nostra nuova procedura fa parte dell’oggetto form.

 

 

Come già sappiamo per utilizzare questa procedura bisogna che venga richiamata da un evento, quindi mettiamo un altro pulsante sulla form, accanto a “Reset”, e chiamiamolo “Reset2”.

 

 

Doppio clic su di esso oppure sulla voce relativa negli eventi e scriviamo il nome della procedura:

procedure TFormProva1.Button2Click(Sender: TObject);

begin

PrimaPriv;

end;

Lanciando il programma si nota che entrambi i pulsanti fanno la stessa cosa, ma uno richiama gli oggetti dal di fuori (ResetOggetti) mentre l’altro da un punto di vista privilegiato (PrimaPriv), in quanto hanno in comune la stessa parentela (FormProva1).

Ora scriveremo una seconda procedura ma questa volta pubblica, e vedremo le differenze. Quindi in “Public” scriviamo il nome della nuova procedura “PrimaPub” e a seguire l’implementazione.

 

 

e come abbiamo fatto prima copiamo lo stesso codice senza scrivere il proprietario:

PROCEDURE TFormProva1.PrimaPub;

Begin

Label1.Caption := 'Progetto 1';

Btn1.Parent := FormProva1;

End;

Sempre come abbiamo fatto prima mettiamo un altro pulsante di fianco a “Reset 2” e chiamiamolo “Reset 3”. Questo dovrà chiamare l’ultima procedura, quella pubblica:

procedure TFormProva1.Button4Click(Sender: TObject);

begin

PrimaPub;

end;

Possiamo constatare che anche quest’ultima procedura fa la medesima cosa e nel medesimo modo, e a prima vista sembra che non ci sia nessuna differenza tra loro. Ma una differenza esiste altrimenti non si spiegherebbe per quale motivo esiste una separazione tra le due cose, per ora ci limiteremo alla sola spiegazione del concetto di visibilità, ma in seguito verrà di nuovo a galla.

In genere un progetto è costituito da più form, ognuna con i suoi oggetti messi sopra e che svolgono il proprio lavoro. Molte volte esiste un dialogo tra queste ma lo scambio di informazioni può avvenire solo tra oggetti pubblici, quelli privati vengono chiamati solo dal proprietario. La procedura pubblica “PrimaPub” può essere chiamata anche da un’altra form mentre quella privata “PrimaPriv” la possiamo richiamare solo dalla FormProva1.

Guardando il codice ci rendiamo conto di aver scritto tre volte la stessa cosa, se per caso dovessimo modificare la scritta, dovremmo farlo tre volte. Questo non è accettabile in un linguaggio strutturato a blocchi come il Pascal, pensando poi in grande sarebbe impensabile se le cose fossero ripetute centinaia di volte. Nel nostro caso è semplice trovare la soluzione basta richiamare sempre la stessa procedura, ossia “ResetOggetti;”. Quindi alla fine il codice rivisitato apparirà così:

 

 

Possiamo semplificare ancora di più il nostro piccolo progetto eliminando le procedure “Private” e “Public” che ci sono servite per fare i nostri studi:

 

 

Come vedete la procedura che svolge il lavoro è unica ma chi chiama il codice può essere anche più di uno, così è molto più leggibile e semplice da maneggiare.

Ora spero che la procedura sia abbastanza chiara come concetto, così possiamo passare tranquillamente a scoprire un’altra peculiarità di questo costrutto, ossia quella di poter accettare parametri.

Una procedura così come l’abbiamo vista fino a ora lavora su dati interni ma potrebbe utilizzare dati che le vengono forniti da chi la chiama. La sintassi per questo tipo di costrutto è questa:

PROCEDURE nomeprocedura(lista parametri);

begin

...

end;

La differenza che notiamo sono le due parentesi messe dopo il nome, al loro interno vengono scritte una o più variabili che il codice della procedura potrà utilizzare, come sempre ci spiegheremo meglio con un esempio.

Nel nostro codice modifichiamo la nostra procedura privata, aggiungendo un parametro di tipo stringa:

PROCEDURE ResetOggetti(VarStr : ShortString);

Begin

FormProva1.Label1.Caption := ‘Progetto 1’;

FormProva1.Btn1.Parent := FormProva1;

End;

Non provate a lanciare il programma perché segnalerebbe un errore, infatti ora la nostra procedura vuole che le venga passato un parametro, mentre prima no. Pertanto bisogna modificare ogni chiamata a essa.

 

 

Se lanciate ora il programma funziona tutto come prima, ma che senso hanno quelle stringhe passate alla procedura? Ma nella nostra procedura, la variabile che contiene la stringa passata non viene utilizzata, allora tocca modificarla un poco:

PROCEDURE ResetOggetti(VarStr : ShortString);

Begin

FormProva1.Label1.Caption := VarStr;

FormProva1.Btn1.Parent := FormProva1;

End;

Ora “VarStr” è utilizzata dal codice e se lanciate il programma capirete come. Quando si preme uno dei tre pulsanti viene chiamata questa procedura e gli viene passato un dato. Il dato viene ricevuto dalla procedura che lo usa per mostrarlo nella label.

La Funzione

Indietro