Manuale Delphi

130
 Manuale sul Delphi AUTORE: Carlo Marona IMPAGINAZIONE: DrN3On RDC  - Red Diamond Crew LEZIONE 1: La storia Il Delphi nasce come evoluzione del "Borland Turbo Pascal". Il Pascal  è un linguaggi o ad alto livello che è stato sviluppato alla fine degli anni sessanta dal professor Niklaus Wirth a Zurigo. Il suo scopo era quello di realizzare un linguaggio comprendente un piccolo numero di concetti fondamentali di programmazione sufficient i ad insegnarla in forma di disciplina logica e sistematica; nello stesso tempo voleva un linguaggi o che fosse facile ed efficient e da implement are sulla maggior parte dei calcolatori. Il suo successo nel conseguire questo obiettivo può essere misurato dalla rapida diffusione dell'uso del PASCAL sia come linguaggio usato nella didattica dei principi di programm azione (si usa tutt'oggi nelle università), sia come linguaggio effettivo per scrivere software di base ed applicativo. Cosa si intende per linguaggio ad alto livello? Un linguaggio ad alto livello è un linguaggio che tende con i suoi costrutti, la sua sintassi e grammatica di avvicinarsi il più possibile al linguaggio ed al ragionamento umano. In contrapposizione ai linguaggi ad alto livello, ci sono i linguaggi a basso livello come l' Assembler  ed affini che rimangono molto più vicini al linguaggio macchina utilizzato dal calcolatore. Queste macchine infatti non comprendono il linguaggio dell'uomo direttament e, sanno solamente lavorare con operazioni matematiche di base (addizione, sottrazi one, operazioni logiche implement ate da circuiti elettronici ) su sequenze più o meno lunghe di 0 o di 1. Rimanendo molto scom odo lavorare con sequenze di questo genere, i linguaggi di programmazi one tendono ad rendere il lavoro del programmatore più semplice astraendo da quello con cui effettivamente il calcolatore andrà a lavorare. L'Assembler è già un linguaggi o ad alto livello rispetto al linguaggio macchi na puro, ma è un linguaggio a basso livello rispetto ad altri linguaggi come il Pascal che lavora su un livello di astrazione super iore. L'evoluzione del Pascal  negli anni successi vi al suo sviluppo, lo ha portato alla definizione della versione 7.0 (includente la v. 2.0 del Turbo Vision) completamente orientata agli oggetti che a tutt'oggi viene ancora utilizzato per la realizzazione di software per DOS. Con l'avvento di Window s la Borland rilasciò il Borland Pascal  pacchetto basato sul linguaggio Object Pascal, naturale evoluzione del Turbo Pascal. La stesura di applicazioni in ambiente Windows rimaneva comunque alquanto lenta e complessa; era necessario conoscere molto bene la programmazione in Object Pascal e le immancabili API di Windows. Fu così che la Borland rilasciò la prima versione del Delphi, la 1.0 appunto. Questa versione di Delphi produceva applicazi oni per Windows a 16-bit. Successivamente venne rilasciat a la versione 2.0 completam ente rivista ed ottimizzat a per lo sviluppo di applicativi in ambiente 32-bit. Siamo all'incirca nel 1996 e da qui il Delphi si è evoluto ad una velocità impressionant e, quasi una versione all'anno. A d oggi (2001) la versione più recente del Delphi è la 5.0 e si vocifera che per la seconda metà dell'anno sarà disponibile la versione 6.0. Con il Delphi la Borland ha introdotto il concetto di sviluppo Visuale RAD (Rapid Application Development) orientato alla gestione degli eventi come nel Visual Basic, senza perdere però i vantaggi della compilazione Pascal. È da notare che il codice scritto in Delphi è conforme all'Object Pascal  di cui ha anch e ereditato il numero di versione; la versione 8.0 per Delphi 1.0, la 9.0 per Delphi 2.0 etc. Ciò è confermato dal fatto che è possibile compilare vecchie applicazioni in Object Pascal tramite il compilatore Delphi. Da notare che, come l'Object Pascal il Delphi è un linguaggio GP ( General Purpose) ovvero un tool di sviluppo che permette di realizzare applicazi oni di qualsiasi tipo, più o meno complesse e tutto questo con una semplicit à estrema. Ho voluto fare questa precisazione perché mi è capitato molte volte di parlare con persone "ignoranti" (nel senso che ignorano ;-) !!) che bistrattano questo linguaggi o solamente perché magari non ne hanno sentito parlare come il Visual Basic di Microsoft e quindi lo ritengono un linguaggi o "giocattolo".

Transcript of Manuale Delphi

Manuale sul DelphiAUTORE: Carlo Marona IMPAGINAZIONE: DrN3On RDC - Red Diamond CrewLEZIONE 1:

La storia

Il Delphi nasce come evoluzione del "Borland Turbo Pascal". Il Pascal un linguaggio ad alto livello che stato sviluppato alla fine degli anni sessanta dal professor Niklaus Wirth a Zurigo. Il suo scopo era quello di realizzare un linguaggio comprendente un piccolo numero di concetti fondamentali di programmazione sufficienti ad insegnarla in forma di disciplina logica e sistematica; nello stesso tempo voleva un linguaggio che fosse facile ed efficiente da implementare sulla maggior parte dei calcolatori. Il suo successo nel conseguire questo obiettivo pu essere misurato dalla rapida diffusione dell'uso del PASCAL sia come linguaggio usato nella didattica dei principi di programmazione (si usa tutt'oggi nelle universit), sia come linguaggio effettivo per scrivere software di base ed applicativo. Cosa si intende per linguaggio ad alto livello? Un linguaggio ad alto livello un linguaggio che tende con i suoi costrutti, la sua sintassi e grammatica di avvicinarsi il pi possibile al linguaggio ed al ragionamento umano. In contrapposizione ai linguaggi ad alto livello, ci sono i linguaggi a basso livello come l'Assembler ed affini che rimangono molto pi vicini al linguaggio macchina utilizzato dal calcolatore. Queste macchine infatti non comprendono il linguaggio dell'uomo direttamente, sanno solamente lavorare con operazioni matematiche di base (addizione, sottrazione, operazioni logiche implementate da circuiti elettronici) su sequenze pi o meno lunghe di 0 o di 1. Rimanendo molto scomodo lavorare con sequenze di questo genere, i linguaggi di programmazione tendono ad rendere il lavoro del programmatore pi semplice astraendo da quello con cui effettivamente il calcolatore andr a lavorare. L'Assembler gi un linguaggio ad alto livello rispetto al linguaggio macchina puro, ma un linguaggio a basso livello rispetto ad altri linguaggi come il Pascal che lavora su un livello di astrazione superiore. L'evoluzione del Pascal negli anni successivi al suo sviluppo, lo ha portato alla definizione della versione 7.0 (includente la v. 2.0 del Turbo Vision) completamente orientata agli oggetti che a tutt'oggi viene ancora utilizzato per la realizzazione di software per DOS. Con l'avvento di Windows la Borland rilasci il Borland Pascal pacchetto basato sul linguaggio Object Pascal, naturale evoluzione del Turbo Pascal. La stesura di applicazioni in ambiente Windows rimaneva comunque alquanto lenta e complessa; era necessario conoscere molto bene la programmazione in Object Pascal e le immancabili API di Windows. Fu cos che la Borland rilasci la prima versione del Delphi, la 1.0 appunto. Questa versione di Delphi produceva applicazioni per Windows a 16-bit. Successivamente venne rilasciata la versione 2.0 completamente rivista ed ottimizzata per lo sviluppo di applicativi in ambiente 32-bit. Siamo all'incirca nel 1996 e da qui il Delphi si evoluto ad una velocit impressionante, quasi una versione all'anno. Ad oggi (2001) la versione pi recente del Delphi la 5.0 e si vocifera che per la seconda met dell'anno sar disponibile la versione 6.0. Con il Delphi la Borland ha introdotto il concetto di sviluppo Visuale RAD (Rapid Application Development) orientato alla gestione degli eventi come nel Visual Basic, senza perdere per i vantaggi della compilazione Pascal. da notare che il codice scritto in Delphi conforme all'Object Pascal di cui ha anche ereditato il numero di versione; la versione 8.0 per Delphi 1.0, la 9.0 per Delphi 2.0 etc. Ci confermato dal fatto che possibile compilare vecchie applicazioni in Object Pascal tramite il compilatore Delphi. Da notare che, come l'Object Pascal il Delphi un linguaggio GP (General Purpose) ovvero un tool di sviluppo che permette di realizzare applicazioni di qualsiasi tipo, pi o meno complesse e tutto questo con una semplicit estrema. Ho voluto fare questa precisazione perch mi capitato molte volte di parlare con persone "ignoranti" (nel senso che ignorano ;-) !!) che bistrattano questo linguaggio solamente perch magari non ne hanno sentito parlare come il Visual Basic di Microsoft e quindi lo ritengono un linguaggio "giocattolo".

LEZIONE 2:

Versioni di Delphi

Abbiamo gi visto nell'Introduzione storica le prime due versioni di Delphi: la 1.0 e la 2.0. Abbiamo gi detto le principali differenze tra queste due versioni ovvero la prima lavora a 16-bit e la seconda a 32-bit. Dalla 2.0 in poi tutte le versioni di Delphi lavorano a 32-bit. Fin dalla prima versione di Delphi per ognuna di queste sono disponibili pi edizioni; in Delphi 1.0 queste erano due e si differenziavano per il supporto allo sviluppo Client/Server. Dalla versione 2.0 possibile scegliere tra tre edizioni differenti "Delphi 2.0 Standard", "Delphi 2.0 Developer" e la "Delphi 2.0 Client/Server". Dalla versione 4.0 queste tre edizioni hanno preso i nomi rispettivamente di "Standard", "Professional", "Enterprise". Le principali differenze tra queste edizioni stanno nella possibilit o no di gestire database, di disporre del supporto per internet, di lavorare con database server con drivers nativi (SQL Server, Oracle, Sybase, Interbase), di incorporare la gestione del multi-language o internazionalizzazione del software e nella disponibilit di tool di sviluppo aggiuntivi quali ad esempio l'SQL Monitor e il supporto per la creazione visuale di query SQL, il supporto per tecnologie CORBA, MIDAS, e COM. La versione 3.0 introduce una novit interessante non presente nelle versioni precedenti: il supporto per i packages. Al pari delle librerie DLL permettono di raggruppare del codice e permetterne il caricamento solo quando se ne ha la necessit; e di condividere, magari con altre applicazioni, il codice in esse contenuto. Ho detto al pari delle DLL: ci non del tutto corretto, ci sono delle differenze importanti tra i due sistemi come vedremo poi nel seguito del corso. Le versioni "Standard" sono, come dice il nome stesso, il livello base di Delphi per la realizzazione di applicazioni semplici che non richiedono l'utilizzo di database e l'accesso ad Internet, perlopi indirizzate a studenti, hobbisti, principianti. Le versioni "Developer" o "Professional" sono rivolte a coloro che utilizzano il Delphi per lavoro e che necessitano di supporto per database e internet. Le versioni "Enterprise", come dice il nome, sono rivolte alle aziende che necessitano del supporto per il controllo di versione, accesso a database sever, internet, internazionalizzazione del software. In questo corso si presuppone, almeno per alcune funzionalit, di avere a disposizione l'edizione "Professional" di Delphi 5.0, la stessa che normalmente utilizzo per lavoro.

Immagini delle confezioni delle varie releases della versione 5.0 (sito Borland)

LEZIONE 3:

Pascal, Delphi, Linux

