Programmazione Delphi

57
7/24/2019 Programmazione Delphi http://slidepdf.com/reader/full/programmazione-delphi 1/57  CORSO DI PROGRAMMAZIONE DELPHI di Vanni Brutto

Transcript of Programmazione Delphi

Page 1: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 1/57

 

CORSO DI PROGRAMMAZIONE DELPHI 

di Vanni Brutto

Page 2: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 2/57

  2

Prefazione

Benvenuti nel mio interessantissimo corso dedicato a tutti coloro che non hanno  MAI   avuto a chefare 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 parterelativa ai Tips & Tricks! Qualsiasi suggerimento per il miglioramento di questo corso è benaccetto... Al fine della completa trattazione è necessario:

• Una copia di Delphi (possibilmente versione 2 o successiva)

• File Help di Delphi

IntroduzioneQuesto 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 permancanza 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 citroviamo di fronte a prodotti già pronti e in cui ogni tipo di software immaginabile è già stato scrittoda qualcuno; la risposta non è così semplice, la programmazione è un’arte, per alcuni è considerataalla stregua di un hobby, e per altri è un lavoro, chi non ha mai provato l’ebbrezza della stesura diuna 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 offremiglior 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 collocaancora un gradino sopra di detto tool, specie con l’avvento del Delphi; non è comunque daescludere anche il C++ Builder, il “cugino” di Delphi.

DisclaimerQuesto corso è stato creato interamente da Vanni Brutto ([email protected]). Potete trovarne unaversione online all'indirizzo http://www.geocities.com/SiliconValley/Lab/6806/. I files che troveretenello zippato 'corso.zip' sono protetti dal diritto d'autore e sono liberamente riproducibili acondizione di non farne uso commerciale o economico o per fine di lucro senza la preventivaautorizzazione dell'autore. In ogni caso deve sempre essere indicato il nome dell'autore e il suoindirizzo. 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, causatidall'utilizzo dei suddetti files. LI USATE A VOSTRO RISCHIO. 

Versione PDF La versione PDF di questo libro è stata adattata da Stefano SteO Arcidiacono([email protected]), potete scaricarla da #GameProg-Ita, il primo sito Italiano interamentededicato alla creazione di videogiochi: http://gpi.infomedia.it

Page 3: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 3/57

  3

Prima parte: breve introduzione al Turbo Pascal (sintassi e strutture) 

Capito lo 1

Un po’ di storiaIl Pascal è un linguaggio ad alto livello, che tenta in pratica di avvicinarsi per quanto possibile alragionamento 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 vengonoscritte nel linguaggio della CPU. Il Pascal nasce per merito di N. Wirth che per primo introdusse lasintassi 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 Pascalscritto da Anders Hejlsberg. I programmatori Pascal hanno apprezzato attraverso gli annil’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 altrilinguaggi 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 disoftware gestionali per DOS. Con l’avvento del Windows, la Borland rilasciò la prima versione diBorland Pascal, un pacchetto basato sul linguaggio Object Pascal, naturale evoluzione del TurboPascal; 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 immancabiliAPI4 del Windows. Per questo la Borland rilasciò nel mercato Delphi e successivamente Delphi2.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 tipoR.A.D. per il C++ (C++ Builder) molto simile al Delphi; attualmente siamo giunti alla versione 3.0di Delphi, e sicuramente il futuro riserverà altre sorprese, tuttavia voglio fare notare che il codicescritto in Delphi è conferme all’Object Pascal, di cui ha ereditato pure il numero delle versione, laversione 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 chenon 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 Delphi2. Scegliere close all dal menu file e chiudere tutti i files eventualmente aperti3. Dal menu file scegliere new e quindi Text4. Salvare il file come Hello.dpr (Delphi Project (*.dpr))5. Scrivere il programma in turbo pascal facendolo precedere dalla seguente riga: {$APPTYPE

CONSOLE}

Page 4: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 4/57

  4

 

{$APPTYPE CONSOLE}

{Hello World! App, tutto quello che è tra parentesi graffe non viene letto dalcompilatore}

Program Hello; {Program va seguito dal nome del file del programma}

UsesForms;

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;UsesForms;

BeginEnd. 

Il file andrà poi salvato con il nome prova ed estensione dpr. La parola riservata Begin indical’inizio del programma e deve corrispondere con un seguente End; si dovrà ricordare fin dora che inPascal 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 compilazionenon 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 nomedel file da salvare e si dovrà SEMPRE aggiungere la riga iniziale {$APPTYPE CONSOLE} perindicare a Delphi che si sta lavorando in modalità DOS, inoltre si dovrà sempre aggiungere la rigaUses Forms, è inutile al file dell’esecuzione, ma serve per caricare il file.

Miglioramenti del primo programmaSi modificherà ora il primo programma creato in precedenza come segue:

{$APPTYPE CONSOLE}{Questo è il secondo programma, tutto quello che è tra parentesi graffe nonvieneletto 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}

Page 5: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 5/57

  5

Questo programma è visivamente più complesso del primo, ma nella realtà non è nulla di particolarmente difficile, ogni programma per Turbo Pascal dovrebbe cominciare con Programseguito dal nome del file, il carattere di punto e virgola finale non è messo a caso, ogni riga diTurbo Pascal dovrebbe finire con un carattere tale, tranne poche eccezioni (tra le quali Begin eEnd); 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’effettocreato.

TIP Nota per gli utilizzatori di Delphi: è possibile eseguire programmi scritti per Turbo Pascalanche in Delphi, si dovrà però seguire la seguente procedura

1. Avviare Delphi2. Scegliere close all dal menu file e chiudere tutti i files eventualmente aperti

3. Dal menu file scegliere new e quindi Text4. 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;BeginWriteLn(‘PROGRAMMA P2’); {WriteLn si usa per scrivere sul video}

