CORSO DI PROGRAMMAZIONE DELPHI
←
→
Trascrizione del contenuto della pagina
Se il tuo browser non visualizza correttamente la pagina, ti preghiamo di leggere il contenuto della pagina quaggiù
CORSO DI PROGRAMMAZIONE DELPHI Benvenuti nel mio interessantissimo corso dedicato a tutti coloro che non hanno MAI avuto a che fare con variabili, cicli o linguaggi. Chi già possiede diverse basi nella programmazione troverà questi primi capitoli superflui, tuttavia invito ad attendere i futuri sviluppi, o di leggere la parte relativa ai Tips & Tricks! Qualsiasi suggerimento per il miglioramento di questo corso è ben accetto... Al fine della completa trattazione è necessario: • Una copia di Delphi (possibilmente versione 2 o successiva) • File Help di Delphi Introduzione Questo testo nasce come risposta ad una delle più frequenti domande poste nell’ambito informatico: come si costruisce un programma. Molti sono affascinati dall’intrigante arte della codifica ma, o per mancanza di tempo, o per scarsità di volontà, non affrontano il grande passo della stesura di un programma. Molti si chiedono, giustamente, l’utilità di saper scrivere codice in un’era in cui ci troviamo di fronte a prodotti già pronti e in cui ogni tipo di software immaginabile è già stato scritto da qualcuno; la risposta non è così semplice, la programmazione è un’arte, per alcuni è considerata alla stregua di un hobby, e per altri è un lavoro, chi non ha mai provato l’ebbrezza della stesura di una utility innovativa non può in ogni caso capire... Ma questo testo nasce appunto per questo, il poter apprendere la programmazione da zero. Si deve innanzi tutto notare che il linguaggio scelto è stato il Pascal, perché è forse quello che offre miglior rapporto tra prestazioni e difficoltà, tuttavia anche il Visual Basic, specie con l’avvento delle nuove versioni potrebbe divenire un ottimo strumento, ma ora come ora, il Pascal si colloca ancora un gradino sopra di detto tool, specie con l’avvento del Delphi; non è comunque da escludere anche il C++ Builder, il “cugino” di Delphi. Disclaimer Questo corso è stato creato interamente da Vanni Brutto (asytnt@tin.it). Potete trovarne una versione online all'indirizzo http://www.geocities.com/SiliconValley/Lab/6806/. I files che troverete nello zippato 'corso.zip' sono protetti dal diritto d'autore e sono liberamente riproducibili a condizione di non farne uso commerciale o economico o per fine di lucro senza la preventiva autorizzazione dell'autore. In ogni caso deve sempre essere indicato il nome dell'autore e il suo indirizzo. Ogni altra modalità di utilizzo deve considerarsi contraria alla volontà dell'Autore. Inoltre, l'Autore non si riterrà responsabile per danni di qualsiasi genere, diretti o indiretti, causati dall'utilizzo dei suddetti files. LI USATE A VOSTRO RISCHIO. Nota dell'impaginatore :) (idr@mail.xoom.it) Ciao! Sono Francesco e questa che state leggendo è la versione riveduta e corretta (nella forma, non nei contenuti) del corso sul Delphi di Vanni Brutto. Per farla ho chiesto e ottenuto l'autorizzazione di Vanni. Se volete mettere questi files sul vostro sito, gradirei che me lo comunicaste e che metteste anche un link al mio sito e a quello di Vanni, dato che ci è costato tempo e fatica ;). L'indirizzo del mio sito è http://gpi.eden.it/idr (The Italian Delphi Repository), mentre quello di Vanni lo trovate un po' più su. Ciao e grazie per la collaborazione! 1
Prima parte: breve introduzione al Turbo Pascal (sintassi e strutture) Capitolo 1 Un po’ di storia Il Pascal è un linguaggio ad alto livello, che tenta in pratica di avvicinarsi per quanto possibile al ragionamento umano. Esempi di linguaggi ad alto livello sono C, C++, Basic, Basic strutturato, Cobol e Fortran; una delle caratteristiche che differenzia il Pascal da alcuni dei suddetti linguaggi è la possibilità di scrivere codice a basso livello, in altre parole righe di programmazione che vengono scritte nel linguaggio della CPU. Il Pascal nasce per merito di N. Wirth che per primo introdusse la sintassi Pascal, in seguito nel 1970 l’uso del Pascal si estese nell’ambito universitario e scientifico, ma si deve scorrere all’incirca fino agli anni ‘80 per arrivare al primo compilatore1 di Turbo Pascal scritto da Anders Hejlsberg. I programmatori Pascal hanno apprezzato attraverso gli anni l’eleganza, nonché la velocità e la stabilità offerta da questo compilatore. Il Turbo Pascal rappresentò per l’epoca la giusta via di mezzo tra l’efficiente ma complesso Assembly2 e altri linguaggi ad alto livello (basic soprattutto), ma non con tali prestazioni. Negli anni il T.P. si evolse, di versione in versione, fino all’eccezionale versione 7.0 (includente anche Turbo Vision 2.0), completamente orientato agli oggetti, e tutt’oggi uno dei migliori pacchetti per la scrittura di software gestionali per DOS. Con l’avvento del Windows, la Borland rilasciò la prima versione di Borland Pascal, un pacchetto basato sul linguaggio Object Pascal, naturale evoluzione del Turbo Pascal; tuttavia la stesura di applicazioni Windows in Object Pascal era alquanto lenta e complessa, il programmatore doveva avere ottime conoscenze di T.P., nonché delle OWL3 e le immancabili API4 del Windows. Per questo la Borland rilasciò nel mercato Delphi e successivamente Delphi 2.0, la versione riveduta e corretta a 32-bit del primo. Delphi introdusse il concetto di programmazione Visuale e orientata agli eventi tipica del Visual Basic, ma senza trascurare i vantaggi della compilazione Pascal. Nel corso del ‘97 la Borland ha creato pure un ambiente di tipo R.A.D. per il C++ (C++ Builder) molto simile al Delphi; attualmente siamo giunti alla versione 3.0 di Delphi, e sicuramente il futuro riserverà altre sorprese, tuttavia voglio fare notare che il codice scritto in Delphi è conferme all’Object Pascal, di cui ha ereditato pure il numero delle versione, la versione 8.0 fu, infatti, del Delphi 1.0 e la successiva 9.0 del Delphi 2.0. Il primo programma in Turbo Pascal. Si noti che in questo corso si inizierà usando la programmazione tipica del Turbo Pascal per passare, poi, a quella Delphi. Questo è fatto volutamente per dare la possibilità anche a coloro che non conoscono nulla di programmazione a capire il funzionamento di detto compilatore. Da quando Brian Kernighan e Dennis Richie hanno realizzato nel 1978 il linguaggio di programmazione C, il tradizionale primo programma è stato quello di visualizzare Hello World! (Ciao gente!) sullo schermo. Chi se la sente di interrompere questa tradizione? 1. Avviare Delphi 2. Scegliere close all dal menu file e chiudere tutti i files eventualmente aperti 3. Dal menu file scegliere new e quindi Text 4. Salvare il file come Hello.dpr (Delphi Project (*.dpr)) 5. Scrivere il programma in turbo pascal facendolo precedere dalla seguente riga: {$APPTYPE CONSOLE} 2
{$APPTYPE CONSOLE} {Hello World! App, tutto quello che è tra parentesi graffe non viene letto dal compilatore} Program Hello; {Program va seguito dal nome del file del programma} Uses Forms; Begin {Inizio del programma} WriteLn(‘Hello World’); {WriteLn si usa per scrivere sul video} ReadLn;{ReadLn si usa per leggere da tastiera} End. {Fine del programma} Se vi siete ripresi dal trauma causato dall’avvio di una finestra DOS possiamo continuare con qualcosa di più... semplice... Creare un programma come segue: {$APPTYPE CONSOLE} Program Prova; Uses Forms; Begin End. Il file andrà poi salvato con il nome prova ed estensione dpr. La parola riservata Begin indica l’inizio del programma e deve corrispondere con un seguente End; si dovrà ricordare fin dora che in Pascal i blocchi di codice andranno definiti sempre tramite un Begin e un End. Si provi ora ad eseguire il programma tramite la voce Run del menu Run... Passata la compilazione non accadrà un bel niente, questo perché questo programma non fa assolutamente nulla! L’importante è osservare che ogni programma deve iniziare con la riga Program contente il nome del file da salvare e si dovrà SEMPRE aggiungere la riga iniziale {$APPTYPE CONSOLE} per indicare a Delphi che si sta lavorando in modalità DOS, inoltre si dovrà sempre aggiungere la riga Uses Forms, è inutile al file dell’esecuzione, ma serve per caricare il file. Miglioramenti del primo programma Si modificherà ora il primo programma creato in precedenza come segue: {$APPTYPE CONSOLE} {Questo è il secondo programma, tutto quello che è tra parentesi graffe non viene letto dal compilatore} Program P2; {Program va seguito dal nome del file del programma} Begin {Inizio del programma} WriteLn(‘PROGRAMMA P2’); {WriteLn si usa per scrivere sul video} WriteLn(‘Questo è semplicemente il mio secondo programma’); WriteLn; WriteLn(‘Premere INVIO per terminare il programma’); ReadLn;{ReadLn si usa per leggere da tastiera} End. {Fine del programma} 3
Questo programma è visivamente più complesso del primo, ma nella realtà non è nulla di particolarmente difficile, ogni programma per Turbo Pascal dovrebbe cominciare con Program seguito dal nome del file, il carattere di punto e virgola finale non è messo a caso, ogni riga di Turbo Pascal dovrebbe finire con un carattere tale, tranne poche eccezioni (tra le quali Begin e End); l’istruzione WriteLn scrive la stringa1 contenuta tra gli apici, WriteLn è un metodo e va quindi seguito dall’apertura e la chiusura di parentesi rotonde. Provate ora a modificare il programma aggiungendo altre frasi o ricopiando più volte alcune istruzioni per vedere l’effetto creato. TIP Nota per gli utilizzatori di Delphi: è possibile eseguire programmi scritti per Turbo Pascal anche in Delphi, si dovrà però seguire la seguente procedura 1. Avviare Delphi 2. Scegliere close all dal menu file e chiudere tutti i files eventualmente aperti 3. Dal menu file scegliere new e quindi Text 4. Salvare il file come Delphi Project (*.dpr) 5. Scrivere il programma in turbo pascal facendolo precedere dalla seguente riga: {$APPTYPE CONSOLE} Si esamini ora il seguente programma: {$APPTYPE CONSOLE} Program P3; Begin WriteLn(‘PROGRAMMA P2’); {WriteLn si usa per scrivere sul video} Begin WriteLn(‘Questo è semplicemente il mio secondo programma’); WriteLn(‘’); End; WriteLn(‘Premere INVIO per terminare il programma’); ReadLn; End. Il programma P3 svolge le stesse funzioni di P2, l’unica differenza risiede nel fatto che il secondo WriteLn è preceduto da un Begin, questo perché si è voluto creare un nuovo blocco di programma. Si osservi inoltre che il terzo WriteLn è stato sostituito da WriteLn(‘’), nella realtà le due righe di codice sono equivalenti(!). 4
Capitolo 2 Le variabili e i calcoli matematici Presentazione Per determinare il volume di una barra cilindrica, dobbiamo conoscere la superficie della sezione, e moltiplicarla per la lunghezza. Osservate il disegno: superficie della sezione = 3,14159xRxR volume della barra=superficie della sezione x L = 3,14159xRxRxL Vediamo come il volume di una barra dipenda in generale da due grandezze: il raggio R e la lunghezza L. Il programma seguente calcola il volume di una area cilindrica ma questa volta con i valori: L=5 R=7 Il programma: {$APPTYPE CONSOLE} Program Volume; Const Pgreco = 3.1415926535897932385; Var R, L, Sup : Real; V : Integer; begin L:= 5; R:= 7; Sup:= PGreco*R*R; V:= Round(Sup*L); WriteLn(V); ReadLn; end. Andiamo ad osservare riga per riga. Nella prima riga si legge: Program Volume; Questa riga serve ad indicare al compilatore che il programma risiede nel file Volume.dpr Successivamente si trova la parola riservata Const, questa è seguita dal nome di una costante che viene inizializzata per un certo valore e cioè il numero corrispondente al Pi. La parola riservata Var serve invece ad indicare la dichiarazione di variabili, questa serve ad indicare al compilatore di assegnare un "pezzettino" di memoria per l’inserimento di tre variabili numeriche con la virgola (Real) ed una variabile numerica intera (Integer). Successivamente nel blocco Begin End troviamo l’assegnazione di 5 per la variabile L e di 7 per la variabile R, l’assegnazione di un valore ad una variabile avviene sempre tramite l’operatore := Con Sup:= PGreco*R*R si indica al compilatore di moltiplicare Pgreco per il quadrato del raggio e assegnare il valore alla variabile Sup. Infine con V:= Round(Sup*L) si indica di moltiplicare la superficie per l’altezza, arrotondare il risultato, e assegnarlo alla variabile V che viene successivamente passata alla funzione WriteLn dove verrà scritta sullo schermo. Ora si vedrà lo stesso programma riprodotto in maniera leggermente diversa: 5
{$APPTYPE CONSOLE} Program Area; Const Pgreco = 3.1415926535897932385; Var R, L, V: Real; begin L:= 5; R:= 7; V:= PGreco*R*R*L; WriteLn(V:0:0); ReadLn; end. Come si può notare il programma è stato reso leggermente meno leggibile, tuttavia il risultato sarà uguale, l’unica sostanziale differenza sta nel fatto che la variabile V è divenuta di tipo real e che per essere scritta tramite WriteLn in maniera decimale si è dovuto ricorrere al suffisso :0:0, non è importante capire cosa serva tale suffisso, l’importante è capire che per scrivere un numero Real tramite WriteLn si dovrà ricorrere ad esso! Non preoccupativi per la difficoltà di programmazione in DOS, appena conoscerete queste semplici basi la programmazione in Windows sarà uno scherzo! 6
Capitolo 3 WriteLn, Write e ReadLn: questi sconosciuti WriteLn e Write La prima istruzione che descriveremo sarà l’istruzione WriteLn, questa istruzione scrive sul video e riporta il cursore a capo, la differenza tra Write è abbastanza evidente, Write non riporta il cursore a inizio riga. ReadLn ReadLn legge un valore dalla periferica standard, di solito dalla tastiera, così l’istruzione ReadLn(Prova), dove prova è una variabile dichiarata stringa, leggerà una frase da tastiera. Con questi piccoli apprendimenti si potrà migliorare il programma del secondo capitolo in modo sostanziale: {$APPTYPE CONSOLE} Program Area; Const Pgreco = 3.1415926535897932385; Var R, L, V : Real; begin WriteLn; WriteLn; WriteLn; WriteLn; WriteLn; WriteLn; WriteLn; WriteLn ('CALCOLO DEL VOLUME DI UN CILINDRO); WriteLn; Write('Inserire la lunghezza del cilindro ->'); ReadLn(L); Write('Inserire il raggio del cilindro ->'); ReadLn(R); V:= PGreco*R*R*L; WriteLn; WriteLn; WriteLn('Il volume del cilindro è: ', V:0:0); WriteLn; WriteLn('premere INVIO per continuare'); ReadLn; end. Il programma in questione è un notevole passo avanti, si può infatti calcolare il volume di un qualsiasi cilindro! 7
Capitolo 4 Tipi di variabili Nella programmazione Pascal si dovrà imparare le sottili differenze che esistono tra le variabili numeriche, qui di seguito riporto un estratto della guida ufficiale di Delphi: Qui di seguito vengono elencati i tipi interi, che non accettano cioè la virgola. Type Range Format Integer -32768..32767 Signed 16-bit Cardinal 0..2147483647 Unsigned 32-bit Shortint -128..127 Signed 8-bit Smallint -32768..32767 Signed 16-bit Longint -2147483648..2147483647 Signed 32-bit Byte 0..255 Unsigned 8-bit Word 0..65535 Unsigned 16-bit Qui di seguito vengono elencati i tipi reali, che ovviamente possono essere utilizzati come interi, tuttavia sono molto più lenti (non più di tanto tuttavia). Type Range Significant digits Size in bytes Real 2.9 x 10-39 .. 1.7 x 1038 11-12 6 Single 1.5 x 10-45 .. 3.4 x 1038 7-8 4 Double 5.0 x 10-324 .. 1.7 x 10308 15-16 8 Extended 3.4 x 10-4932 .. 1.1 x 104932 19-20 10 Comp -263+1 .. 263 -1 19-20 8 Currency -922337203685477.5808.. 922337203685477.5807 19-20 8 Per dichiarare una variabile ricordo che si deve utilizzare la dicitura Var nome_variabile: tipo; ad esempio Var Var1,Var2, Var3 : Integer; R1, R2, R3 : Real; Le Stringhe: giochiamo con le lettere Un tipo particolare che merita una trattazione a parte sono le stringhe: dovete pensare ad una stringa come una linea di un quaderno nella quale potete immettere testo, numeri nonché caratteri come linee apostrofi etc. Il compilatore considererà stringa tutto ciò che trova tra due apici, ad esempio 8
quando è stato mostrata la sintassi di WriteLn si è detto che il testo andava immesso tra due apici, questo perché altro non era che una stringa! L'esempio che segue chiarisce l'utilizzo delle stringhe. {$APPTYPE CONSOLE} Program Stringhe; Uses Forms; Var Nome: String; Begin Write('Inserisci il tuo nome: '); ReadLn(Nome); WriteLn; WriteLn; Write('Benvenuto '); Write(Nome); WriteLn(' nel fantastico mondo della programmazione Pascal'); Nome:= Nome + ' premi invio per continuare'; WriteLn(Nome); ReadLn; End. Il programma non è poi niente di così complesso: si limita a chiedere una stringa e rivisualizzarla successivamente, appare più interessante l'uso di Nome:= Nome + ' premi invio per continuare', questa istruzione altro non fa che accodare al nome precedentemente immesso un altro pezzo di stringa. Si descriveranno qui di seguito alcuni metodi usati frequentemente con le stringhe: AnsiUpperCase AnsiUpperCase serve per rendere maiuscola una stringa, l'esempio che segue chiarirà meglio l'utilizzo: {$APPTYPE CONSOLE} Program Stringhe; Uses SysUtils; Var S: String; Begin Write('Inserisci una stringa: '); ReadLn(S); WriteLn; WriteLn; WriteLn(AnsiUpperCase(S) + ' questa stringa è stata passata a maiuscola'); WriteLn('premi invio'); ReadLn; End. La prima volta che si guarda il listato si potrebbe essere messi in crisi dalla sostituzione di Uses Forms con Uses SysUtils, nella realtà questo avviene in quanto la funzione AnsiUpperCase è dichiarata nella unit SysUtils, ad ogni modo verrà chiarito questo concetto nel Capitolo 7, questo non deve assolutamente spaventarvi! 9
INTtoSTR e STRtoINT Questi due metodi servono per passare da stringhe a interi e viceversa: ad esempio avendo una variabile I contenente un dato numero che deve essere trasferito nella stringa S si dovrà eseguire la seguente riga di codice: S:= INTtoSTR(I); Il che tradotto in linguaggio parlato starebbe né più né meno a: -trasforma l'intero I in stringa e memorizza il risultato nella variabile S. Viceversa STRtoINT provvede all'operazione inversa, volete magari un esempio? Questo è compito vostro! Non preoccupativi a capire tutto quanto esposto in questo capitolo in special modo le tabelle ad inizio capitolo, vi basti sapere che se volete fare una divisione dovrete utilizzare un Real, se lavorate su operazioni intere l'integer è d'obbligo. Inoltre si noti che le istruzioni INTtoSTR e STRtoINT non lavorano con i numeri con la virgola. Ora rilassatevi, rileggete i capitoli precedenti e soprattutto provate a creare piccoli programmi VOSTRI utilizzando magari le stringhe, d'ora in avanti la strada sarà in salita. 10
Capitolo 5 Le istruzioni di controllo IF ... THEN La più semplice formulazione IF...THEN è la seguente: if condizione then begin //Se la condizione è vera allora... istruzione; //Esegui istruzioni... istruzione; istruzione; End Else Begin //Se la condizione precedentemente esposta era falsa allora istruzione; //Esegui istruzioni istruzione; istruzione; end; Quanto appena esposto va imparato come la tabellina del 2! La maniera migliore per capire il costrutto IF...THEN è con un esempio: {$APPTYPE CONSOLE} Program Tre; Uses Forms; Var K: Integer; Begin Write('Inserisci un numero: '); ReadLn(K); If K= 3 Then Begin WriteLn('Il numero era tre'); End Else Begin WriteLn('Sicuramente non hai premuto il tre, bensì un altro numero'); End; ReadLn; End. Il programma chiede un numero e se questo è tre visualizza la scritta il numero era tre. A scanso di equivoci desidero farvi notare che anche la struttura del tipo If K= 3 Then WriteLn('Il numero era tre'); Else WriteLn('Sicuramente non hai premuto il tre, bensì un altro numero'); Sarebbe stata sintatticamente corretta ma è fortemente sconsigliata, la motivazione è quanto mai ovvia: se necessitate di includere più azioni dopo il then queste andranno incluse in un blocco begin 11
end in quanto l'allora della conclusione considera solo l'istruzione che segue. Rileggendo quanto precede mi accorgo che non sono stato assolutamente chiaro, ad ogni modo limitatevi ad utilizzare il costrutto come spiegato, eventualmente eliminate anche l'else se è inutile! Si noti infine che gli operatori IF...THEN lavorano anche con le stringhe, provate il codice che segue: {$APPTYPE CONSOLE} Program Vanni; Uses Forms; Var S: String; Begin Write('Inserisci il tuo nome: '); ReadLn(S); If S = 'Vanni' Then WriteLn('Salve a te grande coder'); ReadLn; End. Inoltre si potranno usare anche i seguenti operatori logici oltre al segno = cioè (diverso) < (minore) > (maggiore), ad esempio 'Abc' > 'Def' sarà falso in quanto in ordine alfabetico 'abc' precede 'def'! Con il prossimo capitolo si introdurranno i concetti di routine, e unit compilata quindi si passerà alla programmazione Windows per trattare i cicli e gli eventi (enjoy). 12
Capitolo 6 LE ROUTINES PROCEDURE Una subroutine è una parte di programma che può essere richiamata da un punto qualsiasi del codice. Il salto alle subroutine si verifica tramite il nome della subroutine stessa. Al termine della subroutine l'esecuzione ritornerà al ciclo principale. Lo schema seguente chiarirà meglio la situazione: Come prassi di questo corso segue un esempio chiarificatore! {$APPTYPE CONSOLE} Program esempio; Uses Forms; Procedure INVIO; begin WriteLn('Premi INVIO per continuare'); ReadLn; end; begin WriteLn('Riga numero uno'); WriteLn('Riga numero due'); WriteLn; INVIO; WriteLn('il programma prosegue dopo l''invio'); WriteLn; WriteLn; INVIO; End. 13
Il programma inizia scrivendo due righe dal corpo principale, quindi l'esecuzione passa alla subroutine INVIO per poi continuare nel body... Qui di seguito verrà presentato un esempio un po' più complesso che implementa il concetto di parametro che sarà meglio introdurre: il parametro consiste in una variabile passata ad una procedura che sarà elaborata da lei stessa, ad esempio nel vecchissimo basic msx (da cui provengo) esisteva una funzione input la cui sintassi era come segue: Input(Stringa, Variabile) Nell'esempio che segue si ricreerà una routine simile! {$APPTYPE CONSOLE} Program esempio; Uses Forms; var K: Integer; Procedure Input(S: String; var I: Integer); begin Write(S); ReadLn(I); end; begin Input('Inserisci un numero: ', K); WriteLn(K); Input('Inserisci un numero: ', K); WriteLn(K); Input('Inserisci un numero: ', K); WriteLn(K); ReadLn; End. I parametri preceduti da Var sono chiamati parametri passati per indirizzo o parametri- variabile, quelli non preceduti da Var parametri per valore o parametri-valore. La differenza sta nel fatto che le variabili passate a variabili cambiano anche il valore della variabile, in altre parole rimovendo il var dalla procedura input il programma non funzionerà in quanto la variabile I della procedura input sarà una copia di K e non K stessa. Ripetendo il concetto le variabili passate per indirizzo diventano a tutti gli effetti le variabili locali, in breve il parametro passato per indirizzo e la variabile passata alla procedura sono la stessa cosa, cioè condividono la stessa locazione di memoria. Di conseguenza ogni modifica del parametro passato per indirizzo è in realtà una modifica della variabile stessa. Al contrario il parametro S che viene passato per valore non verrà alterato in alcun modo. Ad esempio provate ad eseguire il seguente codice: {$APPTYPE CONSOLE} Program esempio; Uses Forms; var K: Integer; 14
Procedure Prova1(I: Integer); begin WriteLn('siamo all''interno di prova1 e la variabile sta per essere impostata a 34'); I:= 34; end; Procedure Prova2(var I: Integer); begin WriteLn('siamo all''interno di prova2 e la variabile sta per essere impostata a 56'); I:= 56; end; begin K:= 0; WriteLn('K corrisponde a ', K); WriteLn('ora verrà chiamata la routine prova1'); Prova1(K); WriteLn('K corrisponde ora a ', K); WriteLn('infine verrà chiamata la routine prova2'); Prova2(K); WriteLn('K corrisponde ora a ', K); ReadLn; End. Il risultato dell'esecuzione del codice sarà il seguente 1. K corrisponde a 0 2. ora verrà chiamata la routine prova1 3. siamo all'interno di prova1 e la variabile sta per essere impostata a 34 4. K corrisponde ora a 0 5. infine verrà chiamata la routine prova2 6. siamo all'interno di prova2 e la variabile sta per essere impostata a 56 7. K corrisponde ora a 56 Si noti che anche se K viene alterato nella procedura prova1 al ritorno il valore assunto da esso non sarà cambiato, questo perché in realtà era stato variato solo il valore di una copia di K, non K stesso! Spero di essere stato abbastanza chiaro, d'altronde la programmazione a subroutine (comunemente detta strutturata). Come sempre consiglio di provare quanto appreso, il prossimo capitolo sarà piuttosto breve in quanto tra poco si passerà alla programmazione Windows. 15
Capitolo 7 Utilizzo delle unit Delphi viene fornito con diverse unit standard. Una di queste, la System unit, viene utilizzata automaticamente durante la compilazione del programma. Se fosse necessario accedere alla dichiarazione o al sottoprogramma di un'altra unit standard, è indispensabile inserire una clausola uses, che è semplicemente un elenco delle unit da ricercare durante la fase di compilazione. Dal punto di vista sintattico, la clausola uses fa parte dell'intestazione del programma e deve essere inserita prima di ogni dichiarazione. L'intestazione Program NomeFile; Uses Forms; indica al compilatore che il programma NomeFile di fare riferimenti ai tipi di dati, alle variabili, alle costanti o alle routine dichiarati o realizzati dalla unit Forms. Durante l'uso delle unit, generalmente si parte dalla necessitò di ottenere una determinata possibilità, ad esempio creare una finestra sotto windows. CREAZIONE DELLE UNIT La creazione di unit personali è leggermente più complicata. All'inizio è necessario determinare a quali dichiarazioni possono accedere le altre unit e i programmi, Queste dichiarazioni costituiscono la sezione interface della unit (per coloro che conoscono il C++ la sezione interface corrisponde né più né meno alla dichiarazione dei prototipo). E' quindi necessario completare le dichiarazioni, comprese le procedure locali e le variabili, nella sezione implementation. Queste sezioni sono illustrate nella sintassi qui riportata: Unit NomeFile; interface { dichiarazioni visibili o pubbliche } implementation { dichiarazioni nascoste o private } Quando la unit viene compilata su disco, viene creato un file .DCU (Delphi Compiled Unit) che contiene il codice oggetto di quella unit. Per meglio chiarire i dettagli relativi alla creazione di una unit, si esamini il seguente esempio: Unit Math; interface procedure Quadrato(var N: Integer); implementation 16
procedure Quadrato(var N: Integer); Begin N:= N * N; End; End. Il file di una unit andrà salvato con estensione .pas, come tradizione del Turbo Pascal. Per richiamare la funzione Quadrato provare il seguente esempio: {$APPTYPE CONSOLE} Program Quadro; Uses Math; Var Numero: Integer; Begin Write('Inserisci un numero: '); ReadLn(Numero); Quadrato(Numero); WriteLn; WriteLn; Write('Il quadrato del numero è: ', Numero); ReadLn; End. Si noti l'utilizzo della parola riservata Uses che prepara il compilatore a linkare l'unit math precedentemente preparata. Con questo si chiudono i capitoli dedicati all'introduzione Turbo Pascal necessaria per creare programmi sotto Delphi. Dal prossimi capitolo si inizierà a programmare sotto Windows! 17
Seconda parte: Programmazione Windows tramite Object Pascal Capitolo 8 La programmazione sotto Windows Per coloro che provengono dal mondo DOS la programmazione sotto Windows può apparire come complicata (e in effetti lo è), in questo capitolo verrà introdotto il concetto di Form e logica RAD. Nel primo capitolo si era creato il programma Hello World, si provvederà qui di seguito a creare il programma Hello Windows, naturale evoluzione del primo. Per cominciare basterà selezionare New Application dal menu File. Il risultato dovrebbe apparire come da figura: Ora premendo F11 apparirà una finestra simile a quella della figura seguente: 18
Sarà bene familiarizzare con l'Object Inspector, perché è da qui che si setteranno eventi e proprietà dei programmi Windows, ad esempio si cambi le seguenti proprietà come da tabella: Nome Proprietà Valore precedente Nuovo Valore Caption Form1 Hello Windows! Position poDesigned poScreenCenter Ora eseguite tranquillamente il programma e come per magia apparirà una finestra con titolo Hello Windows!, Ma dove sta il trucco? Delphi è un compilatore orientato alla logica RAD, aspettatevi quindi una programmazione notevolmente semplificata! Per vedere il codice del programma vi basterà selezionare units dal menu views confermando quindi Unit1. Il codice della form dovrebbe essere il seguente: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} end. Non preoccupatevi se non riuscite a capire niente! Provate quindi ad aggiungere un componente Button prelevabile dalla palette degli strumenti 19
Una volta inserito il button nella form questo apparirà come un normalissimo pulsante di windows. Dall'Object Inspector (F11) selezionate la sezione events, ora cliccate sul pulsante del form (il Button aggiunto precedentemente) e fate un doppio click sulla sezione onMouseMove dell'Object Inspector, se avete eseguito il tutto correttamente dovrebbe aprirsi una finestra di digitazione codice come segue: procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin end; Modificatela nel seguente modo: procedure TForm1.Button1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin Caption:= 'Mouse sul pulsante'; end; Modificate anche l'evento onMouseDown dell'oggetto Form1 come segue: procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin Caption:= 'Hello Windows!'; end; Se avete eseguito il tutto correttamente il vostro programma cambierà il titolo della finestra a seconda che il mouse sia sul pulsante o sulla form. Il secondo programma Windows Nel secondo capitolo si era creato quello che forse era il più complesso programma finora trattato, ora si proverà ad effettuare il cd. porting a windows... Creare un nuovo progetto (New Application dal menu file) e preparare la form come segue: 20
Si modifichino da Object Inspector le seguenti proprietà: Nome Oggetto Nome Proprietà Valore precedente Nuovo Valore Form1 Caption Form1 Volume cilindro Form1 Name Form1 frmMain Button1 Caption Button1 Calcolo Button1 Name Button1 btnCalcolo Button2 Caption Button2 Esci Button2 Name Button2 btnExit Label1 Caption Label1 lunghezza raggio cilindro Label1 Name Label1 lblRaggio Label2 Caption Label2 lunghezza del cilindro Label2 Name Label2 lblAltezza Edit1 Text Edit1 -vuoto- Edit1 Name Edit2 txtRaggio Edit2 Text Edit2 -vuoto- Edit2 Name Edit2 txtAltezza TIP E' buona norma cambiare sempre la proprietà name dando un nome più significativo, si consiglia di vedere a questo proposito l'integrazione sulla Notazione Ungherese a fine corso. Se il tutto è stato eseguito in maniera corretta la vostra finestra avrà il seguente aspetto: 21
Ora basterà modificare il codice della unit come segue: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TfrmMain = class(TForm) lblRaggio: TLabel; txtRaggio: TEdit; lblAltezza: TLabel; txtAltezza: TEdit; btnCalcolo: TButton; btnExit: TButton; procedure btnExitClick(Sender: TObject); procedure btnCalcoloClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var frmMain: TfrmMain; implementation {$R *.DFM} procedure TfrmMain.btnExitClick(Sender: TObject); begin Close; end; procedure TfrmMain.btnCalcoloClick(Sender: TObject); var rRaggio, rAltezza: Real; iResult: Integer; begin rRaggio:= STRtoINT(txtRaggio.Text); rAltezza:= STRtoINT(txtAltezza.Text); iResult:= Round(rRaggio*rRaggio*rAltezza*Pi); Caption:= INTtoSTR(iResult); end; end. L'unica istruzione che forse vi dovrebbe dare problemi è Round che serve per convertire da Real ad Integer. 22
In definitiva la programmazione sotto Windows si svolge in quattro fasi: 1. Inizio di una nuova applicazione 2. Preparazione della from tramite la palette dei componenti Delphi 3. Settaggio delle varie proprietà tramite Object Inspector 4. Definizione dei gestori degli eventi 5. Scrittura del codice 23
Capitolo 9 Chiarimenti sui cicli FOR TO DO Questo capitolo consiste in una spiegazione sull'utilizzo dei cicli, sebbene sia alquanto breve consiglio una lettura attenta in quanto i cicli sono tra le strutture più complesse di un linguaggio di programmazione. Esaminiamo il seguente problema: vogliamo riempire un ListBox con dei numeri da 1 a 100 alla semplice pressione di un Button, teoricamente basterebbe provvedere a ripetere 100 volte l'istruzione ListBox1.Items.Add('1'); cambiando di volta in volta il valore '1' con '2', '3', etc. Converrete che non è così semplice, per risolverlo basterebbe teoricamente incrementare una variabile numerica per 100 volte, convertirla in stringa (istruzione INTtoSTR vista nel capitolo 4) e Aggiungere all'insieme Items della ListBox la stringa. A questo ci viene incontro la struttura For := To (o DownTO) DO Begin [istruzioni...] End; Provate quindi ad aggiungere in un form vuoto (New Application dal menu file) un ListBox ed un Button, all'evento onClick del Button inserite il seguente codice: procedure TForm1.Button1Click(Sender: TObject); Var I: Integer; S: String; begin For I:= 1 To 100 DO Begin S:= INTtoSTR(I); ListBox1.Items.Add(S); End; end; Ad ogni pressione del Button1 verranno aggiungi ogni volta 100 elementi sul ListBox. Ai fini della comprensione del linguaggio consiglio di aggiungere anche il seguente codice all'evento DblClick del ListBox. procedure TForm1.ListBox1DblClick(Sender: TObject); begin ListBox1.Items.Delete(ListBox1.ItemIndex); end; Che Vuol dire né più né meno che "togli il numero su cui fai doppio click"! Provate anche ad aggiungere un secondo Button con il seguente codice: procedure TForm1.Button2Click(Sender: TObject); begin ListBox1.Items.Clear; end; Che altro non fa se non rimuovere tutti gli elementi dell'insieme Items della ListBox. 24
WHILE DO Le caratteristiche salienti di For To Do restano l'alta velocità e la semplicità d'utilizzo, tuttavia per utilizzare questo ciclo si devono conoscere anticipatamente l'inizio e la fine. A questo pone rimedio While DO, naturale evoluzione di For To Do! la sintassi di While DO è la seguente: While DO begin [Istruzioni da ripetere] end; Supponiamo di voler creare un form nella quali finché non si inserisce un ciclo in cui finché non si inserisce una password corretta venga ripetuto. Il programma potrebbe assumere il seguente aspetto: {$APPTYPE CONSOLE} Program PassWord; Uses SysUtils; Var PassWord: String; Begin PassWord:= ''; While PassWord 'FINE' do begin Write('Inserire password: '); ReadLn(PassWord); PassWord:= AnsiUpperCase(PassWord); end; End. Come dovreste aver imparato i programmi che iniziano con la direttiva {$APPTYPE CONSOLE} vengono compilati in DOS mode. Il programma chiede una password finché non si inserisce fine. Se si fosse voluto chiedere solo per tre volte la password si sarebbe potuto ricorrere al ciclo For To Do. Un'altro ciclo dell'object pascal è Repeat Until, tuttavia un uso appropriato di While DO sostituisce in maniera più funzionale quest'ultimo! Ci stiamo avvicinando alla conclusione di questo corso, con il prossimo capitolo si concluderanno le trattazioni sulla programmazione RAD e sarete quindi già in grado di passare alle migliaia di Tips & Tricks presenti nella rete, tuttavia raccomando la lettura dell'integrazione sull'OOP e sulla gestione dei file incluse nel corso. 25
Capitolo 10 Canvas: chi fu costui? Letteralmente canvas significa tela o canovaccio, nel linguaggio Delphi con Canvas si intende un oggetto (TCanvas) che incapsula le operazioni grafiche di Windows rendendole molto più semplici; un programmatore di C++ è costretto a districarsi tra handle to device context e chiamate GDI per disegnare anche una semplice linea (a meno che non ricorra a MFC o simili). Delphi, come tutti i linguaggio RAD oriented, offre una semplicità notevole anche in questo campo, tuttavia per coloro che desiderassero un accesso diretto alle funzioni video la Borland mette a disposizione semplici sistemi per chiamare le API Windows. TIMAGE Il sistema più semplice per visualizzare immagini grafiche è ricorrere al componente TImage prelevabile dalla Palette 'Additional'. L'oggetto TImage dispone della proprietà Picture di tipo TPicture che può contenere un'immagine grafica. TIP Delphi supporta nativamente i file bitmap, le icone e i metafile ma aggiungendo al progetto l'unit Jpeg si avrà accesso alla lettura di questo formato. L'unit jpeg è fornita con tutte le versioni di Delphi 3.0 esclusa la standard. Per caricare un'immagine dall'oggetto Image1 (un TImage piazzato su di una Form) si userà la sintassi Image1.LoadFromFile('Nome file.bmp'); Viceversa per salvare un file su disco Image1.SaveToFile('Nome file.bmp'); TBITMAP La classes TBitmap incapsula hBitmap e hPalette di Win32, tramite Delphi non sarà più necessario manipolare tavolozza e handle! Per creare un Bitmap la sintassi sarà la seguente: Var Bitmap: TBitmap; Begin Bitmap:= TBitmap.Create; Bitmap.LoadFromFile('File.bmp'); Bitmap.free; End; TCANVAS La proprietà Canvas (di tipo TCanavs) è disponibile in tutti gli oggetti discendenti da TGraphicControl e dispone delle proprietà Pen, Brush e Font. Tramite un oggetto TCanvas è quindi possibile svolgere qualsiasi tipo di operazione grafica. TPEN Tramite l'oggetto TPen (proprietà Pen di un canvas) è possibile settare lo spessore e il tipo di linea disegnata in un Canvas. 26
TBRUSH Un pennello (Brush) disegna forme o riempie aree. Le proprietà incapsulate da un pennello sono: Color, Style e Bitmap. Ci sono otto opzioni di pennello selezionabili come stile: bsSolid, bsClear, bsHorizontal, bsVertical, bsDiagonal, bsBDialog, bsCross, bsDiagCross. METODI CANVAS L'oggetto Canvas incapsula la maggior parte di API grafiche, tra i più importanti metodi ricordiamo in questo capitolo solo TextOut, ma ve ne sono molti altri... PROGETTO DI ESEMPIO Probabilmente avete le idee parecchio confuse. Nella cartella 'Esempi' troverete il progetto 'dcanvas.zip' che utilizza tutto quanto spiegato. E' un buon punto di partenza per lo sviluppo di qualche grafica primitiva. 27
Capitolo 11 Chiarimenti sulla programmazione Windows PARTE PRIMA: L'oggetto Form Tutti i programmi Windows sono costituiti da finestre, come ormai dovreste avere appreso in Delphi le finestre prendono il nome di Form e sono discendenti dell'oggetti TForm. 1. Ma che metodi e proprietà dispongono le Form? 2. Come si fa a richiamare una seconda Form? 3. Come si agganciano i menu standard di Windows? 4. E i pop-up menu richiamabili con il tasto destro del mouse? Queste sono le domande che verranno trattate in questo capitolo. Supponiamo ad esempio di voler creare una finestra contenente un Menu tramite il quale sia possibile richiamare una seconda finestra. Il primo passo sarà ovviamente creare un nuovo progetto dal vostro compilatore preferito (Delphi, of course). Fatto questo aggiungeremo un TMainMenu dalla palette degli strumenti. La vostra Form dovrebbe avere ora un componente simile a questo . Cliccate quindi sulla proprietà Items dell'oggetto MainMenu1 (ovviamente da Object Inspector). Il risultato è una finestra simile alla seguente: Sarà bene familiarizzare da subito con questo editor, è da qui che si creano e modificano menu. Nell'Object Inspector inseriremo ora come caption '&File' e nome mnuFile, vi chiederete ora che oggetto stiamo modificando, la risposta è nessuno! Abbiamo appena creato un nuovo oggetto, un TMenuLine (line di menu), Si noti anche che il carattere '&' è divenuto nell'editor un segno di sottolineatura. Inseriamo un nuova line di menu cliccando sul campo vuoto sottostante il menu File, precisamente inseriremo una linea 'About' (nome oggetto mnuAbout) una linea '-' nome oggetto mnuN1 e una linea 'Exit' (mnuExit). 28
Per capirci il risultato dovrebbe essere come segue: Chiudiamo quindi la finestra con titolo Form1.MainMenu1 (l'editor insomma), il risultato sarà una form con un Menu(!) Abbiamo quindi creato un componente Windows senza digitare una sola linea di codice (e poi parlano di C) ma in maniera del tutto RAD (o Visuale, a dir si voglia). Il secondo passo di questa lezione consisterà nel creare una seconda Form richiamabile dal menu About, per fare ciò scegliere new dal menu File di Delphi e dalla Dialog scegliere Form. Verrà quindi aperta una seconda Form di nome Form2 (che fantasia 'sti progettisti di Delphi...) che provvederemo a rinominare (tramite Object Inspector, ma vi devo sempre dire tutto?) in frmAbout. Inseriamo quindi nella form un TCalendar prelevabile dalla palette Sample di Delphi e settiamo la proprietà Align di Calendar1 a alClient, così facendo l'oggetto calendar1 sarà autoresizable (concedetemi il termine). L'ultimo passo sarà rendere attivo il menu About, per fare questo richiamiamo la prima Form (Forms dal menu View di Delphi) e clicchiamo sul menu About, si dovrebbe aprire una finestra codice nella quale digiteremo frmAbout.Show; Nel menu Exit inseriamo invece la riga Form1.Close; avviamo il progetto e se tutto è stato fatto correttamente avremo... un ERROREEEEEEE!!!!!!! (SI AVETE LETTO BENE!!!!!!!). Per l'esattezza dovrebbe apparire una finestra di conferma come la seguente: 29
Nella realtà non è stato commesso nessun errore, se ci pensate la variabile di riferimento della TfrmAbout (frmAbout) non è dichiarata nella unit della Form1, basterebbe quindi aggiungere semplicemente il nome del file contenente la classe TfrmAbout nella direttiva uses dalla unit Form1 (spero di essere stato chiaro). Rispondendo quindi yes alla richiesta information Delphi stesso provvederà a correggere questa incongruenza (diavolo di compilatore!), infatti troveremo dopo la direttiva Uses nella sezione implementation il file Unit1. Vi chiederete (almeno spero) perché non sia stato inserito nella sezione interface, il motivo è presto detto: è la stessa identica cosa. Aggiungiamo adesso un TPopUpMenu nel form frmAbout e dall'editor Items aggiungiamo la linea BlaBla (Caption BlaBla e name mnuBlaBla), Nell'evento click del menu inseriamo la riga ShowMessage('PopUpMenu'); Ora non resta che assegnare alla proprietà PopUpMenu di Calendar1 l'oggetto PopUpMenu1. Abbiamo così creato un progetto che visualizza un semplice calendario alla pressione di un menu About (completamente inutile ma funzionante). Al fine di una più completa conoscenza dell'oggetto TForm provare ad aggiungere nella Form1 un Panel (palette Standard), settatene caption a nulla e align ad alTop. All'interno del Panel si disponga uno SpeedButton e da Object Inspector si assegni all'evento OnClick l'evento mnuAboutClick. ATTENZIONE: non si deve creare un nuovo evento, ma tramite la drop list selezionare un evento già presente. Per finire cambiare la proprietà Glyph dello SpeedButton con una bitmap prelevabile dalla cartella images\buttons di Delphi. Abbiamo così creato una barra degli strumenti presente nelle versioni datate di Office. TIP (Solo per Delphi 3.0) Settate a True la proprietà ShowHint dello SpeedButton, aggiungete del testo alla proprietà Hint e cambiate a true la proprietà Flat. Otterrete così dei "CoolButton" in stile Office '97 (pulsanti a scomparsa con testo di Help sensibile al passaggio del mouse). PARTE SECONDA: Alcuni Tips & Tricks Altre domande che il principiante programmatore Delphi si pone spesso sono: 1. Come si manipola l'oggetto Items di una ListBox 2. Come si ordina una lista di stringhe? 3. Come si crea un "Hot Key" nell'applicazione? L'oggetto Items contenuto come proprietà di una ListBox o di una ComboBox è uno dei più potenti oggetti messi a disposizione da Delphi. Tecnicamente è assimilabile all'oggetto TStringList. I metodi più importanti incapsulati da Items sono: • Add(S: String) • Delete(Index: Integer) • Insert(Index: Integer; S: String) • Clear Tramite l'insieme items si può facilmente memorizzare e ordinare una lista di stringhe. Settando infine la proprietà Sorted a true la lista di stringhe inserite si ordinerà automaticamente! Per creare un Hot Key provate il seguente modo: 30
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (ssCtrl in shift) and (chr(key) in ['A', 'a']) then ShowMessage('Ctrl-A'); end; 31
Capitolo 12 Ottimizzazione del Codice ATTENZIONE: Capitolo e codice non ancora ultimati Sebbene la velocità dei processori del giorno d'oggi e la quantità di Hard Disk disponibile nei PC sia aumentata in maniera esponenziale una delle tappe fondamentali per il programmatore resta l'ottimizzazione del proprio codice. In questo capitolo si studieranno dei semplici metodi per rendere più efficiente la velocità dei propri programmi. In generale i fattori da ottimizzare in un programma restano 4: la velocità di visualizzazione, reale, apparente e l'utilizzo di risorse. E' buona norma ottimizzare un programma durante la sua creazione e non a lavoro ultimato. In questo capitolo si userà un progetto da me creato per spiegare i possibili miglioramenti di un programma. Si tratta del progetto contenuto nel file 'optimize.zip', sempre nella cartella 'Esempi'. VELOCITA' REALE Con velocità reale si intende la velocità intrinseca del programma compilato e che quindi non è ulteriormente migliorabile... Come fare ad ottimizzare una routine? Il trucco sta nell'utilizzare tipi che il sistema operativo e il compilatore gestisce con maggior facilità, ad esempio in Windows 3.1 i tipi numerici a 16-bit erano i più veloci, in Windows '95 e Windows NT gli interi a 32-bit sono al contrario i più rapidi, nel Pascal il tipo Integer era (fino alla versione di Delphi 1.0) a 16-bit, nelle versioni a 32-bit di Delphi (2.X e 3.X) con Integer si intende un intero a 32-bit. Nella sezione "confronto di tipi" del progetto in esame verranno confrontati i tipi SmallInt, Integer, Variant e Real. E' interessante osservare come il tipi Variant sia notevolmente più lento degli altri, questo perché una variabile Variant può contenere sia dati interi che mobili (Integer e Real), ma anche Stringhe o Currency. Potrebbe sembrare vantaggioso usare sempre tipi Variant, ma vi renderete conto che una lentezza superiore di 80 volte può seccare piuttosto l'utente, anche perché è semplice convertire dati da stringhe a numeri tramite funzioni del tipo STRtoINT o INTtoSTR :-D Nel test anche il tipo Real appare decisamente lento, in effetti se possibile è consigliabile svolgere calcoli in Integer e convertire solo quando necessario in dati reali. VELOCITA' DI STRINGHE In Object Pascal non esiste alcun modo per rendere più veloce il tipi String, tuttavia nel progetto Optimize è mostrato un piccolo stratagemma per velocizzare operazioni di stringhe: quando si deve eseguire la stessa funzione con determinate stringhe (ad esempio un concatenamento, S:= S1 + S2 ie.) all'interno di un ciclo è preferibile costruire il valore all'esterno del ciclo, la performance del programma crescerà in maniera insperata... OTTIMIZZAZIONE DEL CODICE Per la serie le pecche del RAD... Ragazzi mettetevi in testa una cosa, in Delphi sarà pure semplice programmare ma il risultato è notevolmente più lento del codice non RAD. Perché ci dici ciò? Semplice perché con piccoli accorgimenti si può rendere una routine notevolmente più veloce senza scrivere tanto codice. Siete scettici? Facciamo un esempio: l'accesso di una proprietà è più lento rispetto all'uso di una variabile di 50 volte, se intendiamo usare in un ciclo una determinata proprietà che resta invariata basterà quindi salvarla in una variabile temporanea. In fondo in fondo il codice è lo stesso. Vedere per chiarimenti "ottimizzazione del codice nel progetto in esame". VELOCITA' APPARENTE Sapete perché vanno tanto di moda le ProgressBar? Perché migliorano la velocità apparente (anche a scapito della reale). Come la Microsoft insegna non si deve fare un programma veloce ma un 32
programma che sembri veloce, il mostrare un clessidra "avverte" l'utente che deve attendere, l'avanzamento di una percentuale sullo schermo fa credere all'ignaro utilizzatore che il programma sta effettivamente svolgendo qualcosa (mentre in realtà potrebbe limitarsi a resizare le immagini porno interne al soft stesso), l'utilizzo di Thread multipli, a costo di rendere un programma il corrispondente di una tartaruga digitale, esalta l'utilizzatore finale (tanto per capirsi se finché il vostro programma non svolge un tubo attivaste uno Screen Saver di Pamela Andersson l'utente non si renderebbe conto del tempo che passa, anzi... :P Se l'esempio non vi dà l'impressione di un miglioramento di velocità probabilmente fate parte della schiera di quelli che necessitano del suddetto Screen Saver :-) ALGORITMI DI RICERCA 33
Capitolo 13 API Handle e programmazione avanzata Piccola premessa: in questo capitolo vi troverete di fronte argomenti del tutto nuovi, tipici della programmazione C strutturata (cioè non orientata agli oggetti). Già con il C++ molti dei concetti che seguono sono stati incapsulati in classi (MFC o OWL). Capirete quindi che essendo il Delphi orientato alla logica RAD, i concetti di handle e API sono stati COMPLETAMENTE sostituiti da oggetti VCL (Visual Component Library). Questo se da un lato il programmatore è più libero, da un altro lato lo rende vincolato a classi scritte da altri. Questo è solo un discorso teorico, in realtà Delphi è talmente potente da poter gestire anche le chiamate API più complesse, nonché tutti quei concetti tipici della programmazione Windows strutturata (funzioni callback per esempio). Se avete quindi ancora problemi nello scrivere semplici applicazioni usando i mezzi che Delphi vi propone non posso che consigliarvi di affinare meglio le vostre tecniche, questo capitolo non fa per voi! HANDLE Un handle è un numero intero a 32-bit senza segno. Tutto qui! Il Windows gestisce ogni oggetto (sia esso grafico come una finestra, sia esso hardware come la periferica video) con un handle, ad esempio quando inseriamo un nuovo pulsante in una form, questo ha necessariamente un handle. E' quindi ovvio che Windows può gestire fino a 232 finestre contemporaneamente, non di più perché questi sono gli handle che può allocare in memoria. Ma perché dovremmo accedere ad un handle, quando Delphi ci mette a disposizione tutto già pronto, ma soprattutto come si fa ad accedere ad un handle? Riguardo alla prima domanda non c'è una risposta precisa, in questo capitolo proporrò alcuni esempi dove per sopperire a limitazioni dell'ambiente Visuale si deve ricorrere a queste tecniche più a basso livello (anche se è un termine improprio). Per accedere ad un handle è invece semplicissimo, ogni oggetto ha una proprietà non visibile da Object Inspector di nome handle! COME NASCONDERE L'ICONA SULLA TASKBAR Avete mai provato a nascondere l'icona sulla TaskBar di Win '95? Molto semplice non si può fare in Delphi! Per capire ciò si deve premettere che in Delphi esiste un oggetto Application che contiene l'handle del pulsante sulla taskbar (non è propriamente così, ma per semplificarvi le cose...;-) quindi basterebbe nascondere trovare una chiamata per nascondere un oggetto grafico conoscendo il suo handle. Proviamo quindi ad inserire in una form vuota un pulsante e nel codice click di questo il seguente codice ShowWindow(handle, SW_HIDE); Eseguiamo il codice... magia alla pressione del tasto sparirà la finestra! Se mi avete seguito attentamente avrete già capito che l'istruzione seguente ShowWindow(Application.handle, SW_HIDE); Farà sparire il pulsante sulla taskbar... provare per credere! Ma cos'è questa istruzione ShowWindow? E' per l'appunto una API che visualizza, minimizza, massimizza o nasconde una finestra. Allora vi chiederete, il pulsante sulla taskbar è una finestra? Non proprio, in realtà l'oggetto Application è costruito attorno ad una finestra non visibile che serve solo ed esclusivamente per visualizzare il pulsante sotto, nascondendo questa finestra tramite l'istruzione ShowWindow potremo fare sparire anche il pulsante ad essa associato. Provate, tanto per fare, anche le seguenti istruzioni: 34
Puoi anche leggere