Come gi menzionato nell'Introduzione storica, l'intento del professor Niklaus era quello di sviluppare un linguaggio facilmente implementabile su piattaforme differenti. Esistono diverse implementazioni del Pascal alcune di queste sono disponibili anche in ambiente Linux. Si tratta di implementazioni di tipo GNU e OpenSource, quale per esempio il "Free Pascal". Questa implementazione completamente compatibile con il Pascal standard e nelle sue ultime versioni implementa anche l'Object Pascal. Esistono anche ambienti di sviluppo GNU come per esempio Lazarus che riproducono quasi in maniera speculare l'IDE di Delphi e che permettono di realizzare con la stessa facilit (anche se ancora con molti problemi) interfacce grafiche per applicazioni Linux. Le distribuzioni menzionate supportano nativamente codice Delphi. Ci permetter di effettuare il porting di applicazioni per Windows in ambiente Linux apportando il minor numero possibile di modifiche al codice. Sulla stessa strada sta lavorando Borland che ha gi rilasciato la versione 1.0 del suo nuovo prodotto, il Kylix. Questo prodotto a tutti gli effetti il porting di Delphi per Windows in ambiente Linux. La stessa Borland afferma che dalla versione 6.0 di Delphi sar possibile effettuare il porting di applicazioni da Windows a Linux semplicemente ricompilando il codice con il Kylix. Il Kylix, per chi gi conosce Delphi, ne la riproduzione esatta: stessa interfaccia grafica, stessi tools, stesse impostazioni e disposizione dei comandi. La cosa pi importante che il codice compilato con il Kylix nativo per Linux ovvero in formato ELF. Per permettere il porting nella maniera pi semplice possibile la Borland ha dovuto riscrivere l'intera VCL (Visual Component Library, ovvero la libreria dei componenti visuali di Delphi) in maniera tale che fosse indipendente dalla piattaforma. Ci stato realizzato creando una nuova libreria la CLX (si legge clix) che si basa per la parte grafica sulle librerie Qt (oggetti multipiattaforma della Trolltech) le stesse utilizzate anche per la realizzazione della parte grafica di KDE. Purtroppo per le prime due edizioni del Kylix non esiste una licenza Open Source o GPL per cui andranno acquistate e non a basso prezzo. Si vocifera per la prossima uscita di una terza edizione che andr a coprire questa fascia. L'intento di Borland infine anche quello di integrare sotto lo stesso tool di sviluppo sia Delphi che C++ BUILDER. Staremo a vedere.

LEZIONE 4:

Panoramica sul linguaggio

Sempre facendo riferimento alla parte introduttiva storica di questo corso, abbiamo visto che Delphi si basa su Object Pascal. Si tratta, come d'altronde il Pascal, di un linguaggio compilato, fortemente tipizzato, che supporta la progettazione strutturata e orientata agli oggetti. Offre un codice di facile lettura, una compilazione veloce e l'uso di pi file unit per la programmazione modulare. Object Pascal ha delle speciali funzionalit che supportano la struttura a componenti e l'ambiente RAD di Delphi. I programmi Delphi sono generalmente divisi in moduli di codice sorgente denominati unit. Ogni programma inizia con una intestazione, che ne specifica il nome, la quale seguita da una clausola opzionale uses e da un blocco di dichiarazioni e di istruzioni. La clausola uses elenca le unit che sono collegate nel programma; queste possono essere condivise da programmi diversi ed hanno spesso proprie clausole uses. La clausola uses fornisce al compilatore informazioni sulle dipendenze esistenti tra i moduli. Dal momento che queste informazioni vengono memorizzate nei moduli stessi, i programmi in Object Pascal non richiedono n makefile, n file header, n direttive "include" per il preprocessore come per esempio nel C++. Diamo un'occhiata alle estensioni utilizzate dal compilatore Delphi. Questo si aspetta di trovare il codice sorgente in Pascal in di tre tipi: File sergente di unit, che terminano con l'estensione .PAS File progetto, che hanno come estensione .DPR File sorgente di package, che terminano con l'estensione .DPK

I file sorgente delle unit contengono la maggior parte del codice di un'applicazione. Ogni applicazione Delphi ha un singolo file progetto e diversi file unit; il file progetto, corrispondente al file "principale" nel Pascal

tradizionale, organizza i file unit in un'applicazione. Delphi mantiene automaticamente un file progetto per ciascuna applicazione. I file sorgente dei packages sono simili ai file progetto, ma vengono usati per costruire speciali librerie a collegamento dinamico, denominate package. Esistono altri file utilizzati nella realizzazione di una applicazione Delphi che non contengono codice Pascal. Questi file vengono di norma mantenuti automaticamente da Delphi. Essi sono: I file from, terminano con l'estensione .DFM I file di risorse, che hanno come estensione .RES I file di opzioni di progetto, che terminano in .DOF

Esistono anche altri tipi di file utilizzati esclusivamente per le impostazioni dell'ambiente di sviluppo come per esempio i file .DSK che contengono le impostazioni del desktop dell'IDE. I file .DFM sono dei file di risorse di Windows che contengono bitmap, stringhe e cos via. Ogni file form la rappresentazione binaria della scheda Delphi corrispondente generalmente ad una finestra o ad una finestra di dialogo di una applicazione Windows. L'IDE di Delphi permette anche di modificare in maniera testuale il contenuto di questi file; tranne in casi eccezionali, come il recupero di schede danneggiate a causa di componenti malfunzionanti, non sia ha la necessit di intervenire direttamente in maniera testuale su questo tipo di file. La gestione viene generalmente tenuta dai tool visuali di Delphi. Ad ogni scheda altres associato un file .PAS contenente il codice Pascal che si riferisce alla scheda in oggetto. Questo file contiene il codice degli eventi degli oggetti nella scheda, le routines definite dall'utente per quella scheda, ecc. Per impostazione predefinita questi file hanno lo stesso nome del file form. I file di risorse sono file di risorse standard di Windows (.RES) per contenere la bitmap per l'icona dell'applicazione. Questo quello che si ha prima di effettuare la compilazione del codice. Una volta che il codice stato compilato, troveremo dei nuovi file nella directory del progetto, alcuni con lo stesso nome di quelli appena visti ma con estensioni differenti. Queste sono: .DCU (Delphi Compiled Unit): sono le estensioni che il compilatore da alle unit compilate che in seguito verranno linkate insieme nel file .EXE .DLL (Dinamic Link Library): solo le estensioni che contraddistinguono una libreria a collegamento dinamico; ovviamente questo tipo di estensione sar disponibile qualora sia stato compilato un progetto di libreria a collegamento dinamico. .BPL (Borland Package Library): sono le estensioni delle librerie a collegamento dinamico della borland ovvero i package; anche queste estensioni non saranno sempre disponibili tranne se si effettua la compilazione di un progetto di package.

Diamo uno sguardo ad un semplice esempio, il tipico programmino "Hello World!" che si soliti realizzare in fase di apprendimento di un nuovo linguaggio. Si tratta di una semplice applicazione per console che pu essere compilato ed eseguito dalla riga di comando. Program Hello_World; {$APPTYPE CONSOLE} Var MessageStr : String; Begin MessageStr := 'Hello world!'; Writeln(MessageStr);

End.

La prima riga di questo codice, dichiara il nome del programma. La direttiva {$APPTYPE CONSOLE} indica al compilatore che si tratta di una applicazione console, da eseguire dalla riga comandi. La riga successiva dichiara una variabile di tipo stringa. Successivamente, all'interno del blocco Begin..End., che costituisce il blocco principale del programma, viene dapprima assegnata alla variabile MessageStr il valore contenuto nella stringa 'Hello world!'. In ultimo con l'istruzione Writeln(MessageStr) il contenuto della variabile MessageStr viene visualizzato sullo schermo dopo di che il programma termina. Per compilare il programma dell'esempio, possibile, se Delphi stato correttamente installato e nella path di sistema riportato il percorso ..\BIN nella directory di installazione di Delphi, utilizzare il seguente comando: supponendo di aver chiamato il file del programma Hworld.Pas o Hworld.dpr possiamo scrivere DCC32 Hworld.pas Otterremo un file eseguibile di nome Hworld.exe che se eseguito stamper a video il testo 'Hello world!'. Questo non solitamente l'uso che si fa di Delphi. Delphi solitamente utilizzato per la realizzazione di applicazioni Windows con interfaccia grafica non eseguibili dalla riga di comando. Anche la struttura del file di progetto leggermente differente e non contiene generalmente codice effettivo dell'applicazione se non poche chiamate ai metodi definiti nelle unit. Vediamo un attimo alcune particolarit che avrete sicuramente gi notato. Prima di tutto il segno ";" (punto e virgola) che delimita la fine di una istruzione. Il Pascal, come il C++ ed altri linguaggi simili, necessita di questo segno di punteggiatura per riconoscere il termine di una istruzione. Un'altra particolarit il "." (punto) che delimita la fine del blocco principale del codice. Come vedremo pi avanti, solamente il blocco principale delle unit avr il punto dopo l'End del blocco principale, i blocchi delle Funzioni e delle Procedure utilizzeranno normalmente il punto e virgola. Ma passiamo ora ad esaminare in maniera pi approfondita la sintassi e la struttura del linguaggio.LEZIONE 5:

Panoramica sull'IDE

L'IDE (Integrated Development Environment) di Delphi ci mette a disposizione molti strumenti utili per la stesura del codice e per la realizzazione visuale delle interfacce grafiche dei nostri programmi.

Fig. 1- La finestra principale dell'IDE di Delphi Quello che colpisce non appena si avvia l'IDE di Delphi per la prima volta, che questo non ricopre interamente il desktop. Ci permette di vedere ci che dietro l'IDE senza ridurre l'IDE stesso ad icona.

Fig. 2 - Come appare l'IDE di Delphi nel desktop di Windows

L'IDE si compone principalmente di quattro sezioni fondamentali: la finestra principale (fig. 1), l'Object Inspector, il Code Editor, il Form Designer. La finestra principale, contiene i menu, le toolbar con i tasti per l'accesso rapido alle funzioni pi usate (personalizzabile), la Component Palette contenente tutti i componenti visuali e non installati in Delphi. Quest'ultima pu essere organizzata a piacimento aggiungendo o togliendo pagine e spostando i componenti da una pagina all'altra. Per esempio, si potrebbe aggiungere una pagina "Help" dove andremo a riporre tutti quei componenti che serviranno ad implementare il sistema di aiuto in linea delle nostre applicazioni. Per fare ci, si pu cliccare con il tasto destro sulla Component Palette e scegliere la voce Properties che visualizzer una finestra di dialogo tramite la quale sar possibile procedere alla personalizzazione. L'IDE permette di personalizzare la disposizione e le caratteristiche degli strumenti attivi dando la possibilit di salvare queste impostazioni come configurazioni del desktop per essere richiamate alla necessit. Per esempio, come visibile nella figura 2, nel mio ambiente di sviluppo ho definito una configurazione "Edit" che utilizzo durante la stesura del codice. Si potrebbe definire anche una configurazione "Debug", da attivare quando si effettua il debug di una applicazione, che visualizzi gli strumenti per il debug e nasconda quelli non necessari a questo scopo. Una volta salvate, queste configurazioni sono richiamabili tramite il menu a tendina posto nella toolbar a fianco a quella dei menu. L'Object Inspector quello strumento che ci permette di modificare a design time la propriet dei componenti che inseriamo nelle Form dell'applicazione. Ci permette altres di associare agli eventi dei componenti il codice opportuno.

Fig. 3 - L'Object Inspector di Delphi Il Code Editor un editor ASCII completo, ricco di utili funzionalit, tramite il quale si agisce sul codice sorgente dell'applicazione.