BeginWriteLn(‘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 secondoWriteLn è 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 dicodice sono equivalenti(!).

Page 6: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 6/57

  6

Capito lo 2

Le variabili e i calcoli matematici Presentazione 

Per determinare il volume di una barra cilindrica, dobbiamo conoscere la superficie della sezione, emoltiplicarla per la lunghezza. Osservate il disegno:superficie della sezione = 3,14159xRxRvolume 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 lalunghezza L. Il programma seguente calcola il volume di una area cilindrica ma questa volta con ivalori:

L=5R=7

Il programma:

{$APPTYPE CONSOLE}Program Volume;ConstPgreco = 3.1415926535897932385;VarR,L,Sup : Real;

V : Integer;

beginL:= 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 servead 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 cheviene inizializzata per un certo valore e cioè il numero corrispondente al Pi. La parola riservata Varserve invece ad indicare la dichiarazione di variabili, questa serve ad indicare al compilatore diassegnare 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 troviamol’assegnazione di 5 per la variabile L e di 7 per la variabile R, l’assegnazione di un valore ad unavariabile avviene sempre tramite l’operatore :=Con Sup:= PGreco*R*R si indica al compilatore di moltiplicare Pgreco per il quadrato del raggio eassegnare il valore alla variabile Sup. Infine con V:= Round(Sup*L) si indica di moltiplicare lasuperficie per l’altezza, arrotondare il risultato, e assegnarlo alla variabile V che vienesuccessivamente passata alla funzione WriteLn dove verrà scritta sullo schermo.

Ora si vedrà lo stesso programma riprodotto in maniera leggermente diversa:

Page 7: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 7/57

  7

 

{$APPTYPE CONSOLE}Program Area;ConstPgreco = 3.1415926535897932385;

VarR,L,V: Real;

beginL:= 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 peressere 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 Realtramite WriteLn si dovrà ricorrere ad esso! Non preoccupativi per la difficoltà di programmazionein DOS, appena conoscerete queste semplici basi la programmazione in Windows sarà uno scherzo!

Page 8: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 8/57

  8

Capito lo 3

WriteLn, Write e ReadLn: questi sconosciuti

WriteLn e WriteLa prima istruzione che descriveremo sarà l’istruzione WriteLn, questa istruzione scrive sul video eriporta il cursore a capo, la differenza tra Write è abbastanza evidente, Write non riporta il cursore ainizio riga.

 ReadLn

ReadLn legge un valore dalla periferica standard, di solito dalla tastiera, così l’istruzioneReadLn(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 modosostanziale:

{$APPTYPE CONSOLE}Program Area;

ConstPgreco = 3.1415926535897932385;

Var R,L,V : Real;

beginWriteLn;

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 unqualsiasi cilindro!

Page 9: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 9/57

  9

Capito lo 4

Tipi di variabili Nella programmazione Pascal si dovrà imparare le sottili differenze che esistono tra le variabilinumeriche, 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 6Single 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; adesempio

Var Var1,Var2,Var3 : Integer;R1,R2,R3 : Real;

Le Stringhe: giochiamo con le lettereUn 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 comelinee apostrofi etc. Il compilatore considererà stringa tutto ciò che trova tra due apici, ad esempio

Page 10: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 10/57

  10

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;

UsesForms;

Var Nome: String;

BeginWrite('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 rivisualizzarlasuccessivamente, 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 distringa. 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à megliol'utilizzo:

{$APPTYPE CONSOLE}Program Stringhe;

UsesSysUtils;

Var S: String;

BeginWrite('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 UsesForms 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, questonon deve assolutamente spaventarvi!

Page 11: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 11/57

  11

INTtoSTR e STRtoINTQuesti due metodi servono per passare da stringhe a interi e viceversa: ad esempio avendo unavariabile I contenente un dato numero che deve essere trasferito nella stringa S si dovrà eseguire laseguente riga di codice:

S:= INTtoSTR(I);

Il che tradotto in linguaggio parlato starebbe né più né meno a: -trasforma l'intero I in stringa ememorizza il risultato nella variabile S.Viceversa STRtoINT provvede all'operazione inversa, volete magari un esempio? Questo è compitovostro! Non preoccupativi a capire tutto quanto esposto in questo capitolo in special modo le tabellead inizio capitolo, vi basti sapere che se volete fare una divisione dovrete utilizzare un Real, selavorate su operazioni intere l'integer è d'obbligo. Inoltre si noti che le istruzioni INTtoSTR eSTRtoINT non lavorano con i numeri con la virgola. Ora rilassatevi, rileggete i capitoli precedenti esoprattutto provate a creare piccoli programmi VOSTRI utilizzando magari le stringhe, d'ora inavanti la strada sarà in salita.

Page 12: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 12/57

  12

Capito lo 5

Le istruzioni di controllo

IF ... THEN

La più semplice formulazione IF...THEN è la seguente:

if condizione thenbegin  //Se la condizione è vera allora... istruzione; //Esegui istruzioni... istruzione; istruzione; 

EndElseBegin //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 ThenBegin WriteLn('Il numero era tre'); 

EndElseBegin 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'); 

ElseWriteLn('Sicuramente non hai premuto il tre, bensì un altro numero'); 

Sarebbe stata sintatticamente corretta ma è fortemente sconsigliata, la motivazione è quanto maiovvia: se necessitate di includere più azioni dopo il then queste andranno incluse in un blocco begin

Page 13: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 13/57

  13

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 utilizzareil costrutto come spiegato, eventualmente eliminate anche l'else se è inutile! Si noti infine che glioperatori 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).

Page 14: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 14/57

  14

Capito lo 6

LE ROUTINES

 PROCEDURE  

Una subroutine è una parte di programma che può essere richiamata da un punto qualsiasi delcodice. Il salto alle subroutine si verifica tramite il nome della subroutine stessa. Al termine dellasubroutine l'esecuzione ritornerà al ciclo principale. Lo schema seguente chiarirà meglio lasituazione:

Come prassi di questo corso segue un esempio chiarificatore!

{$APPTYPE CONSOLE}Program esempio;

UsesForms;

Procedure INVIO;beginWriteLn('Premi INVIO per continuare');

ReadLn;end;

beginWriteLn('Riga numero uno');WriteLn('Riga numero due');WriteLn;INVIO;WriteLn('il programma prosegue dopo l''invio');WriteLn;WriteLn;INVIO;

End.

Page 15: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 15/57

  15

 Il programma inizia scrivendo due righe dal corpo principale, quindi l'esecuzione passa allasubroutine 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 parametroconsiste 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;

UsesForms;

var K: Integer;Procedure Input(S: String; var I: Integer);beginWrite(S);ReadLn(I);

end;

beginInput('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 dellavariabile, in altre parole rimovendo il var dalla procedura input il programma non funzionerà inquanto 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 lastessa locazione di memoria. Di conseguenza ogni modifica del parametro passato per indirizzo è inrealtà una modifica della variabile stessa. Al contrario il parametro S che viene passato per valorenon verrà alterato in alcun modo. Ad esempio provate ad eseguire il seguente codice:

{$APPTYPE CONSOLE} Program esempio; 

Uses

Forms; 

var K: Integer; 

Page 16: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 16/57

  16

 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; 

beginK:= 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 02. ora verrà chiamata la routine prova1

3. siamo all'interno di prova1 e la variabile sta per essere impostata a 344. K corrisponde ora a 05. infine verrà chiamata la routine prova26. siamo all'interno di prova2 e la variabile sta per essere impostata a 567. K corrisponde ora a 56

Si noti che anche se K viene alterato nella procedura prova1 al ritorno il valore assunto da esso nonsarà cambiato, questo perché in realtà era stato variato solo il valore di una copia di K, non Kstesso! Spero di essere stato abbastanza chiaro, d'altronde la programmazione a subroutine(comunemente detta strutturata). Come sempre consiglio di provare quanto appreso, il prossimocapitolo sarà piuttosto breve in quanto tra poco si passerà alla programmazione Windows.

 

Page 17: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 17/57

  17

Capito lo 7

Utilizzo delle unitDelphi viene fornito con diverse unit standard. Una di queste, la System unit, viene utilizzataautomaticamente durante la compilazione del programma. Se fosse necessario accedere alladichiarazione o al sottoprogramma di un'altra unit standard, è indispensabile inserire una clausolauses, 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 essereinserita 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, allecostanti 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 sottowindows.

CREAZIONE DELLE UNITLa creazione di unit personali è leggermente più complicata. All'inizio è necessario determinare aquali dichiarazioni possono accedere le altre unit e i programmi, Queste dichiarazioni costituisconola 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) checontiene 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

Page 18: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 18/57

  18

procedure Quadrato(var N: Integer);BeginN:= 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;

UsesMath;

Var Numero: Integer;

BeginWrite('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 Pascalnecessaria per creare programmi sotto Delphi. Dal prossimi capitolo si inizierà a programmare sottoWindows!

Page 19: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 19/57

  19

Seconda parte: Programmazione Windows tramite Object Pascal

Capito lo 8

La programmazione sotto WindowsPer coloro che provengono dal mondo DOS la programmazione sotto Windows può apparire comecomplicata (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 NewApplication dal menu File. Il risultato dovrebbe apparire come da figura:

Ora premendo F11 apparirà una finestra simile a quella della figura seguente:

Page 20: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 20/57

  20

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 HelloWindows!, Ma dove sta il trucco? Delphi è un compilatore orientato alla logica RAD, aspettateviquindi una programmazione notevolmente semplificata! Per vedere il codice del programma vi

 basterà selezionare units dal menu views confermando quindi Unit1. Il codice della form dovrebbeessere 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

Page 21: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 21/57

  21

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 (ilButton aggiunto precedentemente) e fate un doppio click sulla sezione onMouseMove dell'ObjectInspector, se avete eseguito il tutto correttamente dovrebbe aprirsi una finestra di digitazione codicecome 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);beginCaption:= 'Hello Windows!';

end;

Se avete eseguito il tutto correttamente il vostro programma cambierà il titolo della finestra aseconda 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 Applicationdal menu file) e preparare la form come segue:

Page 22: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 22/57

  22

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

TIPE' buona norma cambiare sempre la proprietà name dando un nome più significativo,si consiglia di vedere a questo proposito l'integrazione sulla Notazione Ungherese afine corso.

Se il tutto è stato eseguito in maniera corretta la vostra finestra avrà il seguente aspetto:

Page 23: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 23/57

  23

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 adInteger.

Page 24: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 24/57

  24

 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 Inspector4. Definizione dei gestori degli eventi5. Scrittura del codice

Page 25: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 25/57

  25

Capito lo 9

Chiarimenti sui cicli FOR TO DOQuesto capitolo consiste in una spiegazione sull'utilizzo dei cicli, sebbene sia alquanto breveconsiglio 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 allasemplice 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 unavariabile numerica per 100 volte, convertirla in stringa (istruzione INTtoSTR vista nel capitolo 4) eAggiungere all'insieme Items della ListBox la stringa. A questo ci viene incontro la struttura

For <variabile di controllo> := <Valore iniziale>  To (o DownTO) <valore finale>  DOBegin[istruzioni...]

End;

Provate quindi ad aggiungere in un form vuoto (New Application dal menu file) un ListBox ed unButton, all'evento onClick del Button inserite il seguente codice:

procedure TForm1.Button1Click(Sender: TObject);VarI: Integer;S: String;

beginFor I:= 1 To 100 DOBeginS:= INTtoSTR(I);ListBox1.Items.Add(S);

End;end;

Ad ogni pressione del Button1 verranno aggiungi ogni volta 100 elementi sul ListBox. Ai fini dellacomprensione del linguaggio consiglio di aggiungere anche il seguente codice all'evento DblClickdel ListBox.

procedure TForm1.ListBox1DblClick(Sender: TObject);beginListBox1.Items.Delete(ListBox1.ItemIndex);

end;

Che Vuol dire né più né meno che "togli il numero su cui fai doppio click"! Provate anche adaggiungere un secondo Button con il seguente codice:

procedure TForm1.Button2Click(Sender: TObject);beginListBox1.Items.Clear;

end;

Che altro non fa se non rimuovere tutti gli elementi dell'insieme Items della ListBox.

Page 26: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 26/57

  26

 WHILE DO

Le caratteristiche salienti di For To Do restano l'alta velocità e la semplicità d'utilizzo, tuttavia perutilizzare questo ciclo si devono conoscere anticipatamente l'inizio e la fine. A questo pone rimedioWhile DO, naturale evoluzione di For To Do! la sintassi di While DO è la seguente:

While <condizione vera> DObegin[Istruzioni da ripetere]

end;

Supponiamo di voler creare un form nella quali finché non si inserisce un ciclo in cui finché non siinserisce una password corretta venga ripetuto. Il programma potrebbe assumere il seguente aspetto:

{$APPTYPE CONSOLE}Program PassWord;

UsesSysUtils;

VarPassWord: String;

BeginPassWord:= '';While PassWord <> 'FINE' dobeginWrite('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 ToDo. Un'altro ciclo dell'object pascal è Repeat Until, tuttavia un uso appropriato di While DOsostituisce in maniera più funzionale quest'ultimo!

Ci stiamo avvicinando alla conclusione di questo corso, con il prossimo capitolo si concluderannole 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 sullagestione dei file incluse nel corso.

Page 27: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 27/57

  27

Capito lo 10

Canvas: chi fu costui?Letteralmente canvas significa tela o canovaccio, nel linguaggio Delphi con Canvas si intende unoggetto (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 perdisegnare anche una semplice linea (a meno che non ricorra a MFC o simili). Delphi, come tutti ilinguaggio RAD oriented, offre una semplicità notevole anche in questo campo, tuttavia per coloroche desiderassero un accesso diretto alle funzioni video la Borland mette a disposizione semplicisistemi 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 tipoTPicture che può contenere un'immagine grafica.

TIPDelphi 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 è fornitacon 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à lasintassi

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ù necessariomanipolare tavolozza e handle! Per creare un Bitmap la sintassi sarà la seguente:

Var Bitmap: TBitmap;BeginBitmap:= TBitmap.Create;Bitmap.LoadFromFile('File.bmp');

Bitmap.free;End; 

TCANVAS

La proprietà Canvas (di tipo TCanavs) è disponibile in tutti gli oggetti discendenti daTGraphicControl 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.

Page 28: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 28/57

  28

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 CANVASL'oggetto Canvas incapsula la maggior parte di API grafiche, tra i più importanti metodi ricordiamoin questo capitolo solo TextOut, ma ve ne sono molti altri...

 PROGETTO DI ESEMPIOProbabilmente 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 diqualche grafica primitiva.

Page 29: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 29/57

  29

Capito lo 11

Chiarimenti sulla programmazione Windows PARTE PRIMA: L'oggetto FormTutti i programmi Windows sono costituiti da finestre, come ormai dovreste avere appreso inDelphi 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 progettodal vostro compilatore preferito (Delphi, of course). Fatto questo aggiungeremo un TMainMenudalla 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 finestrasimile 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 cheoggetto stiamo modificando, la risposta è nessuno! Abbiamo appena creato un nuovo oggetto, unTMenuLine (line di menu), Si noti anche che il carattere '&' è divenuto nell'editor un segno disottolineatura. 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).

Page 30: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 30/57

  30

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 solalinea 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 menuAbout, 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 questorichiamiamo la prima Form (Forms dal menu View di Delphi) e clicchiamo sul menu About, sidovrebbe 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!!!!!!! (SIAVETE LETTO BENE!!!!!!!). Per l'esattezza dovrebbe apparire una finestra di conferma come laseguente:

Page 31: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 31/57

  31

 Nella realtà non è stato commesso nessun errore, se ci pensate la variabile di riferimento dellaTfrmAbout (frmAbout) non è dichiarata nella unit della Form1, basterebbe quindi aggiungeresemplicemente 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é nonsia 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 lineaBlaBla (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 menuAbout (completamente inutile ma funzionante).

Al fine di una più completa conoscenza dell'oggetto TForm provare ad aggiungere nella Form1 unPanel (palette Standard), settatene caption a nulla e align ad alTop. All'interno  del Panel sidisponga uno SpeedButton e da Object Inspector si assegni all'evento OnClick l'eventomnuAboutClick. ATTENZIONE: non si deve creare un nuovo evento, ma tramite la drop listselezionare un evento già presente. Per finire cambiare la proprietà Glyph dello SpeedButton conuna bitmap prelevabile dalla cartella images\buttons di Delphi. Abbiamo così creato una barra deglistrumenti presente nelle versioni datate di Office.

TI P  (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 delmouse).

 PARTE SECONDA: Alcuni Tips & TricksAltre domande che il principiante programmatore Delphi si pone spesso sono: 

1. Come si manipola l'oggetto Items di una ListBox2. 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. Settandoinfine la proprietà Sorted a true la lista di stringhe inserite si ordinerà automaticamente!

 Per creare un Hot Key provate il seguente modo:

Page 32: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 32/57

  32

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);beginif (ssCtrl in shift) and (chr(key) in ['A', 'a']) thenShowMessage('Ctrl-A');

end; 

Page 33: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 33/57

  33

Capito lo 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 PCsia aumentata in maniera esponenziale una delle tappe fondamentali per il programmatore restal'ottimizzazione del proprio codice. In questo capitolo si studieranno dei semplici metodi perrendere 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' buonanorma ottimizzare un programma durante la sua creazione e non a lavoro ultimato. In questocapitolo 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' REALECon 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 tipiche il sistema operativo e il compilatore gestisce con maggior facilità, ad esempio in Windows 3.1 itipi numerici a 16-bit erano i più veloci, in Windows '95 e Windows NT gli interi a 32-bit sono alcontrario i più rapidi, nel Pascal il tipo Integer era (fino alla versione di Delphi 1.0) a 16-bit, nelleversioni 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), maanche 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 svolgerecalcoli 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 progettoOptimize è mostrato un piccolo stratagemma per velocizzare operazioni di stringhe: quando si deveeseguire la stessa funzione con determinate stringhe (ad esempio un concatenamento, S:= S1 + S2ie.) 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 senzascrivere tanto codice. Siete scettici? Facciamo un esempio: l'accesso di una proprietà è più lentorispetto 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 fondoil codice è lo stesso. Vedere per chiarimenti "ottimizzazione del codice nel progetto in esame".

VELOCITA' APPARENTESapete perché vanno tanto di moda le ProgressBar? Perché migliorano la velocità apparente (anchea scapito della reale). Come la Microsoft insegna non si deve fare un programma veloce ma un

Page 34: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 34/57

  34

 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 programmasta 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 ilcorrispondente 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 nonsi renderebbe conto del tempo che passa, anzi... :P Se l'esempio non vi dà l'impressione di unmiglioramento di velocità probabilmente fate parte della schiera di quelli che necessitano delsuddetto Screen Saver :-)

ALGORITMI DI RICERCA

Page 35: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 35/57

  35

Capito lo 13

API Handle e programmazione avanzataPiccola 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 concettiche seguono sono stati incapsulati in classi (MFC o OWL). Capirete quindi che essendo il Delphiorientato alla logica RAD, i concetti di handle e API sono stati COMPLETAMENTE sostituiti daoggetti VCL (Visual Component Library). Questo se da un lato il programmatore è più libero, da unaltro 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 queiconcetti tipici della programmazione Windows strutturata (funzioni callback per esempio). Se avetequindi ancora problemi nello scrivere semplici applicazioni usando i mezzi che Delphi vi proponenon 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, adesempio 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 unhandle? 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 questetecniche più a basso livello (anche se è un termine improprio). Per accedere ad un handle è invecesemplicissimo, ogni oggetto ha una proprietà non visibile da Object Inspector di nome handle!

COME NASCONDERE L'ICONA SULLA TASKBARAvete mai provato a nascondere l'icona sulla TaskBar di Win '95? Molto semplice non si può fare inDelphi! Per capire ciò si deve premettere che in Delphi esiste un oggetto Application che contienel'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 suohandle. Proviamo quindi ad inserire in una form vuota un pulsante e nel codice click di questo ilseguente 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 servesolo ed esclusivamente per visualizzare il pulsante sotto, nascondendo questa finestra tramitel'istruzione ShowWindow potremo fare sparire anche il pulsante ad essa associato. Provate, tanto

 per fare, anche le seguenti istruzioni:

Page 36: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 36/57

  36

ShowWindow(handle, SW_MINIMIZE);ShowWindow(handle, SW_MAXIMIZE); 

Che rispettivamente minimizzano e massimizzano la form. Non usate queste due istruzioni conApplication.handle, vi avviso!

COME CREARE UNA FINESTRA SENZA CAPTION E RESIZABLE

 Non so se avete notato ma il titolo della finestra è "appiccicoso", sembra che non esista possibilitàdi creare una finestra ridimensionabile senza di questo! Ricorrendo però a adeguate chiamate API...

Ogni finestra è costituita da due tipi di stile, lo stile e lo stile esteso (introdotto da Windows 3.1).Per selezionare uno stile basta usare l'API SetWindowLong passando come parametri l'handle dellafinestra, GWL_STYLE nel caso dello stile, SWL_EXSTYLE nel caso dello stile esteso e lo stilevero e proprio. Al contrario l'API GetWindowLong può essere usata per recuperare lo stile usatoAd esempio inseriamo tre pulsante in una form ognuno con il seguente codice nell'evento click:

Button1

var Stile: Integer;beginStile := GetWindowLong(Handle,GWL_STYLE) AND NOT

WS_CAPTION;SetWindowLong(Handle,GWL_STYLE, Stile);ClientHeight := ClientHeight + 1;ClientHeight := ClientHeight - 1;

end;

Button2

beginSetWindowLong(Handle,GWL_STYLE, WS_TILEDWINDOW);ShowWindow(handle, SW_NORMAL);ClientHeight := ClientHeight + 1;

ClientHeight := ClientHeight - 1;end;

Button3

var Stile: Integer;beginStile := GetWindowLong(Handle,GWL_EXSTYLE) or

WS_EX_TOOLWINDOW;SetWindowLong(Handle,GWL_EXSTYLE, Stile);ClientHeight := ClientHeight + 1;ClientHeight := ClientHeight - 1;

end;

Button4

var Stile: Integer;beginStile := GetWindowLong(Handle,GWL_EXSTYLE) or

WS_EX_CLIENTEDGE;SetWindowLong(Handle,GWL_EXSTYLE, Stile);ClientHeight := ClientHeight + 1;ClientHeight := ClientHeight - 1;

end; 

Ora eseguito l'esempio e provate in sequenza i pulsanti. Poi riavviate il progetto e provate i tasti inordine sparso. Il risultato saranno delle Form con stile non direttamente selezionabili in Delphi!

Vi potreste (giustamente) chiedere come assegnare uno stile alla finestra PRIMA che venga creata.Per fare ciò dovremo sovrascrivere un metodo dell'oggetto TForm.

Page 37: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 37/57

  37

  TI P  Se non vi è ben chiaro il concetto di sovrascrittura di un metodo vi consiglio lalettura dell'appendice OOP-Object Oriented Programming.

Per fare ciò dovremo sovrascrivere il metodo CreateParams, l'oggetto TForm1 sarà definito quindi

come segue

typeTForm1 = class(TForm)procedure CreateParams(var Params: TCreateParams); override;

private{ Private declarations }

public{ Public declarations }

end; 

Ovviamente questo è solo in prototipo del metodo CreateParams, inserite quindi anche le seguenti

righe di codice (nella sezione implementation, ma penso che avevate già capito)...

procedure TForm1.CreateParams(var Params: TCreateParams);begininherited CreateParams(Params);Params.ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;

end; 

Il risultato sarà identico alla pressione del tasto Button4, con l'unica differenza che è stato fatto prima che la finestra fosse stata creata. Ma cos'è questo metodo CreateParams? Altro non è che i parametri che verranno passati alle API necessarie per creare la finestra vera e propria, quindi lasovrascrittura del metodo stesso ci permette di manipolare quello che Delphi ci nasconde.

UN BUG NELLA VCL

Quando minimizziamo una finestra di Windows questa mostra delle "ragnatele". Purtroppo i progetti scritti in Delphi sembrano odiare questo gradevole effetto grafico. Nella realtà l'oggettoForm che siamo soliti usare è costruito attorno all'API CreateWindow, in altre parole ogni finestrache viene creata in Windows deve usare quest'API. Gli stessi pulsanti, CheckBox e ListBox sono inrealtà finestre che contengono handle. Purtroppo gli sviluppatori di Delphi per qualche criticabileragione hanno deciso di creare un oggetto Application che "sovrasta" tutte le Form del Delphi. Perquesto quando minimizziamo una Form nella realtà non viene minimizzata ma bensì nascosta equindi Win '95 non può visualizzare l'effetto grafico in questione. Come venirne a capo?Semplicemente con qualche chiamata API ;-). A conferma di quanto vi ho appena spiegato provate

ad inserire in un pulsante la seguente riga di codice:

ShowWindow(handle, SW_MINIMIZE); 

Se avete ben capito l'uso di questa API la finestra dovrebbe venire minimizzata, e in effetti questoavviene ma non nel modo corretto... Il primo passo sarà di fare apparire nella taskbar il pulsante; perfare ciò dovremo sovrascrivere nuovamente il metodo CreateParams (vedi sezione precedente).Tralasciando il prototipo, il metodo vero e proprio sarà il seguente:

procedure TForm1.CreateParams(var Params: TCreateParams);begin

inherited CreateParams(Params);Params.WndParent := GetDeskTopWindow;

end; 

Page 38: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 38/57

  38

In effetti apparirà un pulsante nella taskbar, ma questo certo non risolve il nostro problema!Per nascondere il vecchio pulsante nella taskbar basta proseguire come già spiegato nella prima

 parte del capitolo, aggiungiamo quindi il seguente codice nell'evento OnFormCreate della Form1:

procedure TForm1.FormCreate(Sender: TObject);

beginShow;ShowWindow(Application.handle, SW_HIDE);

end; 

Siamo in dirittura di arrivo (enjoy ;-))... Adesso ci troviamo di fronte a due possibilità:

1. Sovrascriviamo il metodo in TForm che minimizza le Form2. Intercettiamo il messaggio che Windows manda alla Form1 quando questa sta per essere

minimizzata e l'adattiamo per il nostro caso.

Il primo metodo è sicuramente più semplice, ma dato che noi siamo programmatori seri

 procederemo con il secondo. L'intercettazione di un messaggio in Delphi è piuttosto semplice, ineffetti è molto simile alla sovrascrittura di un metodo con l'unica eccezione che il nome della

 procedura non è definito in alcun oggetto (lo possiamo quindi decidere noi stessi) e che il parametrooverride andrà sostituito con message nomemessaggio. L'oggetto TForm1 andrà quindi definitocome segue:

typeTForm1 = class(TForm)procedure CreateParams(var Params: TCreateParams); override;procedure FormCreate(Sender: TObject);

private{ Private declarations }procedure WmSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;

public{ Public declarations }

end; 

Se avete ben compreso la procedura WmSysCommand poteva anche venir denominata comeminimizza, non sarebbe cambiato nulla, invece è importante osservare che il nome del messaggioche ci interessa intercettare è WM_SYSCOMMAND e quindi la procedura accetta un parametro ditipo TWmSysCommand. Analogamente se volessimo intercettare in altro messaggio (ad esempioWM_SIZE dovremo come parametro il tipo previsto dall'Object Pascal (in questo caso TWmSize).

 Non è poi così difficile, vero? Unica avvertenza, dichiarate i messaggi sempre come privati! Sarà

 bene presentare anche la vera procedura, altrimenti qui facciamo notte... ;-)

procedure TForm1.WmSysCommand(var Msg: TWMSysCommand);BeginDefaultHandler(Msg);

End; 

Incredibile, funziona...

Ma dove sta la magia? Semplice, provate a sostituire DefaultHandler(Msg);  con Inherited; nonfunzionerà più! In effetti abbiamo fatto tutto questo lavoro per sovrascrivere quel benedetto

messaggio, non per ereditare il bug. Ma cos'è quella fantomatica riga DefaultHandler? Per spiegarlodevo farvi riscrivere tutta la procedura (spiacente)

Page 39: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 39/57

  39

procedure TForm1.WmSysCommand(var Msg: TWMSysCommand);Var DefMsg: TMessage;BeginDefMsg := TMessage(Msg);DefWindowProc(handle, Msg.Msg, DefMsg.wParam, DefMsg.lParam);

End; 

Questa procedura funziona alla perfezione al posto dell'altra per il semplice motivo cheDefaultHandler altro non è che l'incapsulazione Pascal dell'API DefWindowProc. Quest'API serve

 per richiamare il funzionamento standard di un messaggio Windows, quindi richiamandoDefaultHandler la finestra verrà minimizzata e non nascosta.

Vi consiglio vivamente di dare un'occhiata al progetto finale della form free minimize bug(..\Esempi\minsmp.zip).

La programmazione Windows strutturataPrima di procedere in questo capitolo rilassatevi, bevetevi pure una Coca Cola e se necessario fatevi

un giro. Tutte le tecniche RAD e orientate agli oggetti andranno riposte nel dimenticatoio al fine diuna completa comprensione...Fin dalle prime versioni Windows la programmazione per questo ambiente è sempre stata ostica,solo per visualizzare una semplice finestra erano necessarie decine di righe di codice.Fortunatamente le case costruttrici dei più noti compilatori prepararono un set di librerie orientateagli oggetti che semplificavano la programmazione per questo o.s. Tra le più note ricordiamo leMicrosoft Foundation Class e le Object Windows Library rispettivamente Microsoft e Borland.Ovviamente essendo queste librerie orientate all'OOP erano utilizzabili solo dal C++ tra l'altro laMicrosoft impose le sue MFC come standard per qualsiasi applicazione scritta nel suo ambienteVisual C++ tanto che alcuni seguaci di compilatori Borland le ribattezzarono Microsoft FrittenChicken (pollo fritto alla Microsoft).Fortunatamente anche il Pascal, ribattezzato Delphi, si evolse in questo senso, anzi la Borland feceun ulteriore passo avanti predisponendo un ambiente Visuale dove le sue librerie VCL (VisualComponent Library) vengono aggiunte e rimosse tramite semplici tecniche Drag & Drop (tipichedegli ambienti RAD) con un sistema molto simile al Visual Basic.La differenza sostanziale tra Visual Basic e Delphi è però che quest'ultimo è un linguaggiorealmente compilato e quindi ci dà la possibilità di creare eseguibili anche nella vecchia maniera(tramite cioè la programmazione strutturata).Vi chiederete ora il perché dobbiate seguire questo capitolo quando potete farne bellamente ameno... La risposta è abbastanza semplice, in alcuni casi è consigliabile sapere cosa Delphi prepara"dietro le quinte" e l'unico modo per farlo è imparare la stesura di applicazioni strutturate.

 LA WINDOWCLASS

Il primo passo per la creazione di una finestra in Windows è la definizione di una suaWindowClass, una WindowClass altro non è che un record di tipo TWndClassEx contenente leinformazioni di base di una finestra.

Definizione del record TWndClassEx in C++

typedef struct _WNDCLASSEX { // wcUINT cbSize; //SizeOf del record stesso

UINT style; //Stile speciale della finestraWNDPROC lpfnWndProc; //Puntatore alla Window Procedureint cbClsExtra;

Page 40: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 40/57

  40

int cbWndExtra;HANDLE hInstance; //Handle dell'istanza dell'applicazioneHICON hIcon; //Handle dell'icona della finestraHCURSOR hCursor; //Handle del puntatore del mouseHBRUSH hbrBackground; //Handle del pennello

LPCTSTR lpszMenuName;LPCTSTR lpszClassName; //Nome della classeHICON hIconSm; //Handle della small icon} WNDCLASSEX;

La classe andrà poi registrata tramite RegisterClassEx(NomeClasse).

 LA WINDOW PROCEDURE

Come avrete notato nel campo lpfnWndProc si deve specificare un puntatore ad una fantomaticaWindow Procedure. Ma cos'è? Molto semplice una funzione CallBack! Una funzione CallBack èuna funzione che viene chiamata direttamente dal sistema operativo, ad esempio quandoridimensioniamo una finestra Windows spedisce un messaggio WM_SIZE alla Window Proceduredella finestra ridimensionata e all'interno di questa funzione il programma svolgerà le operazioninecessarie al ridimensionamento.

 Nella nostra applicazione la Window Procedure sarà così definita

function WindowProc(Window: HWnd; Message: Cardinal; WParam: Word; LParam:Longint): LongInt; stdcall;beginResult:= DefWindowProc(Window, Message, WParam, LParam);

end;

Come già spiegato nella prima parte del capitolo DefWindowProc serve per richiamare lefunzionalità standard della finestra. In effetti l'assegnamento di Result è del tutto inutile, se volete

 potete tranquillamente rimuoverlo...

 LA CODA DEI MESSAGGICome già accennato Windows è un sistema operativo basato sulle funzioni callback, quando l'utenteesegue un'azione su di una finestra Windows manda un messaggio alla sua window procedure. InPascal i messaggi sono definiti nella unit Messages che dovrà per tanto essere inclusa in tutti i

 progetti Delphi e sono, come da convenzione Microsoft, preceduti da WM_ (Window Message). Il

 programmatore Delphi che si scontra con i messaggi tende a confonderli con gli eventi previstidall'ambiente, in realtà gli eventi Delphi sono costruiti attorno ai messaggi Windows.In questa tabella potete vedere alcuni tra i più diffusi messaggi con il loro corrispettivo (quando

 presente) evento Delphi.

Messaggio Windows  Evento Delphi 

WM_PAINT TForm.OnPaint

WM_COMMAND TMenuItem.OnClick

WM_SYSCOMMAND

WM_KEYDOWN TForm.OnKeyDown

WM_KEYUP TForm.OnKeyUp

Page 41: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 41/57

  41

Come è quindi evidente è importante conoscere come gestire i messaggi in quanto non sempre unmessaggio che intendiamo sovrascrivere è accessibile da un evento Delphi. Generalmente il

 programmatore Delphi che intende intercettare un messaggio lo può fare in quattro diversi modi:

Tramite l'evento Delphi corrispondente

Sovrascrivendo la Window Procedure dell'oggetto Tform ..\Esempi\wndproc.zipIncludendo la direttiva Message nella definizione di un

metodo..\Esempi\msg.zip

Tramite le tecniche di subclassing ..\Esempi\subclass.zip

L'ultimo metodo è generalmente più complesso da gestire e consuma più risorse Windows, tuttaviaè indispensabile per creare componenti VCL discendenti da TComponent che devono riceveremessaggi dell'oggetto Parent, quindi per completezza è stato incluso. Si è invece tralasciata lasovrascrittura di DefaultHandler, questo metodo è in genere sconsigliato, personalmente consiglioai programmatori di propendere verso la gestione tramite direttiva Message. Per completare la

conoscenza dei messaggi Windows consiglio chi volesse saperne di più di informarsi pure sulle APISendMessage, PostMessage e RegisterWindowMessage. Comunque le conoscenze acquisite inquesto contesto sono già sufficienti per la creazione di diverse applicazioni basate su messaggi nonincapsulati da eventi Delphi.

CREATEWINDOWEXQui le cose si fanno serie ;-)Per creare "fisicamente" una finestra si deve usare l'API CreateWindowEx, per la verità se non siutilizzano gli stile estesi si potrebbe usare anche l'API CreateWindow ma è meglio familiarizzarefin da subito con quest'API.

Definizione CreateWindowEx in C++HWND CreateWindowEx(DWORD dwExStyle, // extended window styleLPCTSTR lpClassName, // address of registered class nameLPCTSTR lpWindowName, // address of window nameDWORD dwStyle, // window styleint x, // horizontal position of windowint y, // vertical position of windowint nWidth, // window widthint nHeight, // window heightHWND hWndParent, // handle of parent or owner windowHMENU hMenu, // handle of menu, or child-window identifierHINSTANCE hInstance, // handle of application instanceLPVOID lpParam // address of window-creation data);

Se la funzione "succede" verrà ritornato l'handle della finestra creata.

Dopo tanta teoria altro non resta che provare il seguente esempio...

program WinClk;

usesWindows,

Page 42: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 42/57

  42

  Messages;

constAppName = 'WinClk';btnText = 144;

function WindowProc(Window: HWnd; Message: Cardinal; WParam: Word;LParam: Longint): LongInt; stdcall;beginCase Message ofWM_CLOSE : Halt;WM_COMMAND:Case wParam ofbtnText:MessageBox(Window, 'This is only a text', AppName, 0);

end;end;

Result:= DefWindowProc(Window, Message, WParam, LParam);end;

procedure WinMain;varWindow: HWnd;Message: TMsg;

constWindowClass: TWndClassEx = (style: 0;lpfnWndProc: nil;cbClsExtra: 0;cbWndExtra: 0;hInstance: 0;hIcon: 0;hCursor: 0;hbrBackground: 0;lpszMenuName: 'MyFirst';lpszClassName: AppName);

beginWindowClass.cbSize:= SizeOF(WindowClass);WindowClass.lpfnWndProc:= TFnWndProc(@WindowProc);

if HPrevInst = 0 then beginWindowClass.hInstance:= HInstance;WindowClass.hIcon := LoadIcon(0, IDI_APPLICATION);WindowClass.hCursor := LoadCursor(0, idc_Arrow);WindowClass.hbrBackground:= COLOR_WINDOW;

if RegisterClassEx(WindowClass) = 0 thenHalt(255);

end;

Window:= CreateWindowEx(0,AppName, {Class name}'Windoze Clock', {Window name}ws_OverlappedWindow, {style}cw_UseDefault, {X}cw_UseDefault, {Y}cw_UseDefault, {Width}cw_UseDefault, {Height}

0, {WndParent}0, {Menu}HInstance, {Instance}nil); {structure creation parameter}

Page 43: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 43/57

  43

 CreateWindow('button', 'bla bla', WS_CHILD or WS_VISIBLE orBS_PUSHBUTTON, 30, 30, 70, 70, Window, btnText, HInstance, nil);

If Window = 0 Then Halt;

ShowWindow(Window, CmdShow);UpdateWindow(Window);

while GetMessage(Message, 0, 0, 0) dobegin{This translates virtual-key messages into character messages.}TranslateMessage(Message);DispatchMessage(Message); {The translated message is now 'mailed'

out.}end;

Halt(Message.wParam);

end; {WinMain}

{****************************}

beginWinMain; {By this time it is simple <G>}

end. 

La fatica è stata ricompensata: se la compilazione andrà a buon fine avrete un eseguibile di appena15-16Kb! Da oggi se un programmatore C ve la mena che il Delphi non può creare applicazionicompatte snocciolategli questo progetto ;-)

Vi consiglio di dare un'occhiata al progetto, interamente creato dal sottoscritto, 'wincp.zip'. Lacomplessità è di livello medio, ma nel seguito del capitolo verranno spiegati tutti i concettifondamentali per una corretta comprensione dell'applicazione.

 ATTENZIONE, CAPITOLO NON ANCORA COMPLETATO, ATTENDETE, ATTENDETE ;-)

Page 44: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 44/57

  44

Capito lo 14

Conclusioni sulla programmazione DelphiComplimenti,…Come per cosa? Ma per avere completato il corso Delphi ;-) In questo capitolo tratteremo ledomande più frequenti che vengono poste da un novello programmatore Delphi.

TIPS PER PRINCIPIANTI

1 - Come posso convertire una String in un Integer e viceversa? Potete facilmente convertire una String in Integer con la funzione STRtoINT; INTtoSTR lavora nelsenso opposto.

2 - Delphi può convertire un tipo Currency in String?

A quanto pare non può. Potete comunque utilizzare la unit 'curunit.zip' che dà la possibilità diaccedere alle funzioni CURtoSTR e STRtoCUR. Per usare questa unit dovete aggiungerla al vostro progetto; dopo di ciò dovete aggiungere CurUnit nella parte uses della vostra unit. Notate che laconversione viene effettuata secondo le regole della vostra lingua impostata in Windows, quindi perl'italiano bisogna usare "," come separatore decimale e "." come separatore di migliaia. Quindi1.000.000,23 restituisce 1000000.23. Se non funziona, mandatemi una e-mail con il messaggio dierrore che ricevete.

3 - Sto cercando un modo per nascondere la Caption (o Title) bar della mia applicazione.

Vorrei avere una finestra ridimensionabile senza Caption Bar. E' possibile?

Potreste provare questo metodo connesso all'evento onCreate:

SetWindowLong(Handle,GWL_STYLE, GetWindowLong(Handle,GWL_STYLE) AND NOTWS_CAPTION);ClientHeight := Height; 

4 - Come posso fare un componente TEdit che perde il focus quando viene premuto ENTER?  Nella cartella 'Esempi' c'è il componente 'ems.zip' che passa il focus al componente successivoquando l'utente preme ENTER.

5 - Qual è il modo più semplice per catturare le immagini in Windows? procedure TScrnFrm.GrabScreen;var

DeskTopDC: HDc;DeskTopCanvas: TCanvas;DeskTopRect: TRect;

beginDeskTopDC:= GetWindowDC(GetDeskTopWindow);DeskTopCanvas:= TCanvas.Create;DeskTopCanvas.Handle:= DeskTopDC;

DeskTopRect:= Rect(0,0,Screen.Width,Screen.Height);

ScrnForm.Canvas.CopyRect(DeskTopRect,DeskTopCanvas,DeskTopRect);

ReleaseDC(GetDeskTopWindow,DeskTopDC);

end; 

Page 45: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 45/57

  45

6 - Come posso fermare l'esecuzione in Delphi (come Stop in V.B.)?  Non c'è un modo in Delphi di fermare l'esecuzione del programma. Comunque in Delphi 3.0 potete

utilizzare la procedura di assertion di debug. Per esempio, se Delphi trova Assert(False,

'Program Stopped'); il compilatore stoppa l'esecuzione del progetto e potete utilizzare Step Overo Trace Into per debuggare la vostra procedura. Se avete una copia di Delphi 2.0 potete fare una

 procedura VBStop mettendo un errore in una sezione try .. except.

7 - Come posso trascinare e muovere componenti a runtime?

Questo funzionerà con un TPanel.

procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift:TShiftState; X, Y: Integer);constSC_DragMove = $F012;