Fig 4 - Il Code Editor Il Form Designer lo strumento che, durante la fase di sviluppo, ci permette di disporre e configurare i componenti nelle nostre Form. A livello visuale, insieme all'Object Inspector, costituisce lo strumento fondamentale per lo sviluppo delle nostre applicazioni.

Fig. 5 - Il Form Designer Vedremo questi strumenti pi approfonditamente nei paragrafi seguenti. Oltre a questi strumenti sono da menzionare: il Project Manager per la gestione dei progetti e di tutti i files che lo compongono, la To-Do List che permette di definire all'interno del codice cosa c' da fare (appunto To-Do!), il Class Explorer che permette di visualizzare l'albero "genealogico" di una classe, ovvero tutti gli oggetti di cui quella classe eredita propriet e metodi. Una novit importante da segnalare, rispetto alle versioni precedenti, la possibilit che offre il Project Manager di aprire pi progetti contemporaneamente. Ci risulta molto utile quando abbiamo a che fare con applicazioni composte anche da DLL. Un'altra funzionalit messaci a disposizione dall'IDE di Delphi l'Object Repository, ovvero uno strumento che ci permette di creare una specie di database contenente schede, finestre di dialogo, moduli dati, wizard, DLL atte a semplificare lo sviluppo di applicazioni. Questo disponibile dal menu File scegliendo la voce New. Cos facendo apparir una finestra contenente le strutture base di per vari oggetti. In pratica questo strumento rappresenta una interfaccia per gestire templates di oggetti. Ci permette ad esempio di creare applicazioni con la stessa struttura di finestre, magari centralizzando il codice in comune. possibile espandere la dotazione di templates esistenti aggiungendone di personalizzati; ci possibile cliccando con il tasto destro del mouse sulla finestra dell'Object Repository e scegliendo la voce Properties, oppure dal menu Tool scegliendo la voce Repository. Questa la dotazione standard dell'IDE di Delphi, ma non finisce qui La struttura dell'IDE aperta, ovvero possibile scrivere applicazioni o add-on per l'interfaccia di sviluppo stessa. Per esempio, come potete notare dalle figure precedenti, nel mio ambiente di sviluppo ho installato una serie di add-on chiamati G-Experts che aggiungono molte funzionalit utili all'interfaccia di sviluppo. In poche parole, se l'IDE manca di qualche funzionalit, potrete sempre inserirla voi scrivendo del codice ad hoc. Questo argomento non verr trattato nel corso, ma esistono libri, come quelli di Marco Cant, che spiegano come creare estensioni per l'IDE di Delphi. Tra gli strumenti aggiuntivi, forniti con Delphi, sono presenti anche un Image Editor molto semplice per realizzare le icone dei componenti e delle applicazioni, il Database Desktop (per le versioni Professional) per l'esplorazione e la manipolazione di database ed il Package Editor. In ultimo da aggiungere che la maggior parte degli strumenti nominati precedentemente possono essere disposti a piacere all'interno dell'IDE. Per esempio possibile inserire nella finestra che contiene l'Object Inspector anche il Project Manager come possibile vedere dalle figure. Questi strumenti sono di tipo dockable, ovvero si comportano come le barre degli strumenti di Word e quindi possibile, trascinandoli, posizionarli in una finestra o nell'altra oppure lasciarli liberi come finestra a s nel desktop.LEZIONE 6:

L'Object Inspector

L'Object Inspector , insieme al Form Designer, lo strumento pi utilizzato, a livello visuale, per la creazione delle applicazioni. Tramite questo strumento si possono gestire tutte le propriet (disponibili a design time) ed eventi dei componenti visuali e non. Anche questo strumento ampiamente personalizzabile. Una delle personalizzazioni possibili quella di visualizzare l'elenco delle propriet ordinate per nome o raggruppate per categorie.

Fig. 1 - Le propriet del componente Button1 visualizzate nell'Object Inspector Come possibile vedere dalla figura 1 tutte le propriet impostabili a design time, sono disponibili nell'Object Inspector. Le pagine di questo si dividono, sia per quanto riguarda le propriet che per i gestori degli eventi, in due parti: sulla sinistra sono riportati i nomi delle propriet e sulla destra i rispettivi valori. L'Object Inspector capace di visualizzare ed impostare numerosi tipi di dati. Per quanto riguarda i dati numerici e le stringhe di caratteri, questi vengono rappresentati cos come sono (per esempio la propriet Height del componente e la propriet Name). Per tipi di dati pi complessi, come per esempio il font, che rappresentato da un classe TFont, l'Object Inspector aggiunge davanti al nome della propriet un segno "+". Cliccando su di esso, si espandono le propriet relative alla classe TFont istanziata per l'Oggetto Button1.

Fig. 2 - La propriet Font del componente Button1.

Quando a fianco di un valore presente un tasto con tre puntini ( ) significa che l'Object Inspector ha un Editor di Propriet ad hoc per quel tipo di valore. Cliccando questo tasto si apre una finestra che permette di modificare il valore della propriet e di riportarlo automaticamente nell'Object Inspector. La stessa operazione pu essere effettuata premendo la combinazione di tasti Ctrl + Invio dalla tastiera. Sempre come esempio, quello riportato di seguito l'editor di propriet per il tipo TFont.

Fig. 3 - L'editor di propriet per il tipo TFont.

Quando invece al posto del tasto presente il tasto ci indica che possibile scegliere il valore da una lista predefinita di valori. Infatti cliccando questo tasto, otteniamo ci che visibile nella figura 4

Fig. 4 - Scelta del valore dalla lista di valori predefiniti.

Questo possibile in quanto la propriet ModalResult visibile in figura di tipo TModalResult che altro non che un tipo enumerato. Tutti i valori dei tipi enumerati sono selezionabili con la modalit precedentemente vista. anche possibile utilizzare i tasti freccia della tastiera per selezionare un valore oppure facendo doppio click con il tasto sinistro del mouse i valori si avvicenderanno secondo l'ordine riportato nell'elenco. Per esempio, prendiamo in esame la figura 4. Il valore selezionato per la propriet ModalResult mrNone; senza visualizzare la tendina con l'elenco potremmo fare doppio click con il mouse sul valore per ottenere mrOk; se continuiamo a fare doppio click avremo mrCancel e cos via. C' ancora un altro tipo di dato che l'Object Inspector in grado di gestire; il tipo Set, insieme. Quando una propriet di tipo Set, il suo valore racchiuso tra parentesi quadre. In pratica vengono rappresentati tra parentesi gli elementi che sono inclusi nell'insieme.

Fig. 5 - Come appare una propriet di tipo Set nell'Object Inspector

Le propriet Set, presentano, come le propriet di tipo Class, un segno "+" davanti al nome della propriet; cliccando su di esso viene mostrato l'elenco degli elementi che possono appartenere all'insieme. Per indicare che un particolare elemento incluso nell'insieme, impostare il suo valore a True e viceversa per escluderlo impostarlo a False. Passiamo ora a visionare la pagina dell'Object Inspector dedicata alla manipolazione dei gestori di eventi.

Fig. 6 - La pagina relativa ai gestori degli eventi. Nella figura 6 riportata la pagina degli eventi relativi ad un componente Button (TButton). Per definire un gestore di eventi per un particolare evento, ci sono vari modo; fare doppio click con il tasto sinistro del mouse sull'evento corrispondente, scrivere il nome del gestore di evento nella casella a destra del nome dell'evento e premere invio, scegliere un gestore di evento tra quelli gi definiti agendo sul tasto con la freccia. Seguendo il primo modo l'IDE creer per noi un gestore di evento il cui nome sar composto dal nome del componente pi il nome dell'evento a cui si riferisce. Ovviamente verr aggiunto al codice tutto ci che necessario per creare il gestore di evento. Vediamo un esempio. Sempre con il nostro componente Button di nome Button1, facendo doppio click sul evento OnClick nell'Object Inspector, verr creato automaticamente un gestore per l'evento OnClick di nome "Button1Click" e verr aggiunto il seguente codice a quello gi esistente

procedure TForm1.Button1Click(Sender: TObject); begin end; All'interno del blocco Begin..End di questa procedura andr solamente inserito il codice che dovr essere eseguito nel momento in cui si premer il componente Button. Insieme al codice sopra riportato, viene, ovviamente, aggiunta la dichiarazione della procedura "Button1Click" come procedura di tipo pubblico all'interno della classe TForm1.

type

TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations }

Nella parte superiore dell'Object Inspector presente presente una casella combinata dalla quale possibile scegliere il componente di cui modificare le propriet.LEZIONE 7:

Il Form Designer

Il Form Designer di Delphi quello strumento che permette, a livello visuale, di creare le interfacce grafiche delle applicazioni semplicemente disponendo i componenti su di esso ed impostando le loro propriet. Questo gestisce sia componenti visuali che non visuali. Gli oggetti non visuali, (ovviamente in fase di sviluppo sono visibili!) sono rappresentati da dei riquadri assomiglianti agli speed buttons delle toolbars recanti per una icona che stata definita durante lo sviluppo del componente. Un esempio di oggetto non visuale l'oggetto Timer (TTimer) che in fase di sviluppo appare cos .

Lavorare con il Form Designer semplicissimo, sufficiente selezionare un componente dalla Component Palette, situata nella finestra principale dell'IDE e posizionarlo all'interno di quella che sar la nostra form. Il posizionamento pu avvenire in vari modi: si pu cliccare sul componente nella Component Palette e successivamente cliccare nella form alla posizione in cui lo vogliamo inserire; si pu cliccare il componente nella Component Palette quindi cliccare nella form alla posizione voluta e trascinare per definirne le dimensioni. Se non si trascina durante il posizionamento del componente, questo assumer una la dimensione standard definita la momento dello sviluppo. Una volta che il componente si trova nella form, possiamo spostarlo, ridimensionarlo, cambiare le sue propriet. Per posizionare pi componenti dello stesso tipo possibile selezionare selezionarlo dalla Component Palette tenendo premuto il tasto Shift sulla tastiera. Cos facendo intorno ad esso nella Component Palette apparir un rettangolo di colore blu che indicante che stiamo posizionando pi componenti di quel tipo. Per disattivare questa modalit di inserimento basta cliccare sul tasto con la freccia nella Component Palette. Un'altro modo per inserire componenti in un form quello di fare doppio clic sul tasto relativo nella Component Palette; cos facendo il componente verr posizionato al centro della form.

Fig. 1 - Il Form Designer con alcuni componenti

Per spostare un componente sufficiente cliccare su di esso e mantenendo cliccato trascinarlo nella posizione voluta. Per ridimensionare un componente, invece, occorre prima selezionarlo e quindi trascinare una delle otto maniglie che compaiono attorno ad esso. La logica la stessa utilizzata da programmi di grafica tipo CorelDraw e simili. Nella figura 1 riportata l'immagine del Form Designer con alcuni componenti. possibile notare le maniglie di ridimensionamento attorno al componente Edit1. I puntini visibili sullo sfondo della form sono relativi alla griglia di posizionamento, ci permette di allineare comodamente i componenti in quanto, grazie alla propriet snap, questi si agganciano automaticamente, con l'angolo superiore, a questi punti. Quando si sposta un componente, appare un riquadro che ci informa sulla posizione dell'angolo superiore sinistro del componente rispetto all'angolo superiore sinistro della form, il tutto espresso in pixel.

Fig. 2 - Spostamento di un componente La stessa cosa accade quando si ridimensiona un componente; questa volta per vengono visualizzate le dimensioni che assume lo stesso espresse sempre in pixel e rappresentano la lunghezza e l'altezza del componente.