beginReleaseCapture;(sender as TWinControl).perform(WM_SysCommand, SC_DragMove, 0);

end;

8 - Come posso intercettare i miei hotkeys? Primo: settate il KeyPreview del form a true;Quindi, fate qualcosa di simile:

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; 

9 - Windows, web pages, programmi multimediali, etc. utilizzano gli sfondi…

 Naturalmente potete mettere un componente Image sul vostro form e settare la sua proprietàAlignment a Client per mettere uno sfondo sul vostro form. Ma c'è un altro modo per farlo:

1. Aggiungete quello che segue alla sezione Public declarations del form:bmpBackground : TBitmap; 

2. Fate doppio click sul form e aggiungete il codice di inizializzazione del bitmap nella

 procedura FormCreate:bmpBackground := TBitmap.Create;bmpBackground.LoadFromFile('c:\windows\setup.bmp');

3. Andate nell'elenco degli eventi del form e fate doppio click su OnPaint. Aggiungete lelinee seguenti alla procedura FormPaint:

Canvas.Draw( 0, 0, bmpBackground );

4. Infine inserite il seguente codice nella procedura FormDestroy (OnDestroy event):bmpBackground.Free; 

Page 46: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 46/57

  46

10 - Qual è il modo più semplice per cambiare il control menu di una applicazione basata su

form? unit Unit1; 

interface 

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; 

type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); 

private { Private declarations } procedure WmSysCommand(var Msg: TWmSysCommand); message WM_SYSCOMMAND; 

public { Public declarations } 

end; 

var Form1: TForm1; 

implementation 

{$R *.DFM} 

procedure TForm1.FormCreate(Sender: TObject); var hSysMenu: hMenu; begin hSysMenu := GetSystemMenu(handle, False); 

AppendMenu(hSysMenu, MF_SEPARATOR, 0, ''); AppendMenu(hSysMenu, MF_STRING, $200, 'Always on Top'); end; 

procedure TForm1.WmSysCommand(var Msg: TWmSysCommand); begin inherited ; 

If Msg.CmdType = $200 Then Begin ShowMessage('Always on top pressed'); 

End; end; 

end. 

11 - Come far emettere un beep dal computer:messageBeep(0); 

12 - Come mettere in pausa il programma per NumSec secondi:varNumSec SmallInt; StartTime: LongInt; 

begin StartTime := now; repeat 

Application.ProcessMessages;  until Now > StartTime + NumSec * (1/24/60/60);end; 

Page 47: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 47/57

  47

 

13 - Come mostrare la clessidra del mouse (e quindi tornare indietro alla freccia):try Screen.Cursor := crHourGlass; {do something here...} 