Fig. 3 - Ridimensionamento di un componente Facendo click con il tasto destro del mouse su un componente o sulla form appare un menu le cui voci permettono di allineare i componenti, di definirne l'ordine di tabulazione (la sequenza con cui viene assegnato il fuoco ai componenti spostandosi con il tasto Tab della tastiera), cambiare lo Z-Order dei componenti (portarli in primo piano o sullo sfondo), modificare l'ordine di creazione dei componenti.

Fig. 4 - Il menu contestuale. In questo menu possono essere presenti anche altre voci (quelle visualizzate sono quelle standard) in base all'oggetto specificato poich questo potrebbe avere un Component Editor personalizzato che semplifichi la configurazione delle sue propriet. Potrebbero essere presenti anche voci che permettono di impostare, senza ricorrere all'Object Inspector, alcune propriet come per esempio per un componente TreeView (TTreeView), dove in testa al menu contestuale appare la voce "Items Editor..." che permette di aprire un editor ad hoc per l'inserimento, la cancellazione e ridisposizione degli elementi dell'albero. All'interno del Form Designer possibile selezionare pi oggetti per impostarne le propriet comuni agli stessi valori. Ho parlato di propriet comuni in quanto al momento della selezione di pi componenti, anche di tipo differente, l'Object Inspector visualizzer ovviamente solo le propriet impostabili su tutti i componenti selezionati. Per selezionare pi componenti si pu selezionare il primo di essi e tenendo premuto il tasto Shift sulla tastiera selezionare gli altri. anche possibile utilizzare solamente il mouse per selezionare pi componenti. Se i componenti sono posizionati in modo da essere all'interno di una area rettangolare, si pu, cliccare sulla form e trascinare. Cos facendo si vedr un rettangolo che avr come origine il punto in cui si iniziato a trascinare e come dimensione quella da voi definita trascinando il cursore del mouse. A questo punto rilasciando il tasto del mouse avremo selezionato tutti i componenti presenti all'interno del rettangolo di selezione. Una volta selezionati i componenti possono essere deselezionati cliccando semplicemente sulla form o sottraendoli alla selezione tenendo sempre premuto il tasto Shift sulla tastiera e cliccando su di essi. Gli spostamenti e i ridimensionamenti sono possibili anche tramite la tastiera, tramite i tasti freccia e al combinazione del tasto Ctrl o del tasto Shift. Per spostare un componente tramite i tasi freccia, necessario prima selezionarlo quindi tenendo premuto il tasto Ctrl ed agire sui tasti freccia per spostarlo nelle direzioni rappresentate dai tasti. Per ridimensionare un componente procedere in maniera analoga allo spostamento agendo per sul tasto Shift. Questa modo di operare risulta comodo per un posizionamento ed un ridimensionamento preciso dei componenti in quanto le variazioni avvengono a scatti di un pixel per volta. Una volta posizionati i componenti all'interno della form, onde evitare di spostarli inavvertitamente, possibile bloccarli con la funzione "Lock Controls" dal menu Edit.LEZIONE 8:

Il Code editor (parte prima)

Il Code editor di Delphi un editor ASCII molto completo, ricco di molte funzioni utili nella stesura del codice. Quando si impostano le propriet degli oggetti a livello visuale, l'ambiente integrato di Delphi apporta, a livello di codice Pascal, le modifiche necessarie. Per esempio quando aggiungiamo ad una Form un componente prendendolo dalla "Component Palette", viene aggiunta automaticamente la dichiarazione di quell'oggetto nel codice. Le caratteristiche fondamentali del "Code Editor", sono il "Syntax Highligth", il "Class Completion", il "Code Insight", il "Code Explorer", la possibilit di aggiungere dei segna posto (bookmarks) per ritornare velocemente ad una certa posizione all'interno del codice, i "Tool Tips" che forniscono informazioni sia durante la fase di debug (valori delle variabili, ) che in fase di stesura del codice, fornendo per esempio aiuto sulla sequenza e sul tipo di parametri da passare ad una funzione o procedura. Altra funzionalit che ritengo

importante, se non fondamentale, quella dell'aiuto in linea. Posizionando il cursore su una porzione del codice e premendo F1, si accede direttamente all'help relativo al testo su cui posizionato il cursore.

Fig. 1 - Ecco come appare la schermata del Code Editor Come possibile vedere dall'immagine, nel code editor compare gi del codice che stato inserito al momento della creazione di una nuova applicazione. Infatti quando si crea una nuova applicazione, l'ambiente di sviluppo crea come sia il file di progetto che una Form (o finestra) principale. N.B. Nelle immagini che vedrete in questo corso, potreste accorgervi di configurazioni e impostazioni che potrebbero differire dal vostro ambiente di sviluppo. Per esempio, la combinazione di colori che vedete nel Code Editor "Classic" ovvero segue i colori del vecchio ambiente di sviluppo Turbo Pascal. Ritengo sia la migliore sia per il contrasto a livello visivo, sia perch essendo lo sfondo di colore scuro e lavorandoci parecchie ore non stanca. La configurazione standard presente di default dopo l'installazione prevede uno sfondo bianco. Torno a ripetere che in questo corso si presuppone di avere a disposizione almeno la versione 5 Professional di Delphi. Il codice visibile nella figura fa riferimento alla form riportata di seguito

Fig. 2 - Main form del programma non contenente alcun componente Come potete vedere, nel codice definita una classe TForm1 e una variabile Form1 di tipo TForm1. In pratica l'ambiente di Delphi ha gi predisposto per noi le basi per cominciare a realizzare la nostra applicazione.

Ora, se aggiungiamo un componente alla nostra Form, vedremo che il codice viene automaticamente aggiornato. Per esempio aggiungiamo dalla Component Palette un componente Button e vediamo cosa succede

Fig. 3 - La nostra Form con aggiunto il componente Button Ecco cosa viene automaticamente aggiunto al codice

Fig. 4 - La definizione dell'oggetto Button aggiunto alla nostra Form. Quando inseriamo un componente in una form, viene automaticamente aggiornato il codice nel Code Editor e possiamo anche notare che, come in precedenza per la Form, gli viene anche assegnato un nome in base al numero di componenti dello stesso tipo, con lo stesso nome, gi presenti nella Form stessa. Infatti il nostro Bottone all'interno del codice Delphi viene identificato tramite il nome di Button1. Questa solo il minimo che pu fare per noi l'ambiente di sviluppo di Delphi, infatti come avrete notato in Fig. 1, accanto all'area predisposta per l'editing del codice, vi un riquadro contenente una struttura ad albero, che ci fa vedere le varie sezione del codice in forma semplificata. Questo riquadro il Code Explorer che ci permette di navigare all'interno del codice senza scorrere il testo del codice, ma semplicemente selezionando la voce che ci interessa tra quelle riportate. Quando si inserisce del codice nell'editor, viene automaticamente aggiornata la struttura del Code Explorer. Questo strumento , come tutti gli strumenti messi a disposizione dall'IDE, personalizzabile permettendo di scegliere cosa visualizzare nell'albero e cosa no.

Fig. 5 - Ramo TForm1 del Code Explorer espanso mostra il componente Button1 da noi aggiunto. Facendo doppio clic con il mouse nel Code Explorer alla voce Button1, vedremo che il cursore nel Code Editor si posizioner dove nel codice definito il nostro componente Botton1. Ora espandiamo tutti i rami visualizzati nel code Explorer vediamo le corrispondenze con il codice.

Fig. 6 - Tutti i rami del Code Explorer espansi; possiamo vedere le corrispondenze con il codice nella destra Tutti gli elementi che abbiamo visto all'interno del codice sono riportati anche nella struttura ad albero del Code Explorer. Anche le unit incluse nella clausola Uses vengono riportate il tutto ordinato alfabeticamente. Ci risulta molto utile per ricercare funzioni, procedure, variabili ecc. e per posizionarsi rapidamente nel codice soprattutto in presenza di unit contenenti migliaia di righe di codice.LEZIONE 9:

Il Code editor (parte seconda)

Tramite il Code Explorer anche possibile inserire definizioni di variabili o funzioni o procedure. Cliccando con il tasto destro del mouse e scegliendo la voce New viene aggiunto un nuovo item editabile nel ramo selezionato.

Fig. 7 - Aggiunta di un nuovo item al Code Explorer. Per inserire una funzione o una procedura, utilizzare la stessa sintassi che si utilizzerebbe per dichiararla all'interno del Code Editor. Riguardo al Code Editor bisogna ancora dire alcune cosette. Come visibile in tutte le figure rappresentanti il Code Editor, nella parte superiore della finestra che lo contiene sono presenti delle "linguette" (sulla sinistra) e delle freccie tipo Internet Explorer. La funzionalit di quest'ultime la stessa di quelle di Internet Explorer; infatti ci permettono di navigare nel codice seguendo gli spostamenti che abbiamo gi effettuato. N.B. Non corrisponde all'Undo e Redo per le modifiche apportate al codice! Per quanto riguarda le linguette, esse rappresentano i files aperti nell'Editor e ci permettono di passare ad editare un file o l'altro semplicemente cliccando su di esse. Per esempio, se nel nostro editor avessimo aperto una unit di nome Unit2, vedremo a fianco della linguetta Unit1 un'altra linguetta recante il nome della nuova unita aperta. Cliccando su di essa visualizzeremmo il codice in essa contenuto. Rimane ancora una parte relativa all'editor che non stata ancora trattata. quel piccolo riquadro presente in fondo alla finestra. Quest'area contiene, ovviamente al momento opportuno (dopo la compilazione per esempio), messaggi di errore, informazioni riguardanti la compilazione del codice o errori segnalati dal Class Completion. Sotto quest'area presente una barra di stato che contiene informazioni riguardo la posizione del cursore (riga: colonna), se sono state apportate modifiche al codice (modified) e lo stato della modalit di inserimento dei caratteri (insert, overwrite). Il Class Completion un'altra delle funzionalit, a mio parere molto comoda, che permette di appunto completare, in maniera quasi automatica, il codice che si sta scrivendo. Infatti, digitando il nome di una classe, o di una sua istanza, per esempio il nostro Button1 nelle figure precedenti, seguito dal punto (.), il nostro editor ci propone un elenco di propriet e metodi appartenenti a quella classe. possibile scegliere la voce che ci interessa tramite le frecce della tastiera o cominciare a digitare parte della propriet o metodo che ci interessa. Cos facendo, tramite un ricerca incrementale, l'editor ci porta alla voce di nostro interesse; battendo invio, l'editor terminer per noi la scrittura del codice.

Fig 8 - Il Class Completion in azione Un'altra funzionalit che merita di essere citata, quella che ci permette di saltare alla definizione di un identificatore come si farebbe cliccando su un collegamento ipertestuale in un Web Browser. Infatti, tenendo premuto il tasto Ctrl e puntando un identificatore nel codice, quest'ultimo si trasforma in un collegamento ipertestuale a tutti gli effetti. Cliccandolo, verremo trasferiti in quella parte di codice contenete la dichiarazione dell'identificatore puntato, anche se questo dichiarato in un'altra unit.

Fig. 9 - Un collegamento ipertestuale sul tipo di Button1 Un ultima caratteristica molto interessante del Code Editor la possibilit di definire dei templates di codice per richiamarli all'occorrenza. Tramite la voce Editor Properties->Code Insight accessibile dal menu Tool possibile definire il testo dei templates.

Fig. 10 - Definizione dei Code Template. Una volta fatto ci, possibile richiamare i code templates durante la scrittura del codice tramite la combinazione di tasti Ctrl + J; verr visualizzata una lista dei templates definiti. Cominciando a scrivere il nome di un template ed utilizzando la combinazione di tasti Ctrl + J verr visualizzata la lista dei templates corrispondenti alla parte di nome gi digitata e qualora si fosse digitato per intero il nome del template o alla parte di nome digitata corrispondesse solamente un template, questo verrebbe subito riportato nel codice. Per esempio, scrivendo "cases" e premendo la combinazione di tasti Ctrl + J apparir il seguente blocco di codice Case of : ; : ; End; con il cursore posizionato tra Case ed of, cio possibile definire nel template la posizione da cui si incomincer a digitare il codice mancante.LEZIONE 10:

Il Project Manager

Il Project Manager strumento raggruppa in s tutti i file che compongono un progetto. Quest'ultimo pu essere composto anche da pi progetti. Questo potrebbe essere il caso di un'applicazione che includa delle DLL o pi eseguibili. I vari progetti vengono racchiusi in gruppi. Uno solo dei progetti appartenenti ad un gruppo pu essere attivo nello stesso momento e questo sar il progetto su cui si andr ad operare quando per esempio di proceder alla compilazione del codice.

Fig. 1 - Il Project Manager Nella figura precedente questo strumento inserito nella stessa finestra dell'Object Inspector ma anche possibile averlo come finestra a s o inserito nel Code Editor. Ecco come apparirebbe solo soletto.

Fig. 2 - Il Project Manager in una finestra a s Fondamentalmente si compone di un albero organizzato in gruppi e progetti. Nella figura 2 visibile il gruppo di progetto ProjectGroup1 contenente il progetto Project1. A fianco sono riportati i percorsi in cui sono stati salvati i file. Nella parte superiore presente una casella combinata che permette la selezione del progetto attivo e accanto alcuni bottoni che permettono di aggiungere nuovi progetti, di rimuoverli o di rendere attivo il progetto selezionato nell'albero. possibile anche operare tramite il menu contestuale che si attiva facendo click con il tasto destro del mouse sulla voce che interessa.

Fig. 3 - I vari menu contetsuali che appaiono cliccando sulle diverse voci dell'albero (Da sinistra: Project Group, Project, File del progetto, file sorgente ed altri) Le ultime tre voci sono presenti in tutti i menu e permettono di visualizzare o nascondere parti dell'interfaccia, come la Toolbar e la Status Bar, o di attivare/disattivare la funzionalit di docking che permette di inserire il Project Manager in altre finestre dell'IDE. Per aggiungere files al progetto anche possibile trascinarli da Esplora Risorse di Windows. Tramite questo strumento possibile gestire le opzioni relative al progetto selezionando la voce Options dal menu contestuale del progetto oppure scegliendo la stessa voce dal menu Project della finestra principale dell'IDE. Tra le opzioni possibile specificare informazioni riguardanti la versione dell'applicazione, direttive del compilatore, i percorsi in cui il compilatore andr a cercare le unit da compilare, scegliere l'icona dell'applicazione, il suo titolo, quale sar la finestra principale del programma, quali finestre saranno create automaticamente all'apertura del programmai, le opzioni del linker, quali packages sono utilizzati dall'applicazione e se l'applciazione deve essere compilata utilizzando i packages di run-time.

Fig. 4 - La finestra di dialogo opzioni del progetto.LEZIONE 11:

Sintassi e Struttura del codice

Abbiamo visto in precedenza un esempio di applicazione console. Ora vedremo un altro esempio riguardante per un'applicazione per Windows ovvero quello che ci interessa di pi e per cui Delphi nato. Questo il codice: Program Editor;

Uses Forms, REAbout in 'REABOUT.PAS' {AboutBox}, REMain in 'REMAIN.PAS' {MainForm}; {$R *.RES} Begin Application.Title := 'Text Editor'; Application.CreateForm(TMainForm, MainForm); Application.Run; End.

Come potete vedere il codice leggermente diverso, come contenuto, da quello che abbiamo visto in precedenza ma la struttura la stessa. Abbiamo una intestazione del programma "Program Editor", una clausola "Uses" contenente i riferimenti per l'inclusione di altre unit nel programma, ed il blocco principale "Begin..End.". Solitamente in questo blocco sono presenti solamente chiamate a metodi dell'oggetto Application del progetto. Ogni progetto Delphi ha una variabile Application di tipo TApplication (o come vedremo TWebApplication, TserviceApplication in base al tipo di progetto scelto) che permette di accedere alle propriet e metodi base dell'applicazione stessa. Quindi la struttura di un file di progetto di Delphi pu essere riassunta cos (in rosso i nostri commenti): Program NomeProgramma; //Intestazione del programma Uses Unit1, Unit2, , UnitN; //Clausola uses per l'inclusione di altre unit nel programma {$R *.RES} Begin //Blocco principale del progetto ... End.

Struttura e Sintassi delle unitOgni unit contenuta in un file .PAS e pu contenere dichiarazioni di tipi, variabili, funzioni, procedure. Come il file di progetto, anche la unit inizia con una intestazione (che ha inizio con la parola chiave Unit e dal nome della unit stessa) seguita da altre sezioni come riportato di seguito: Unit Unit1; {Intestazione} Interface Uses {Lista di unit}

Implementation Uses {Lista di unit} {Codice per la definizione di tipi, variabili, funzioni e procedure} Initialization {Codice di inizializzazione della unit} Finalization {Codice di finalizzazione della unita} End. Come si pu vedere abbiamo: una sezione definita "Interface" che conterr le definizioni di tipi, variabili, dichiarazioni di funzioni e procedure che si vuole siano accessibili da altre unit; una sezione definita "Implementation" che conterr il codice "privato" della unit, non accessibile dall'esterno, consistente in dichiarazioni di tipi, variabili, funzioni, procedure e il codice di implementazione delle funzioni o procedure stesse. Le sezioni "Initialization" e "Finalization" sono facoltative e servono ad eseguire codice per l'inizializzazione della unit e per la finalizzazione della unit rispettivamente al momento del caricamento della unit stessa e al momento del rilascio. Se in una clausola uses sono presenti pi di una unit, la sequenza con cui saranno eseguite le sezioni "Initialization" sar la stessa di quella della clausola uses. Per esempio se la clausola uses riporta uses unit1, unit2, unit3; l'ordine con cui verranno eseguite le sezioni di inizializzazione sar: unit1, unit2, unit3. Per quanto riguarda le sezioni di finalizzazione l'ordine sar inverso rispetto a quello di inizializzazione. Con riferimento all'esempio di prima avremo: unit3, unit2, unit1. Riguardo alla clausola uses di un programma o libreria, come nell'esempio di programma Windows che abbiamo visto in precedenza, c' la possibilit di indicare il percorso in cui si trova la unit da includere nel progetto specificando dopo il nome della unit la parola chiave "in" seguita dal percorso assoluto o relativo racchiuso tra apici. Per esempio mettiamo che la unit "Unit1.pas" nel seguente progetto si trovi in un percorso diverso da quello in cui sitrova il file principale del progetto avremo: Program Program1; Uses Unit1 in 'c:\progetti\mioprogetto2\Unit1.pas';

In questo caso ho fatto riferimento ad un percorso assoluto ma avrei potuto specificare un percorso relativo. Per esempio, se il Program1 si trovasse nella directory "c:\progetti\mioprogetto1" e all'interno ci fosse una directory chiamata "extra" in cui ripongo delle unit, nell'esempio precedente avrei potuto scrivere: Uses Unit1 in 'c:\progetti\mioprogetto1\extra\Unit1.pas'; oppure Uses Unit1 in '..\extra\Unit1.pas'; considerando sempre il fatto che il file principale del programma si trovi in "c:\progetti\mioprogetto1".

Un'ultima cosa riguardo le unit. Come facilmente intuibile, nella clausole uses di una unit posso fare riferimento ad altre unit. In questo caso bisogna fare attenzione ai "riferimenti circolari", ovvero fare attenzione a non far riferimento in una unit ad un'altra che a sua volta si riferisce alla prima. Leggendo potrebbe venire in mente che chi sta scrivendo questo corso sia un pazzo. In effetti pi semplice capire ci che ho detto con un esempio. Program Program1; Uses Unit1; Const Pippo = Pluto; ... Unit Unit1; Interface Uses Unit2; Const Pluto = Paperino; ...

Unit Unit2; Interface Const Paperino = 1; ... Nell'esempio precedente non ci sono problemi di "riferimenti circolari" e tutto funziona bene. Program Program2; Uses Unit1; Const Pippo = Pluto; ...

Unit Unit1; Interface Uses Unit2; Const Pluto = Paperino; ...

Unit Unit2; Interface

Uses Unit1; Const Paperino = 1; ... In questo esempio invece abbiamo un problema di "riferimento circolare". Infatti la Unit1 fa riferimento nella sua clausola uses alla Unit2 che a sua volta fa riferimento nella sua clausola uses alla Unit1. Al momento della compilazione del progetto questo errore viene segnalato dal compilatore. Nel caso in cui sia necessario utilizzare questa struttura di progetto, per evitare un "riferimento circolare" tra la Unit1 e la Unit2 sufficiente spostare la clausola uses con il riferimento alla Unit 1 della Unit2 nella sezione "Implementation" come riportato di seguito: Program Program2; Uses Unit1; Const Pippo = Pluto; ... Unit Unit1; Interface Uses Unit2; Const Pluto = Paperino; ... Unit Unit2; Interface Const Paperino = 1; Implementation Uses Unit1; ... Se abbiamo due unit che dichiarano una variabile, costante, tipo, routine con lo stesso nome, possiamo accedere alla variabile, costane, tipo, routine che ci interessa fornendo anche il nome della unit nel modo seguente: Unit Unit1; Interface Const Pluto = 1; ... Unit Unit2;

Interface Const Pluto = 2; ... Uses Unit1, Unit2; ... Topolino := Unit1.Pulto; //La variabile Topolino assumer valore 1 Topolino := Unit2.Pluto; //La variabile Topolino assumer valore 2 ... N.B. Chi conosce gi il C++, pu notare che le unit del Delphi o pi in generale dell'Object Pascal corrispondono ai "NameSpace" e che la clausola uses corrisponde alla direttiva "#Include".LEZIONE 12:

La sintassi (parte prima)

L'Object Pascal usa il set di caratteri ASCII, comprendente le lettere dalla A alla Z e dalla a a alla z, le cifre da 0 a 9 e gli altri caratteri standard. Non fa distinzione tra maiuscole e minuscole, come il C++ o il Java o Javascript. Tutti i caratteri quali lo spazio (ASCII 32) ed i caratteri di controllo, come il carattere di ritorno o di fine riga etc. (ASCII 0 a 31), vengono chiamati Blank. La pi piccola unit significativa di testo in un programma il token. Questo composto da una istruzione o da un'espressione o da una dichiarazione. Quindi un programma una sequenza di token separati da separatori (spazio o commento). quindi legale scrivere nel codice Pippo:=1;Pluto:=2; Per motivi di leggibilit e di convenzione, per, si preferisce utilizzare il formato seguente: Pippo := 1; Pluto : = 2; I token si suddividono in simboli speciali, identificatori, parole riservate, direttive, numerali, etichette, stringhe di caratteri. Quelli che seguono sono simboli speciali: #$&'()*+,-./:;=@[]^{} Anche la combinazione di alcuni di essi rientra nei simboli speciali: .. // (* (. *) .) := = Non fanno parte dei simboli speciali i seguenti caratteri: ! "(doppio apostrofo) ? % \ _(sottolineatura)| (pipe)~ (tilde)

Identificatori

Gli identificatori indicano variabili, costanti, procedure, funzioni, tipi, etc. Possono avere una lunghezza qualunque e devono iniziare con una lettera o con un carattere di sottolineatura (_) e non possono contenere spazi. Se necessario, per una maggiore leggibilit del codice, si pu utilizzare il carattere sottolineatura (_). Alcuni esempi di identificatori: Count / Count / cOunt / counT / _Pippo / _pippo / Items_Count / Items_count / Search_for