finally 

Screen.Cursor := crDefault;end; Application.ProcessMessages;  

14 - Come ricevere il controllo dello stato di <Enter>:procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); {put this in the OnKeyPress event of any control you want...} begin {#13 is the RETURN key, or use #9 for the TAB key} if Key = #13 then begin Key := #0; {supress the bell} {do what you want to do here}; 

end; end; 

15 - Come cambiare il colore del testo in un campo DBGrid secondo il contenuto delle celle:Primo, fate doppio click sul componente Ttable sul form e aggiungete il campo a cui sieteinteressati, in questo esempio è usato il campo "Client", e se il valore di questo campo è "XXXX"allora cambierà il colore. Questo codice va messo nell'evento OnDataDrawCell:

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect; Field:TField; State: TGridDrawState);beginif Table1Client.AsString = 'XXXX' then begin

DBGrid1.Canvas.Brush.Color := clRed;DBGrid1.Canvas.Font.Color := clSilver;DBGrid1.Canvas.FillRect(Rect); {paint in the background}{now write the field value on top of the background...}DBGrid1.Canvas.TextOut(Rect.Left+2, Rect.Top+1, Field.AsString);

end;end; 

16 - Come lanciare un altro programma dal vostro (3 modi diversi!):WinExec('C:\windows\notepad.exe', SW_SHOWNORMAL); WinExec('C:\windows\notepad.exe', SW_SHOWMAXIMIZED); WinExec('C:\windows\notepad.exe', SW_SHOWMINIMIZED); 

17 - Come esaminare un'intera tabella di dati:Table1.First;x := 0; while not(Table1.Eof) dobegin {do what you have to do here} Table1.Next; 

end;

Inoltre, settando un range prima della linea Tbl1.First, potete esaminare tutti i record all'interno diquesto range utilizzando quanto già detto.

18 - Come intercettare i tasti funzione:

Per prima cosa, settate la proprietà KeyPreview del vostro form a TRUE, quindi mettete questocodice nell'evento OnKeyDown del form:

Page 48: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 48/57

  48

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift:TShiftState);beginif Key = VK_F5 thenshowMessage('I pressed the F5 key');

end; 

Inoltre, potete usare da VK_F1 a VK_F12 per gli altri tasti funzione.

19 - Come copiare tutti i valori dei campi da un record a un altro:In questo esempio dalla tabella TableSource verso TableDest, entrambe aventi la stessa struttura:

varNum: SmallInt;

beginfor Num := 0 to TableSource.FieldCount-1 dobeginTableDest.Edit;

TableDest.Fields[Num].Assign(TableSource.Fields[Num];TableDest.Post;

end;end; 

20 - Come vedere se un integer è pari o dispari:function TestForEven(TestInt: Integer): Boolean; begin if (TestInt div 2) = (TestInt/2) then result := True 

else result := False; end; 

21 - Come vedere se una string somiglia a un integer:function IsInteger(TestThis: String): Boolean; begin try StrToInt(TestThis);  

excepton EConvertError do result := False; 

else result := True; 

end; end; 

TIPS AVANZATI

1 – Può una applicazione Delphi mostrare l'effetto standard di Win '95 quando minimizzo le

finestre dell'applicazione?Si, ma non è proprio semplice. Suggerisco di osservare il mio esempio 'minsmp.zip' che mostracome ottenere quest'effetto

2 – Sto cercando un Debug Box come il Visual Basic, Delphi 2.0 ce l'ha? No, non ce l'ha. Comunque puoi installare il componente TDebugBox ('debugbox.zip') fatto da me

che è molto simile al debug box del Visual Basic.

Page 49: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 49/57

  49

3 – Qualcuno mi ha parlato di un cheat code in Delphi 2.0, è vero?

Si, digita queste parole nella finestra About Box:

|alt| A-N-D Foto di Anders Hejlsberg

|alt| T-E-A-MUn elenco dei responsabili di questo bel

 prodotto

|alt| D-E-V-E-L-O-P-E-R-S Un elenco della gente di R&D

4 – Se si ha la data 1/1/2000 e si esegue il codice seguente: DateToStr(StrToDate('1/1/2000'))

l'anno cambia da 2000 a 1900. Qual è il modo migliore per evitarlo?

Il valore della costante ShortDateTime in WIN.INI determina come DateToStr e StrToDateconvertono le stringhe. Il default è dd/mm/yy – anno a due cifre. Potete risolvere questo problemautilizzando l'istruzione

ShortDateFormat:= 'dd/mm/yyyy';nell'evento formcreate del form principale della vostra applicazione.

5 – Come posso intercettare un messaggio di windows?Penso che il tip 6 risponderà alla vostra domanda!

6 – Come posso trascinare una finestra con un click nella sua area in primo piano? Non è molto difficile: fate un nuovo progetto con il form principale chiamato Form1 e la sua unitUnit1, cambiando il suo codice con questo:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls;

typeTForm1 = class(TForm)Button1: TButton;protectedprocedure WMLButtonDown(var Message: TWmLButtonDown); message WM_LBUTTONDOWN;private{ Private declarations }public{ Public declarations }end;

varForm1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.WMLButtonDown(var Message: TWmLButtonDown);beginif Message.Keys = MK_LBUTTON Then beginDefWindowProc(handle, WM_NCLBUTTONDOWN, 2, 0) //If Left click pressed...

End Else Begin

inherited; //Else standard functionEnd;

end;end. 

Page 50: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 50/57

  50

7 - Posso vedere il codice assembly del mio programma?

Si, segui questo metodo per abilitare una nuova funzione in Delphi

• Uscite da Delphi

• Lanciate il "Registry Editor" (regedit.exe o regedt32.exe)

• Selezionate le seguenti chiavi del registro:

Version 2.0:

HKEY_CURRENT_USER\Software\Borland\Delphi\2.0\Debugging  Version 3.0:

HKEY_CURRENT_USER\Software\Borland\Delphi\3.0\Debugging  

• Aggiungete una string item chiamata "EnableCPU" e settate il suo valore a "1"(senza apici)

• Chiudete il Registry Editor

• Riaprite Delphi e selezionate "View | CPU"

Ora quando debuggherete il vostro programma, vedrete le istruzioni assembly nella nuova finestra"DisassemblyView".

9 – Sto cercando un modo per lanciare la mia applicazione all'avvio del sistemaE' abbastanza semplice copiare e incollare la vostra applicazione nel gruppo Startup per farla partireall'avvio di Windows. Ma, se volete farlo con la programmazione (alla fine del vostro programma disetup, ad esempio), o se volete che il vostro programma venga lanciato solo la prossima volta cheWindows viene avviato, la seguente funzione vi può essere d'aiuto:

procedure RunOnStartup(sProgTitle, sCmdLine: string; bRunOnce: boolean);varsKey : string;reg : TRegIniFile;

beginif( bRunOnce )then beginsKey:= 'Once';

end else beginsKey := '';

end;

reg:= TRegIniFile.Create('');

reg.RootKey:= HKEY_LOCAL_MACHINE;reg.WriteString('Software\Microsoft' + '\Windows\CurrentVersion\Run' + sKey +#0, sProgTitle, sCmdLine );reg.Free;

end; 

Uso:sProgTitle: Nome del vostro programma. Generalmente parlando, potrebbe essere quello che volete.sCmdLine: Questo è il percorso completo del vostro eseguibile.

 bRunOnce: Settatelo a True se volete lanciare il vostro programma solo una volta. Se questo parametro è False, il vostro programma verrà lanciato ogni volta che Windows parte.

Esempio:RunOnStartup( 'Title of my program', 'MyProg.exe', False );

Page 51: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 51/57

  51

10 – Qual è un modo per ottenere i messaggi del joystick?

Potete utilizzare l'API JoySetCapture e controllare MM_JOY1MOVE o MM_JOY2MOVE. Sevolete un componente già pronto, allora potete utilizzare ' joy10.zip' (che comunque è in fase di betatesting).

11 – Ho visto un ListBox draggabile (Access '95), ...E' davvero semplice rendere un ListBox draggabile in Delphi, basta sovrascrivere il metodoParamCreate method ('flist.zip').

12 – Quale sistema operativo è in esecuzione?

La variabile Win32Platform  (definita in SysUtils.pas) restituisce il sistema operativo in cui è inesecuzione il vostro progetto Delphi. Il risultato può essere:

Valore  Sis. Op.  Risultato  VER_PLATFORM_WIN32S  Win32s 0 VER_PLATFORM_WIN32S_WINDOWS  Windows 95 1 VER_PLATFORM_WIN32_NT  Windows NT 2

13 – I programmi come possono effettuare l'allineamento a destra del menu item?

 Non è così difficile: provate questa procedura:

procedure TForm1.FormCreate(Sender: TObject);varMInfo: TMenuItemInfo;Buffer: array [0..79] of char;

beginMInfo.cbSize := SizeOf(TMenuItemInfo);

MInfo.fMask := MIIM_TYPE;MInfo.dwTypeData := Buffer;MInfo.cch := SizeOf(Buffer);// Ottiene le informazioni del menuif GetMenuItemInfo(MainMenu.Handle, 2, True, MInfo) thenbeginMInfo.fMask := MIIM_TYPE;MInfo.fType := MInfo.fType or MFT_RIGHTJUSTIFY;// Giustifica il menu a destraSetMenuItemInfo(MainMenu.Handle, 2, True, MInfo);

end;end; 

14 – Le finestre standard sono così noiose...Siete alla ricerca di una finestra più interessante? Il codice seguente crea un Form arrotondato,

 provate ad eseguire questa applicazione.

procedure TForm1.FormCreate(Sender: TObject);varR: HRgn;

beginR:= CreateEllipticRgn(1,1,Width, Height);SetWindowRgn(Handle, R, True);

end; 

Veramente carina!

Page 52: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 52/57

  52

15 – Come creare una Kiosk application?

Potete creare facilmente una kiosk application in Win '95 aggiungendo questo codice all'eventoOnCreate.

var B: LongBool;beginSystemParametersInfo (SPI_SCREENSAVERRUNNING, Word(True), @B, 0);BorderStyle := bsNone;BorderIcons := [];FormStyle := fsStayOnTop;Height := Screen.Height;Width := Screen.Width;Top := 0;Left := 0;Show;ShowWindow(Application.handle, SW_HIDE);

end; 

In FormDestory aggiungete semplicemente questo codice:

var B: LongBool;beginSystemParametersInfo (SPI_SCREENSAVERRUNNING, Word(False), @B, 0);

end; 

Ricordate anche di applicare un button col metodo Close...E' una applicazione divertente, non è vero?

16 – Perché gli eseguibili di Delphi sono così grandi?

Delphi è un ambiente RAD, quindi nell'eseguibile sono immagazzinate un sacco di informazioni,

anche se non sono necessarie...Ma c'è un modo per creare un eseguibile piccolo (meno di 50Kb)? Si, e no, potete creare unaapplicazione utilizzando solo le API, e quindi la grandezza sarà limitata a meno di 17Kb; seaggiungete una unit CommCtrl la grandezza aumenterà a 34Kb, ma quando utilizzate Forms Unit ilvostro eseguibile sarà di circa 200Kb! :-(Ho fatto un progetto ('wincp.zip') che utilizza solo chiamate API. E' di soli 34.5Kb ma non è unRAD! Notate che per comprendere questo codice dovete conoscere veramente bene la

 programmazione in C!

17 – Mi serve un progetto che mostri come rotare del testo.Se state cercando un modo per rotare del testo, il progetto 'rotate.zip' vi insegnerà a manipolareTFont Object per questa utile funzione!

18 – Come faccio a linkare dei files .wav nei miei progetti?

Con l'utilizzo delle risorse potete includere nell'eseguibile di una applicazione tutti i files che viservono e caricarli direttamente in memoria! Il mio progetto 'wavesmp.zip' utilizza un file .res filecompilato con BRCC32.EXE (Borland Recource Compiler, guardate nella directory bin di Delphi).Vengono linkati anche files di testo! Gustatevelo!

19 – Come fare una applet Control Panel?

Soluzione: utilizzate il mio esempio 'cplapplet.zip' 

E' veramente semplice da comprendere, penso che questo progetto risolverà i vostri problemi ;-)

Page 53: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 53/57

  53

20 – Come includere in una Status Bar una Progress Bar?

Soluzione: utilizzate il mio esempio 'barsmp.zip'

21 – Qualcosa sul tracciare disable bitmap?Questo problema mi ha toccato di recente, fortunatamente ho trovato questa procedura nel

componente TExplorerButton (cercate in DSP). Spero che l'autore non si arrabbi :-))

procedure DrawDisabledBitmap(Canvas: TCanvas; x, y: Integer; bmp:TBitmap);(* This code come from* TExplorerButton component version 2.4* (c)1996 Fabrice Deville* [email protected]* http://www.tornado.be/~fdev/*)var MonoBmp: TBitmap;beginMonoBmp := TBitmap.Create;

tryMonoBmp.Assign(bmp);MonoBmp.Canvas.Brush.Color := clBlack;MonoBmp.Monochrome := True;Canvas.Brush.Color := clBtnHighlight;SetTextColor(Canvas.Handle, clBlack);SetBkColor(Canvas.Handle, clWhite);BitBlt(Canvas.Handle, x+1, y+1, bmp.Width, bmp.Height,MonoBmp.Canvas.Handle, 0, 0, $00E20746);Canvas.Brush.Color := clBtnShadow;SetTextColor(Canvas.Handle, clBlack);SetBkColor(Canvas.Handle, clWhite);BitBlt(Canvas.Handle, x, y, bmp.Width, bmp.Height,

MonoBmp.Canvas.Handle, 0, 0, $00E20746);finallyMonoBmp.Free;

endend; 

22 – La via più semplice per fare dei Menu fighi (come Office '97) ?La via più semplice? Utilizzate il mio componente 'advmenu.zip'!

23 – Posso far apparire il menu avvio da codice?

Certamente! Provate questo codice...

procedure TForm1.Button1Click(Sender: TObject); var hwnd, 

hwndchild: Integer; begin // Get the taskbar handle hwnd:= FindWindowEx(0, 0, 'Shell_TrayWnd', ''); // Get the Start button handle hwndChild:= FindWindowEx(hwnd, 0, 'button', ''); // Just to test i press the button ;-) SendMessage(hwndChild, WM_LBUTTONDOWN, 0, 0); 

end;

24 – Come controllare se Delphi è in esecuzione? 

if ((FindWindow('TApplication', 'Delphi 3') <> 0) and(FindWindow('TPropertyInspector', nil) <> 0)) then //... 

Page 54: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 54/57

  54

Appendice A

Object Oriented programming: questo sconosciutoCODICE+DATI=OGGETTOFinora si sono sempre create due sezioni distinte: quella dei dati e quella del codice; un oggetto si

 può immaginare come l'evoluzione di un record ma che al contrario di questo contiene procedure efunzioni. Ad esempio l'oggetto TTelevisione disporrà delle proprietà Spina, Antenna, Interruttore,Volume, Frequenza e dei metodi   Accendi, Spegni, Sintonizza, AlzaVolume e AbbassaVolume. Alivello di codice l'oggetto TTelevisione apparirà definito come segue:

Type TTelevisione = classSpina: (Inserita, Disinserita);Antenna: (Portatile, Normale, Satellitare);Interruttore: (ON, OFF);Volume: Byte;

Frequenza: Byte;procedure Accendi;procedure Spegni;procedure Sintonizza(Canale: Byte);procedure AlzaVolume;procedure AbbassaVolume;constructor Create;

end;

Procedure TTelevisione.Accendi;BeginIf Spina = Disinserita ThenSpina:= Inserita;

If Interruttore = OFF ThenInterruttore:= ON;End;

Procedure TTelevisione.Spegni;BeginIf Spina = Inserita ThenSpina:= Disinserita;

If Interrutore = ON ThenInterruttore:= OFF;

End;

Procedure TTelevisione.Sintonizza(Canale: Byte);BeginIf Frequenza <> Canale ThenFrequenza:= Canale;

End;

Procedure TTelevisione.AlzaVolume;BeginVolume:= Volume + 10;

End;

Procedure TTelevisione.AbbassaVolume;BeginVolume:= Volume - 10;

End;

Constructor TTelevisione.Create;Begin

Page 55: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 55/57

  55

  Frequenza:= 1;Spina:= Inserita;Interruttore:= ON;Volume:= 30;Antennza:= Satellitare;

End;

Per utilizzare l'oggetto TV basterà creare una variabile che faccia riferimento all'oggetto TTelevisione stesso, ad esempio il codice Var TV: TTelevisione;  rende possibile utilizzarel'oggetto TTelevisione tramite la variabile TV. Il Primo passo sarà quindi di inizializzare l'oggetto

TV tramite l'istruzione TV:= TTelevisione.Create;  cioè assegna alla variabile TV l'oggettoTTelevisione inizializzato dal constructor Create; Vi chiederete ora cosa sia un constructor, o

 perché si debba seguire questa prassi, le risposte non sono semplici e dovrete per ora accontentarvidi imparare questo come un fatto scontato perché tutti gli oggetti sono strutturati in questo modo ( è

buona norma far iniziare il nome di un oggetto con la T). Come consuetudine di questo corso propongo un piccolo sorgente esplicativo.

Program WinForm;

UsesForms;

VarfrmHello: TForm;

BeginfrmHello:= TForm.Create(nil);frmHello.Caption:= 'Hello Object programming';

frmHello.Position:= poScreenCenter;frmHello.ShowModal;frmHello.free;

End.

Il programma crea una variabile frmHello derivata dall'oggetto TForm e quindi ne eredita tutti i

metodi, le proprietà nonché le caratteristiche intrinseche  non accessibili direttamente dal programmatore.

L'istruzione frmHello:= TForm.Create(nil);  assegna alla variabile l'oggetto TForminizializzato; probabilmente nel constructor create vengono settate a nulle le variabili interne, vienesettata un'icona di default e preparate alcune proprietà che determinano l'aspetto della finestra(forma, colore, etc.). Nell'istruzione seguente la proprietà caption viene cambiata in modo di

visualizzare uno specifico titolo, la finestra viene quindi centrata (frmHello.Position:=

 poScreenCenter;) e visualizzata (frmHello.ShowModal;).Infine è buona norma richiamare il metodo free di ogni oggetto  per liberare tutta la memoriaallocata dallo stesso tramite il constructor create.

RICHIAMO  E' ora spiegato perché quando si crea una nuova Form viene creato automaticamente ilcodice

Type TForm1 = class(TForm);......

Page 56: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 56/57

  56

  ...

VarForm1: TForm1;

Cioè viene creato un nuovo oggetto TForm1 che eredita automaticamente tutte le

caratteristiche di TForm (detto oggetto Ancestor o Padre). La riga Var Form1: TForm1 rende accessibile l'oggetto TForm1 tramite la variabile Form1.

 L'EREDITARIETA'

Come già accennato un oggetto può essere un "erede" di un altro. L'OOP permette però all'oggettodiscendente di modificare il comportamento standard dell'oggetto ancestor. Ad esempiosupponiamo di voler creare l'oggetto TAdvancedTelevision discendente dell'oggetto TTelevisionche dispone di tutte le caratteristiche della classe ancestor ma anche delle proprietà colore e forma.L'oggetto TAdvancedTelevision sarà così definito

Type TAdvancedTelevision = class(TTelevision)Colore: (Rosso, Giallo, Verde, Blu);Forma: (Cubo, Parallelepipedo, Standard);constructor Create; ovverride;

constructor TAdvancedTelevision.Create;begininherited Create;Colore:= Rosso;Forma:= Standardend;

Si noti che dopo la definizione del prototipo del constructor Create è stata inserita la direttivaovverride per comunicare al compilatore che si sa sovrascrivendo il construtor TTelevision, tuttavia

la prima istruzione del construtor è inherited Create;  che serve per ereditare il construtordell'ancestor. Se non si provvedesse ad ereditare il vecchio constructor l'oggettoTAdvancedTelevision non avrebbe le proprietà Volume, Antenna, etc. inizializzate.

TIPQuando si sovrascrive un constructor la prima istruzione deve essere

necessariamente inherited Create;, viceversa nella sovrascrittura di un destructor

l'istruzione inherited Destructor; deve essere l'ultima, questo per evitare perditedi memoria o scorrette inizializzazioni delle variabili. 

Si noti che per ereditare un oggetto si utilizza l'istruzione Type Discendente =

class(Antenato).

TIPIn effetti anche l'oggetto TTelevisione era un discendente della classe TObject,

l'istruzione Type Discendente = class  corrisponde alla definizione Type

Discendente = class(TObject).L'oggetto TObject mette a disposizione un

constructor Create, un destructor Destroy e infine un metodo free.

Page 57: Programmazione Delphi

7/24/2019 Programmazione Delphi

http://slidepdf.com/reader/full/programmazione-delphi 57/57

Un'ultima osservazione sull'ereditarietà è che un oggetto discendente può essere postoall'assegnazione (:=) con l'antenato ma non viceversa. A livello di codice questo significa che:

• Discendente:= Antenato; 

è sintatticamente corretto, ma viceversa

• Antenato:= Discendente; 

 provoca un errore di compilazione. questo perché l'oggetto ancestor non dispone di tutti i dati deldiscendente.

TIPAlcuni oggetti, specialmente quelli grafici, possono tranquillamente lavorare conl'operatore di assegnazione, tuttavia è altamente scorretto (per motivi che non sto qui

a spiegarvi). al posto dell'istruzione Bitmap1:= Bitmap2;  usare quindi

Bitmap1.Assign(Bitmap2).

La programmazione ad oggetti potrebbe sembrare in prima fase tanto complessa ma inutile, nellarealtà è più semplice ed efficacie di quanto possa sembrare da questo capitolo che purtroppo è

 puramente teorico. Nella sezione "creazione di oggetti VCL" si riprenderà quanto appreso qui permetterlo in pratica con esempi in Delphi.