NumeraliIn Object Pascal i numeri reali ed interi possono essere rappresentati sia in forma decimale che in forma esadecimale. La prima forma composta da sequenze di numeri separati o no da punti e possono essere precedute dai segni + o - per indicarne il segno. Per i numeri interi non possibile utilizzare il punto (ovviamente, se sono interi!). Un esempio di numero intero 23989, +23989 oppure -56739. I numeri reali possono altres essere rappresentati in forma esponenziale inserendo all'interno della sequenze di numeri il carattere E o e seguito da un numero (positivo o negativo). Questo carattere sta ad indicare che il numero alla sua sinistra va moltiplicato per 10 elevato al numero alla sua destra. Per esempio: 7E-2 equivale a 7 x 10-2 12.25e6 e 12.25E+6 equivalgono entrambi a 12.25 x 106

Stringhe di caratteriIn Object Pascal le stringhe di caratteri sono racchiuse tra apostrofi ('). Due apostrofi che non racchiudono alcuna carattere identificano una stringa null. Ad esempio '' (occhio, sono due apostrofi adiacenti non le virgolette, quelle sopra il 2 nella tastiera!). Alcuni si chiederanno come possibile rappresentare all'interno di una stringa il carattere apostrofo visto che quest'ultimo delimita la stringa stessa. Bene, per rappresentare un apostrofo all'interno di una stringa basta ripeterlo due volte, per esempio 'L''anno scorso'. Una stringa composta solamente da un apostrofo appare cos ''''. Uno spazio, invece, apparir cos ' '. possibile inserire all'interno di una stringa di caratteri, sequenze di caratteri di controllo utilizzando il simbolo # seguito dal codice ASCII del codice stesso. Ad esempio, la stringa 'Questa stringa termina con un a capo ed avanzamento riga.'#13#10.

CommentiCome in quasi tutti i linguaggi di programmazione, per documentare o "commentare" il codice sorgente, possibile inserire, tramite particolari costrutti, dei commenti. In Pascal esistono vari modi per inserire commenti all'interno del codice sorgente. Si pu far precedere il commento da //. Per esempio Var Pippo : Integer; //Commento In questo caso il commento terminer con la fine della riga del codice. Per utilizzare commenti su pi righe, si possono impiegare le parentesi graffe {}. Ad esempio

Unit Unit1; { Questo commento si sviluppa

su pi righe } ...

Direttive del compilatoreLe direttive del compilatore sono particolari direttive che non influiscono sull'esecuzione del programma ma sulla compilazione del codice sorgente. Queste sono dei commenti che hanno come primo carattere, all'interno delle parentesi graffe {} o dei simboli (* *), il carattere $ (dollaro). Un esempio di direttiva lo abbiamo gi visto nel primo esempio di programma all'inizio del corso {$APPTYPE CONSOLE} In questo caso la direttiva indica al compilatore che il programma dovr essere compilato per essere eseguito dalla console e non nell'ambiente grafico di windows. Esistono molte direttive per il compilatore e per un elenco completo si rimanda ai manuali del linguaggio od alla guida in linea.

OperatoriUn operatore si comporta come le funzioni che fanno parte del linguaggio. Per esempio se sia ha qualcosa del tipo (X + Y), che composta da due operandi (X , Y) e da un operatore (+), nel caso in cui X ed Y rappresentino dei numeri, l'espressione restituir la loro somma. In Object Pascal esistono vari tipi e categorie di operatori. Ci sono operatori aritmetici, per logica booleana, per la manipolazione logica a livello di bit, di stringa, di puntatore, per i set, relazionali e classe.

Operatori aritmeticiSegue un elenco degli operatori aritmetici definiti in Object Pascal:Operatore + * / Div Mod Operazione Addizione Sottrazione Moltiplicazione Divisione (reale) Divisione (intera) Modulo Tipo Operandi Integer, real Integer, real Integer, real Integer, real Integer Integer Tipo Risultato Integer, real Integer, real Integer, real Real Integer Integer Esempio X+Y X -Y X*Y X/Y X div Y X mod Y

Come facilmente comprensibile, tutti gli operatori sopra riportati sono operatori binari, accettano cio due operandi. Per i prime quattro operandi non si sono problemi. Vediamo invece come si comporta l'operatore div. Questo operatore effettua la divisione tra operandi di tipo integer e restituisce un integer. In pratica questo operando restituisce il risultato di X / Y arrotondandolo all'intero per difetto. Vediamo un esempio: X / Y (con X = 9 e Y = 2) resituisce 4,5

X div Y (con X = 9 e Y = 2) resituisce 4 L'operatore mod restituisce il resto della divisione intera dei suoi operandi. Accetta operandi di tipo integer e il risultato di tipo integer. Con riferimento all'esempio precedente abbiamo che X mod Y (con X = 9 e Y = 2) resituisce 1 perch equivale a X - (X div Y) * Y = 9 - (9 div 2) * 2 = 1 (N.B. l'operatore di moltiplicazione, come altre che vedremo di seguito, ha la precedenza rispetto alla sottrazione quindi prima viene risolto il contenuto tra parentesi, poi viene effettuata la moltiplicazione tra il risultato precedente e 2 ed infine viene sottratto a 9 il risultato delle operazioni precedenti: 9 div 2 = 4; 4 * 2 = 8; 9 - 8 = 1) IMPORTANTE: da segnalare che nelle espressioni X / Y, X div Y, X mod Y, ove Y sia uguale a 0 (zero) si verifica un errore di divisione per zero L'operatore + e l'operatore - sono impiegati anche come operatori unari ovvero si applicano ad un solo operando. Essi servono a definire il segno di una espressione. Si applicano ad operandi di tipo integer o real e il risultato restituito dello stesso tipo dell'operando a cui si applicano ma con il segno opportunamente cambiato.

LEZIONE 13:

La Sintassi (parte seconda)

Segue un elenco degli operatori booleani definiti in Object Pascal:Operatore Not And Or Xor Operazione Negazione Congiunzione Disgiunzione Tipo Operandi Tipo Risultato Esempio Boolean Boolean Boolean Boolean Boolean Boolean Boolean Not X X and Y X or Y X xor Y

Disgiunzione esclusiva Boolean

Poco c' da dire su questo tipo di operatori, essi seguono infatti le regole della logica booleana. Una considerazione importante va fatta sulle diverse modalit di valutazione che l'Object Pascal offre. Questa di default impostata sulla valutazione parziale, ma possibile impostare la valutazione totale utilizzando la direttiva del compilatore {$B+} e disattivarla con la direttiva {$B-}. La valutazione parziale da preferire perch garantisce tempi di esecuzione pi brevi, questo perch la valutazione dell'espressione viene eseguita rigidamente da sinistra verso destra interrompendola nel momento in cui la valutazione risulta completa. Questo tipo di valutazione si applica sia all'operatore and che all'operatore or. In pratica quando viene valutata una espressione del tipo X and Y e X assume valore False Y non viene valutata in quanto il risultato dell'espressione gi noto; infatti una espressione del tipo X and Y pu risultare True in un solo caso, ovvero quando X ed Y sono True, in tutti gli altri casi assume valore False.

Operatori logici con bitSegue un elenco degli operatori logici applicabili ai bit definiti in Object Pascal:Operatore Not And Or Xor Shl Operazione Negazione Congiunzione Disgiunzione Tipo Operandi Tipo Risultato Esempio Integer Integer Integer Integer Integer Integer Integer Integer Not X X and Y X or Y X xor Y X shl 3

Disgiunzione esclusiva Integer Spostamento a sinistra Integer

Shr

Spostamento a destra Integer

Integer

X shr 3

Gli operatori shl e shr eseguono uno spostamento di bit, pari al numero indicato dopo l'operando, rispettivamente a sinistra ed a destra. Per esempio, se X contiene il valore 20 (in binario 010100) X shl 1 restituir 40 (in binario 101000). Con riferimento all'esempio precedente, se al posto di shl ci avessimo shr il risultato ottenuto sarebbe stato 10 (in binario 001010). Quindi quando si utilizza l'operatore shl equivale a moltiplicare il primo operando per 2 elevato al secondo operando. Seguendo sempre l'esempio precedente questo equivale a X * 21, mentre nel caso dell'operatore shr l'equivalente operazione quella di divisione del primo operando per 21.

Operatori relazionaliSegue un elenco degli operatori relazionali definiti in Object Pascal:Operatore = < > = Operazione Uguaglianza Disuguaglianza Minore di Maggiore di Minore uguale a Tipo Operandi Vari Vari Vari Vari Vari Tipo Risultato Boolean Boolean Boolean Boolean Boolean Boolean Esempio X=2 X Y XY X = 2

Maggiore uguale a Vari

Normalmente i tipi degli operandi devono essere compatibili, eccezion fatta per i tipi real ed integer che possono essere confrontati tra di loro. Per quanto riguarda le stringhe, vengono confrontate in base al set di caratteri ASCII esteso. Il confronto viene effettuato da sinistra verso destra, carattere per carattere. Ad esempio la stringa 'Delphi' minore della stringa 'Pascal' in quanto la lettera 'D' viene nel set di caratteri prima della lettera 'P'. Ovviamente qui la differenza tra le due stringhe immediata; se avessimo avuto una stringa 'Delphi' ed una stringa 'Delpho', quest'ultima sarebbe stata maggiore della prima ma solamente grazie all'ultimo carattere che costituisce la stringa. Nel caso di una stringa Str1 = 'Delphi' e di un'altra stringa Str2 = 'Delphi', il confronto Str1 = Str2 restituirebbe True. Alcuni degli operatori che abbiamo gi visto possono essere applicati anche in altri casi. Per esempio gli operatori +, -, *, =, = , si applicano anche ai set (insiemi) con rispettivamente i seguenti significati: unione, differenza, intersezione, sottoinsieme di, superset, uguaglianza, disuguaglianza. Per i tipi set esiste anche un altro operatore, l'operatore in che indica se un elemento presente in un insieme. Per esempio, se disponiamo di un set S composto dai seguenti elementi [1, 2, 3, 4] l'espressione 3 in S restituir True poich 3 un elemento del set S. Per quanto riguarda i puntatori, gli operatori applicabili a quest'ultimi sono: +, -, ^, =, . Il pi importante (o il pi usato) fra questi, l'operatore ^ che serve a dereferenziare un puntatore. Gli altri operandi servono ad aggiungere uno scostamento all'indirizzo puntato, a calcolare lo scostamento tra gli indirizzi puntati da due puntatori, a confrontare gli indirizzi puntati da due puntatori. Un altro operatore importante @ che serve a restituire l'indirizzo di una variabile, l'indirizzo di ingresso di una subroutine o di un metodo di classe.

Regole di precedenza degli operatoriEspressioni complesse vengono valutate seguendo delle regole per ciascuno degli operatori visti. Di seguito presente una lista degli operandi e dei rispettivi livelli di precedenza.Operatore @, Not *, /, div, mod, and, shl, shr, as +, -, or, xor =, , , =, in, is Precedenza Prima (pi alta) Seconda Terza Quarta (pi bassa)

In una espressione vengono valutati prima gli operatori con precedenza pi alta. Per esempio l'espressione 2 + 3 * 4 da come risultato 14 e non 20! Infatti viene valutata prima la moltiplicazione tra 3 e 4 (12) poich la moltiplicazione ha una precedenza pi alta ed in seguito viene aggiunto al risultato 2 (12 + 2 = 14). Per modificare la precedenza degli operatori, si utilizzano le parentesi tonde '(', ')'. Racchiudendo tra parentesi tonde una espressione, questa verr valutata per prima e tutto il resto a seguire seguendo sempre le regole di precedenza. Con riferimento all'esempio precedente, potremmo ottenere come risultato 20, modificandolo come segue: (2 + 3) * 4 Cos facendo, verr valutato prima il contenuto tra parentesi (2 + 3 = 5) ed il risultato moltiplicato per 4 (5 * 4 = 20). Le parentesi possono essere utilizzate anche quando la precedenza gi definita dall'operatore, senza influenzare la valutazione, consentendo una maggiore leggibilit ed interpretazione del codice. Sempre con riferimento all'esempio precedente scrivendo 2 + (3 * 4) il risultato non cambierebbe, mettendo bene in evidenza quale parte dell'espressione viene valutata prima. Per gli operatori che godono della stessa precedenza, la valutazione avviene normalmente da sinistra verso destra. Ad esempio 2+3-4=1 poich 2 + 3 = 5 e 5 - 4 = 1.

Conversione di tipiUn'altra funzionalit che ci mette a disposizione il Delphi, la possibilit di effettuare delle conversioni di tipo. Ci possibile racchiudendo tra parentesi tonde l'espressione da convertire e facendo precedere il tutto (senza spazi) dal tipo in cui si vuole convertire l'espressione. La sintassi esatta la seguente tipo(espresione) Ad esempio potrebbe essere utile convertire in boolean un valore intero come 0 nel modo seguente: boolean(0).LEZIONE 14:

I tipi (parte prima)

Nelle sezioni precedenti del corso abbiamo visto, in particolare nelle sezioni che spiegavano gli operatori, cose come Integer, String, Boolean. Si tratta dei tipi di dati. Un tipo essenzialmente un nome che identifica un particolare genere di dati. Un tipo determina anche il range di valori validi per quel tipo. Quando si definisce una variabile si deve specificarne il tipo. L'Object Pascal un linguaggio fortemente tipizzato. Ci significa che distingue un gran numero di dati. Solitamente, questa caratteristica permette al compilatore di trattare i dati in maniera intelligente e di poter rilevare degli errori in fase di compilazione che altrimenti sarebbero difficili da diagnosticare. Esistono diversi tipi di dati in Object Pascal; questi sono organizzati in tipi fondamentali (definiti direttamente dal linguaggio), generici, predefiniti e definiti dall'utente.

I tipi fondamentali sono implementati direttamente nel linguaggio Object Pascal; i loro formati e intervalli di validit sono gli stessi in tutte le implementazioni e sono indipendenti dalla CPU e dal sistema operativo. I tipi generici invece, possono variare da un'implementazione all'altra e sono specifici della piattaforma. consigliabile l'utilizzo dei tipi generici in quanto facilitano il porting tra piattaforme differenti. I tipi predefiniti sono automaticamente riconosciuti dal compilatore e non hanno necessit di essere dichiarati. I tipi Object Pascal possono essere classificati come segue: simple, string, structured, pointer, procedural, variant.

I tipi SimpleI tipi simple definiscono insiemi ordinati di valori. Appartengono a questa categoria di tipi, i tipi ordinal e real.

I tipi ordinalI tipi ordinal definiscono insiemi ordinati di valori in cui tutti i valori hanno un predecessore ed un successore univoci ad esclusione del primo valore e dell'ultimo. Sono tipi ordinal i tipi integer, boolean, character, subrange. Ogni valore caratterizzato da una ordinalit che ne determina l'ordinamento nel tipo. Solamente per il tipo integer l'ordinalit corrisponde con il valore stesso. In tutti gli altri tipi, ad esclusione del subrange, il primo valore ha ordinalit 0, successivo 1 e cos a seguire. Delphi, o meglio l'Object Pascal, mettono a disposizione diverse funzioni predefinite che permettono di lavorare sulla ordinalit di questa categoria di tipi. Le pi importanti tra queste sono le seguenti:Funzione Ord Pred Succ High Low Valore restituito restituisce l'ordinalit di un valore restituisce il predecessore del valore specificato restituisce il successore del valore specificato restituisce il valore pi alto nel tipo restituisce il valore pi basso nel tipo

Vediamo alcuni esempi: High(Byte) restituisce 255 in quanto il valore pi alto del tipo 255; Succ(4) 5 poich 5 il successore di 4. Esistono due funzioni deifnite in Object Pascal che che si usano per incrementare e decrementare il valore di una variabile ordinal e sono Inc e Dec. La prima incrementa il valore ed equivale al Succ del valore stesso, la seconda lo decrementa ed equivale al Pred del valore indicato.

I tipi IntegerI tipi Integer sono un sottoinsieme dei numeri interi. Esistono vari tipi di interi in Object Pascal che si differenziano per intervallo di valori rappresentabili e per formato. Per quanto riguarda i tipi interi generici abbiamo il tipo Integer e Cardinal. I tipi integer fondamentali sono: Shortint, Smallint, Longint, Int64, Byte, Word, Longword. Nella tabella seguente sono riportate le differenze tra i tipi menzionati.Tipo Integer Cardinal Shortint Smallint Longint Int64 Byte Word Longword Intervallo -2147483648..2147483647 0..4294967295 -128..127 -32768..32767 -2147483648..2147483647 -263..263-1 0.255 0..65535 0..4294967295 32 bit 8 bit + segno 16 bit + segno 32 bit + segno 64 bit + segno 8 bit 16 bit 32 bit Formato 32 bit + segno

Incrementando l'ultimo valore o decrementando il primo valore di un tipo integer il risultato sconfina all'inizio od alla fine dell'intervallo valido per quel tipo. Ad esempio, nel caso del tipo Byte che ha come intervallo 0..255 l'esecuzione del codicevar

I : Byte;

... I := High(Byte); I := I + 1; assegna ad I il valore 0. Da notare che se stato attivato il controllo sugli intervalli, il codice precedente generer un errore di runtime.

I tipi characterFanno parte dei tipi ordinal anche i tipi character i cui tipi fondamentali sono AnsiChar e WideChar. Gli AnsiChar sono caratteri che occupano un byte (8 bit) mentre i tipi WideChar sono caratteri che occupano due byte ovvero una word (16 bit). Il rpimo tipo ordinato secondo il set di caratteri esteso ANSI mentre il secondo ordinato secondo il set UNICODE i cui primi 256 caratteri corrispondono ai caratteri ANSI. Il tipi generico Char che nell'implementazione corrente equivale ad AnsiChar. Esistono anche per questo tipo delle funzioni predefinite dell'Object Pascal come la Chr che restituisce il carattere associato ad un intero compreso nell'intervallo AnsiChar o WideChar. Ad esempio Chr(65) restituisce 'A'. Come per tutti i tipi ordinali, possibile applicare al tipo character la funzione predefinita Ord che restituisce l'ordinale del valore character. Ad esempio, riprendendo l'esempio precedente, Ord('A') restituisce 65 che appunto l'ordinalit del carattere 'A' all'interno di AnsiChar o WideChar. Valgono anche per i tipi character gli sconfinamenti come visto per i tipi integer.

I tipi BooleanI tipi boolean predefiniti sono quattro e sono: Boolean, ByteBool, WordBool e LongBool. Si utilizza preferibilmente il tipo boolean mentre gli altri esistono per compatibilit con altri linguaggi e con l'ambiente Windows. Una variabile boolean equivale a ByteBool ed occupa un byte (8 bit) mentre una WordBool occupa due byte (16 bit) ed una LongBool due word (32 bit). L'intervallo di valori per questo tipo composto da due costanti predefinite che sono True e False. Un valore boolean viene considerato True quando la sua ordinalit diversa da zero. Da notare che se questo valore compare in un contesto in cui atteso un valore boolean, questo viene automaticamente convertito dal compilatore in True la dove la sua ordinalit sia diversa da 0.

I tipi EnumeratedIl tipo enumerated serve a definire insiemi ordinati di valori. Da notare che l'ordinalit di questi valori segue l'ordine con cui sono stati elencati i valori al momento della dichiarazione del tipo. Per dichiarare un tipo enumerated si utilizza la seguente sintassi Type EnumeratedTypeName = (val1, val2, ..., valn); Un esempio pratico potrebbe essere la dichiarazione di un tipo enumersto "Seme" in un gioco di carteType

Seme = (Cuori, Quadri, Fiori, Picche);

Nel caso del nostro esempio, i valori validi per il tipi "Seme" da noi dichiarato sono: Cuori, Quadri, Fiori, Picche. In pratica quando si dichiara un tipo enumerated si dichiarano delle costanti (val) del tipo enumerated dichiarato (EnumeratedTypeName). Sempre facendo riferimento al nostro esempio, Cuori, Quadri, Fiori, Picche sono costanti di tipo Seme. Bisogna fare attenzione, al momento della dichiarazione del tipo, a non utilizzare, per gli identificatori dei valori, nome che possano andare in conflitto con altri nomi dichiarati nello stesso campo d'azione. Ad esempio, dichiarando un tipoType

TSound = (Click, Clack, Clock);

ed utilizzando il valore Click come nel codice seguente, si verificher un conflitto di nome; questo perch Click anche il nome di un metodo della classe TControl e di tutti i sui discendenti (nel senso degli oggetti che discendono da esso!).Procedure Var

TForm1.Edit1Exit(Sender : TObject);

Snd : TSound;

Begin

... Snd := Click; ...End;

Si pu aggirare questo tipo di inconveniente facendo riferimento al valore Click qualificandolo con il nome della unit in cui stato dichiarato. Ammettiamo che il tipo TSound sia dichiarato nella unit SoundFuncs, si potrebbe utilizzare il seguente codice Snd := SoundFuncs.Click; Comunque, bench sia possibile utilizzare il codice precedente, si consiglia di cercare di definire, per i valori dei tipi eneumerated, dei nomi che non entrino in conflitto con altri identificatori. Una buona pratica quella di anteporre al nome del valore enumerated le iniziali del nome del tipo enumerated. Nell'esempio precedente abbiamo dichiarato un tipo TSound; possiamo ridefinire i nomi dei suoi valori anteponendo "ts" al loro nome in questo modoType

TSound = (tsClick, tsClack, tsClock);

Come ancheType

TMyType = (mtVal1, mtVal2, mtVal3);

I tipi SubrangeCome dice il nome stesso, questi tipi identificano dei sottoinsiemi di valori appartenenti ad un altro tipo ordinale che viene definito tipo base. Per definire un tipo subrange, si utilizza la seguente sintassi Type SubrangeTypeName = Low..High; dove Low ed High appartengono allo stesso tipo ordinal e Low minore di High. Questo costrutto definisce quel sottoinsieme di valori compresi tra Low ed High. Per esempio

Type

PrimiDieciNumeri = 1..10;

definisce un tipo subrange di nome PrimiDieciNumeri che conterr i valori 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. Non valgono per questo tipo gli sconfinamenti visti per i tipi precedenti.LEZIONE 15:

I tipi (parte seconda)

I tipi realI tipi real definiscono insiemi di numeri che possono essere rappresentati con la notazione in virgola mobile. I tipi real fondamentali sono riportati di seguitoTipo Intervallo Cifre Dimensione significative in byte 11-12 7-8 15-16 19-20 19-20 19-20 6 4 8 10 8 8

Real48 2.9 x 10-39..1.7 x 1038 Single 1.5 x 10-45..3.4 x 1038 Double 5.0 x 10-45..1.7 x 10308 Extended 3.6 x 10-4951..1.1 x 104932 Comp -263 + 1..263 - 1 -922337203685477.5808.. Currency 922337203685477.5807

Il tipo real generico equivale al double. Seguono alcune considerazioni sui tipi real fondamentali Il tipo Real48 viene mantenuto per compatibilit con il tipo real delle versioni precedenti di Object Pascal. Non essendo un tipo che utilizza un formato di memorizzazione non nativo per le CPU intel determina prestazioni pi lente. Extended il tipo real che permette maggiore precisione ma a sua volta meno portabile. Il tipo Comp (computazionale) nativo per le CPU Intel e rappresenta un integer a 64 bit. Pur essendo un tipo integer viene classificato come real in quanto non si comporta come tipo ordinal; non infatti possibile incrementare o decrementare un valore comp. Viene mantenuto per compatibilit con le versioni precedenti. Al suo posto si consiglia l'uso del tipo Int64. Currency un tipo di dati che viene utilizzato per i calcoli valutari poich ne riduce al minimo gli errori di arrotondamento. caratterizzato da punto decimale fisso e viene memorizzato come un integer a 64 bit scalato, con le ultime quattro cifre meno significative che rappresentano i decimali. Valori di questo tipo vengono automaticamente moltiplicati o divisi per 10000 quando vengono usati in espressioni con altri tipi real.

I tipi StringL'Object Pascal possiede, a differenza di altri linguaggi come ad esempio il C ed il C++, tipi di dati dedicato alla gestione dell stringhe. I tipi string supportati dall'Object Pascal sono i seguentiTipo Lunghezza massima Memoria richiesta da 2 a 256 byte da 4 byte a 2GB da 4 byte a 2GB Usato per compatibilit con versioni precedenti caratteri a 8 bit (ANSI) caratteri UNICODE; server e interfacce COM

ShortString 255 caratteri AnsiString ~231 caratteri WideString ~230 caratteri

AnsiString il tipo preferito per la maggior parte della applicazioni. A volte viene anche chiamato LongString.

I tipi string possono essere mischiati nelle assegnazioni e nelle espressioni in quanto il compilatore effettua automaticamente le conversioni del caso. Bisogna invece fare attenzione nel passaggio di parametri alle funzioni ed alle procedure che deve rispettare il tipo dei parametri dichiarati insieme alla funzione o procedura. Il tipo generico per il tipo string string. Non si tratta proprio di un tipo ma di una parola chiave del linguaggio che identifica un tipo di dati contenete una stringa. Come stato predefinito la parola chiave string si riferisce al tipo AnsiString (se non seguita da un numero fra parentesi quadre). possibile cambiare string in ShortString tramite la direttiva del compilatore {$H-}. Anche per il tipo string esistono funzioni predefinite come Length che restituisce la lunghezza in caratteri di una stringa e SetLength che ne regola la lunghezza. Due variabili di tipo string possono essere confrontate tramite gli operatori relazionali. In tal caso il confronto avviene confrontando l'ordinalit dei caratteri che occupano la stessa posizione. Ad esempio la stringa "AB" risulter minore di "AC". Confrontando stringhe di differente lunghezza, la dove i caratteri della stringa pi lunga non hanno corrispondenza nella stringa pi corta, vengono considerati maggiori. Di conseguenza la stringa "AB" risulter maggiore della stringa "A". Una variabile string pu essere indicizzata come se si trattasse di un array. I tal caso possibile accedere i caratteri di una stringa utilizzando la seguente sintassi. S[i] dove S una variabile di tipo string e i un intero indicante la posizione all'interno della stringa S. Per cui, S[2] := 'A' assegna alla posizione 2 della stringa S il carattere 'A'. Molta attenzione va fatta nella manipolazione delle stringhe tramite la tecnica vista in precedenza in quanto, in presenza di stringhe di tipo AnsiString o WideString che in realt rappresentano stringhe terminate con null, la sovrascrittura dell'ultimo carattere (il null appunto) potrebbe causare un errore di violazione di accesso.

I tipi Short StringCome visto nella tabella dei tipi string, il tipo ShortString pu essere lungo da 0 a 255 caratteri. Mentre la sua lunghezza varia dinamicamente, la memoria che occupa viene allocata staticamente e corrisponde a 256 byte; all'interno del primo byte riportata la lunghezza in caratteri della stringa. Ne consegue che per ottenere la lunghezza di una stringa ShortString possibile leggere il valore ordinale del carattere presente alla posizione 0 secondo la rappresentazione ad array. L'operazione Ord(S[0]) equivalente a Length(S) dove S una variabile string. L'Object Pascal supporta anche dei sottotipi di ShortString la cui lunghezza varia da 0 a 255. Questi tipi vengono definiti specificando un numerale tra parentesi quadre dopo la parola chiave string. Per esempioType

String50 = String[50];

definisce un tipo String50 la cui lunghezza massima di 50 caratteri. Questo tipo di dichiarazione permette di risparmiare spazio in memoria poich per contenere un variabile del tipo String50 verranno allocati solamente 51 byte a differenza dei 256 del tipo base ShortString.

I tipi Long String (AnsiString)Come accennato in precedenza il tipo AnsiString viene anche definito LongString. Il tipo AnsiString rappresenta una stringa allocata dinamicamente la cui lunghezza massima limitata solamente dalla memoria disponibile. Una variabile di questo tipo non altro che un puntatore che occupa 4 byte. Il sistema utilizzato, totalmente gestito in maniera invisibile all'utente, simile ad una lista di caratteri. Ci permette appunto di avere una lunghezza dipendente solamente dalla memoria disponibile nel sistema. Un'altra caratteristica di questo tipo che, trattandosi di puntatori, due o pi variabili di questo tipo possono far riferimento allo stesso valore senza spreco aggiuntivo di memoria.

I tipi Wide String

L'allocazione di variabili di questo tipo il medesimo di quello per variabili di tipo AnsiString con la differenza che le stringhe rappresentate utilizzano caratteri UNICODE a 16 bit. Si differenzia solamente per efficienza che risulta minore in quanto non utilizza accorgimenti come il contatore dei riferimenti utilizzato invece dal tipo AnsiString. Questo tipo utilizzato prevalentemente per la compatibilit con i tipi nelle funzionalit COM.

I tipi strutturatiFanno parte di questa categoria di tipi i Set, gli Array, i Record, i file oltre alle classi ed alle interfacce. Una istanza di tipo strutturato raccoglie sotto di se pi valori. I tipi Set possono a loro volta contenere valori di tipo strutturato eccezion fatta per il tipo Set che pu contenere solamente valori di tipo ordinale.

SetIl tipo set implementa quello che in matematica viene definito insieme. Un set pu contenere solamente valori dello stesso tipo ordinale senza seguire alcun ordinamento intrinseco. Altres non ha significato che un elemento sia inserito due volte in un Set. L'intervallo di validit dei valori di un tipo Set dipende dall'intervallo di validit del tipo ordinal utilizzato per creare il Set. Questo tipo ordinale che origina il Set viene chiamato tipo base. Il costrutto utilizzato per dichiarare un tipo Set il seguenteSet of

TipoBase

Esempi di dichiarazione di tipi Set sono i seguenti:Type

TChars = 'A'..'Z'; TSetOfChars =Set of

TChars;

Per assegnare dei valori a varibili di tipo Set, facendo riferimento all'esempio precedente, si procede come segue: Var Caratteri : TSetOfChars; ... Caratteri := ['A', 'F', 'B', 'T', 'X']; Con analogia alla matematica ed agl'insiemi, un tipo Set pu essere vuoto e viene rappresentato con [].

ArrayGli array rappresentano una raccolta indicizzata di elementi tutti appartenenti ad uno stesso tipo che, come per i tipi Set, prende il nome di Tipo Base. A differenza dei tipi Set, un array pu contenere, proprio perch indicizzato, pi volte lo stesso valore. I tipi base utilizzabili nella dichiarazione di array, possono essere qualsiasi dai tipi ordinal ai tipi string, puntatori, altri array etc. Gli array possono essere dichiarati staticamente o dinamicamente ed essere mono o multi dimensionali. Un array monodimensionale rappresenta un vettore di elementi, mentre array multidimensionali rappresentano matrici di elementi.

Array staticiIl costrutto che si utilizza per dichiarare array statici il seguente array [TipoIndice1, ..., TipoIndicen] of TipoBase; Il numero di elementi che pu contenere un array cos definito dato dal prodotto delle dimensioni dei TipoIndice racchiusi tra parentesi quadre.

Gli array monodimensionali o vettori, hanno un solo TipoIndice come in questo esempioType

TVettore100 =

Array

[1..100]

of

Integer;

In questo esempio stato definito un vettore che pu contenere al massimo 100 valori integer. Per accedere ai valori di una variabile array come sopra dichiarata si utilizza la sintassi MioVettore[50] dove MioVettore il nome della variabile di tipo TVettore100 e 50 l'indice dell'elemento 50 all'interno dell'array. Quando si definisce una variabile di tipo array e non si assegnano valori a tutti gli elementi, gli elementi non assegnati vengono comunque allocati e conterranno valori non definiti. Si possono anche dichiarare array multidimensionali come di seguitoType

TMatrice10X10 =

Array

[1..10, 1..10]

of Integer;

In questo caso stato dichiarato un tipo TMatrice10X10 composto da 10 righe e 10 colonne. La dichiarazione precedente equivale a dichiarare un tipo array di array come di seguitoType

TMatrice10X10 =

Array

[1..10]

of Array

[1..10]

of Integer;

Per accedere i valori di una variabile dichiarata come TMatrice10X10 si procede in maniera simile agli array monodimensionali tranne per il fatto che, essendo questi a pi dimensioni, bisogna indicare un indice per ognuna delle dimensioni dell'array. Nel caso dell'esempio precedente MiaMatrice[2, 3], dove la variabile MiaMatrice di tipo TMatrice10X10, acceder al valore contenuto alla riga 2 colonna 3 della matrice. In Object Pascal sono definite funzioni per operare con gli indici e le dimensioni degli array statici. Con Low e High si ottiene rispettivamente il limite inferiore e quello superiore del primo tipo dell'array. Con Length si ottiene il numero di elementi nella prima dimensione dell'array.

Array dinamiciA differenza degli array statici, gli array dinamici non hanno dimensioni e lunghezza fisse e quindi la memoria viene riallocata quando si assegna un valore all'array o quando si utilizza la funzione SetLength per impostarne le dimensioni. Per dichiarare deigli array dinamici si utilizza il costrutto Type NomeTipo = Array of TipoBase; Quando si dichara un array dinamico questo non occupa memoria fino a quando non si effettua una chiamata alla funzione SetLength. Per esempio, se stata dichiarata una variabile MioArray di tipo TMioArray = Array of Integer per creare effettivamente l'array in memoria effettuando la chiamata SetLength(MioArray, 100), si allocher memoria per un array di 100 elementi integer. Da ricordare che l'indicizzazione degli array dinamici si basa sempre su integer e comincia da 0. In pratica gli array dinamici sono puntatori similmente ai LongString. Per disallocare un array dinamico, possibile assegnare alla variabile che lo referenzi il valore Nil oppure passare la variabile stessa alla funzione Finalize; questo verr disallocato solamente nel caso in cui non siano presenti altri riferimenti ad esso. Array di lunghezza 0 assumono il valore Nil. Anche per gli array dinamici sono disponibili le funzioni standard Length, Low ed High. Queste restituiscono rispettivamente il numero di elementi dell'array, 0 in ogni caso, e l'indice superiore dell'array. Nel caso di array vuoti High restituisce -1. Interessante notare che si avr in questo caso High < Low (-1 < 0).

RecordPer fare subito un confronto con altri linguaggi, tra cui C e C++, questo tipo corrisponde ai tipi struct (Struttura). Esso rappresenta un insieme di elementi eterogenei fra loro, ovvero un tipo record pu raggruppare

in se tipi diversi di elementi. Gli elementi di un record vengono detti campi; nella dichiarazione di un tipo record occorre specificare un nome per il