Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf ·...

54
Prof. Tombolini Gino Appunti di programmazione Visual Basic 1 Indice Lezione 1 Introduzione a Visual Basic. Lezione 2 Le variabili in Visual Basic. Lezione 3 Le routine in Visual Basic Lezione 4 Le funzioni in Visual Basic. Lezione 5 Il primo programma in Visual Basic. Lezione 6 Convenzioni. Lezione 7 Interfaccia grafica e controlli standard. Lezione 8 Operatori Booleani e struttura IF Lezione 9 Nozioni avanzate sulle variabili. Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop Lezione 13 Struttura Select Case Lezione 14 Stringhe Lezione 15 Debug e gestione degli errori Lezione 16 Gestione dei Files Lezione 17 Gli Oggetti Lezione 18 Studiare un'applicazione professionale : il Blocco Note di Windows Lezione 19 I Menù Lezione 20 Controlli: approfondimenti Lezione 21 Date e orari Lezione 22 L’oggetto Printer Introduzione al Visual Basic

Transcript of Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf ·...

Page 1: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

1

Indice Lezione 1 Introduzione a Visual Basic. Lezione 2 Le variabili in Visual Basic. Lezione 3 Le routine in Visual Basic Lezione 4 Le funzioni in Visual Basic. Lezione 5 Il primo programma in Visual Basic. Lezione 6 Convenzioni. Lezione 7 Interfaccia grafica e controlli standard. Lezione 8 Operatori Booleani e struttura IF Lezione 9 Nozioni avanzate sulle variabili. Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop Lezione 13 Struttura Select Case Lezione 14 Stringhe Lezione 15 Debug e gestione degli errori Lezione 16 Gestione dei Files Lezione 17 Gli Oggetti Lezione 18 Studiare un'applicazione professionale : il Blocco Note di Windows Lezione 19 I Menù Lezione 20 Controlli: approfondimenti Lezione 21 Date e orari Lezione 22 L’oggetto Printer

Introduzione al Visual Basic

Page 2: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

2

Fig.3: La finestra delle Proprietà visualizza le proprietà dell'oggetto seleziono sul form. A seconda dell'oggetto seleziono, le proprietà visualizzate nella tabella saranno differenti. Per modificare una proprietà fare clic sulla casella corrispondente alla seconda colonna. A questo punto può essere richiesto di immettere manualmente di come numeri, lettere o simboli, oppure scegliere tra più possibilità de o ancora potrà comparire una finestra di dialogo collega all'argomento.

Prima lezione - Introduzione a Visual Basic Innanzitutto è bene spiegare cosa si intende per Visual Basic: con questo termine si può intendere sia il programma che consente di sviluppare applicazioni per Windows, sia il linguaggio di programmazione in cui tali applicazioni vengono scritte. Il Visual Basic è chiamato così perché deriva dal linguaggio BASIC (Beginners All-Purpose Symbolic Instruction Code), un tipo di linguaggio semplice e molto diffuso che era implemento, ad es., nei mitici Apple II e Commodore 64; nel corso dell'evoluzione del BASIC si sono aggiunte molte istruzioni e sono cambiate diverse caratteristiche, la principale delle quali è indica dal termine "visual": come vedremo tra poco, infatti, per progettare l'interfaccia grafica di un'applicazione si ha a disposizione un ambiente grafico in cui si possono utilizzare numerosi componenti di vario tipo, come i pulsanti, le caselle di testo ecc. In questo modo è possibile creare l'interfaccia grafica in modo semplice e veloce, senza dover ogni volta scrivere le istruzioni necessarie per ordinare al computer di creare le finestre di cui abbiamo bisogno, come invece accadrebbe se utilizzassimo un linguaggio non "visuale". Cominciamo a vedere come si presenta l'ambiente di progettazione di Visual Basic 6.0: quello che vi si

presenta è l'IDE (Integrated Development Environment, Ambiente di Sviluppo Integrato), e al suo interno ci sono diverse finestre: scegliendo di creare un nuovo progetto "exe standard"

(Fig.1) al centro compare una finestra con un "form": i form rappresentano le finestre che saranno visualizzate dalla vostra applicazione; a sinistra compare la "casella degli strumenti" (Fig.2), con una serie di icone ciascuna delle quali rappresenta un particolare oggetto inseribile sul form: ad es., ci sono le label (etichette), le textbox (caselle di testo), i commandbutton (pulsanti), ecc.; selezionando un'icona è possibile disegnare direttamente sul form l'oggetto ad essa associato. A destra compaiono la finestra di gestione dei progetti e la finestra delle proprietà(Fig.3): la prima fornisce l'insieme dei file che compongono il progetto di applicazione che ste creando, mentre la seconda visualizza le proprietà dell'oggetto seleziono sul form: all'inizio, dato che il form è vuoto, la finestra delle proprietà elencherà proprio quelle del form; inserendo un oggetto qualunque sul form, verranno visualizzate le proprietà dell'oggetto appena inserito. Ogni oggetto, o controllo, presente nella casella degli strumenti è dotato di un insieme di proprietà, metodi ed eventi.

Proprietà le proprietà rappresentano gli attributi che definiscono l'aspetto e varie funzionalità di ogni controllo; ad es., la proprietà Name indica il nome con cui quel controllo è identificato all'interno del codice; le proprietà Height e Width indicano l'altezza e la larghezza del controllo, ecc. Molte proprietà sono comuni a diversi oggetti (ad es. qualunque controllo dispone della proprietà Name), altre invece sono specifiche di un controllo particolare (ad es., la proprietà Interval è disponibile solo per il controllo Timer). Solitamente le proprietà possono essere lette e anche impostate, ovvero è possibile sia leggere il valore della proprietà, sia assegnare ad essa un nuovo valore: in tal caso si dice che la proprietà è di lettura e scrittura; tuttavia esistono anche proprietà di sola lettura (alle quali non è possibile assegnare un nuovo valore) e di sola scrittura.

Metodi un metodo è un'azione che l'oggetto può eseguire: ad es., l'oggetto form dispone dei metodi Show e Hide, che rispettivamente mostrano oppure nascondono il form all'utente; il controllo picturebox, invece, dispone del metodo Pset, che serve ad assegnare un certo colore ad un punto del picturebox. Come per le proprietà, alcuni metodi sono comuni a diversi controlli, altri invece sono specifici di un controllo particolare.

Eventi gli eventi sono, come dice il nome, "situazioni" generate dal controllo quando si verificano certe condizioni; solitamente, ma non necessariamente, gli eventi si producono in conseguenza di un'azione dell'utente: per es., quando l'utente fa clic su un pulsante, il controllo che identifica quel pulsante genera un evento click; un esempio di evento non generato dall'utente è l'evento Timer del controllo omonimo, che viene generato dopo un certo numero di millisecondi specificato dalla proprietà Interval.

Fig.1: Apertura di un nuovo progetto "EXE Standard"

Fig.2: Casella degli strumenti utilizzabili in Visual Basic. Quelli visibili all'apertura dell'applicazione sono i controlli standard (o di default). Per visualizzare o gestire l'aggiunta/rimozione di altri controlli cliccare col pulsante destro del mouse sulla finestra "Generale".

Page 3: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

3

Cliccando due volte di seguito su un controllo contenuto nel form, o sul form stesso, si apre un'altra finestra, l'editor del codice, in cui il programmatore può scrivere le istruzioni necessarie a far compiere al computer determinate operazioni. L'editor del codice si presenta con un'area bianca in cui va scritto, appunto, il codice, e con due caselle a discesa poste nella parte superiore della finestra

(Fig.4): la casella di sinistra fornisce l'elenco degli oggetti disponibili sul form seleziono, oltre alla sezione Generale, che serve per le dichiarazioni, come vedremo oltre; la casella di destra fornisce invece un elenco degli eventi associi al controllo seleziono nella casella di sinistra.

Ad es., selezionando nella casella di sinistra l'oggetto form e nella casella di destra l'evento click, verrà visualizza nell'area del codice la sezione relativa all'evento click dell'oggetto form, in cui il programmatore può scrivere le istruzioni che devono essere eseguite quando l'utente fa clic sul form. Per accedere alle proprietà e ai metodi dei vari controlli, bisogna scrivere il nome del controllo seguito da un punto "." e dal nome del metodo o della proprietà (ad es. "Form1.Show" oppure "Command1.Caption").

Come ogni linguaggio di programmazione, il Visual Basic è costituito da un insieme di parole chiave, funzioni, istruzioni che seguendo determinate regole sintattiche permettono al programmatore di impartire "ordini" al computer al fine di produrre un certo risultato

Cominciamo col vedere come si dichiarano le variabili, ovvero come si fa a ordinare al computer di utilizzare una certa variabile e di assegnare a quest'ultima un certo valore; la sintassi per dichiarare una variabile in Visual Basic è la seguente:

Dim NomeVariabile As TipoVariabile Dim Pippo As Integer mentre per assegnarle un valore bisogna scrivere il nome della variabile, il simbolo "=" e il valore da assegnare (es.: pippo=10). Il nome della variabile è a completa discrezione del programmatore, tuttavia bisogna osservare qualche restrizione: ad es., il nome non può essere più lungo di 255 caratteri, non può contenere punti o spazi, deve iniziare con una lettera, non può essere uguale a una delle parole-chiave utilizzate da Visual Basic Ad es., non si può fare: Dim dim As Integer perché "dim" è una parola riserva per la dichiarazione delle variabili. Il tipo della variabile indica il tipo di valore che è possibile assegnare alla variabile, ed è possibile scegliere tra diverse alternative; i tipi principali supporti da Visual Basic sono:

Tipo di dati

Spazio occupato in memoria

Intervallo di valori

Byte 1 byte 0/255 Integer 2 byte -32768/+32767 Long 4 byte -2147483648 / +2147483647

Single 4 byte Numeri dotati di decimali virgola mobile e singola precisione. Max 3.4E+38

Double 8 byte Come i single ma a doppia precisione String variabile da 0 a circa 65000 caratteri Currency 8 byte Numeri dotati di decimali virgola fissa. Max 9.2E+14 Date 8 byte Memorizza date e ore Boolean 2 byte True (vero) o false (falso) Variant 16 byte Accoglie qualsiasi tipo di dato

Come si può notare, i tipi di variabili si distinguono sia per la quantità di memoria che richiedono, sia per l'intervallo di valori che possono assumere. La dichiarazione delle variabili, in Visual Basic, non è obbligatoria: quando Visual Basic trova un nome di variabile non dichiaro, crea automicamente una variabile con quel nome (è ciò che si chiama dichiarazione implicita); questa può sembrare una bella comodità, ma in realtà è più una fonte di errori che altro. Basta pensare a cosa succede se scrivo:

Dim Pippo As Integer Pippo = 10 Pipo = 5

Per evitare questo tipo di errori, è possibile rendere obbligatoria la dichiarazione esplicita di TUTTE le variabili: per fare ciò, bisogna andare sul menù strumenti, scegliere opzioni, e selezionare la casella "dichiarazione di variabili obbligatoria": nella sezione "generale" del nostro form sarà automicamente aggiunta l'istruzione: Option Explicit

che per l'appunto informa visual basic del fatto che la dichiarazione esplicita è obbligatoria. In questo modo Visual Basic genererà un errore perché riconosce che la variabile "Pipo" non è stata dichiarata.

Fig.4: Casella destra e sinistra

Page 4: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

4

Seconda lezione - Le variabili in Visual Basic Una cosa importante da tenere presente a proposito delle variabili è la loro area di visibilità: ciò deriva dal fatto che una variabile può essere dichiarata in punti diversi del codice, e cioè nella sezione dichiarazioni di un form oppure all'interno di una routine; nel primo caso, la variabile sarà visibile, e quindi potrà essere utilizzata, in tutto il form (si dice che è una variabile dichiarata a livello di modulo); nel secondo caso la variabile sarà visibile soltanto all'interno della routine in cui è dichiarata (si dice che è una variabile locale). Per capire bene la differenza proviamo ad aprire un nuovo progetto e a scrivere, nella sezione dichiarazioni del form:

Dim VarGen As Integer Public Sub Prova() Dim VarLoc As Integer VarGen=1 VarLoc=1 End Sub

e, nella routine Load del form:

Private Sub Form_Load() Prova VarGen=2 VarLoc=2 Debug.Print VarGen, VarLoc End Sub Nota: il comando Debug.Print viene utilizzato per visualizzare il valore delle due variabili nella finestra Immediata

quando il form viene caricato si verifica l'evento Load, durante il quale vengono eseguite le istruzioni che abbiamo appena inserito: dapprima viene eseguita la routine prova con le sue due istruzioni, dopodichè alle due variabili viene assegnato il valore 2; infine il valore delle due variabili viene visualizzato nella finestra "Immediata", di cui si parlerà più avanti. Per visualizzare la finestra basta andare sul menù "Visualizza" e scegliere la voce "Finestra Immediata". Ora, proviamo a mandare in esecuzione il nostro progetto andando sul menu Esegui e scegliendo Avvia, oppure premendo il tasto F5: quello che succederà è l'interruzione del programma con la visualizzazione del seguente messaggio di errore:

variabile non definita dove la variabile è quella evidenziata, cioè la variabile VarLoc. Questo succede proprio perché all'esterno della routine Prova la variabile locale VarLoc non esiste: infatti le variabili locali vengono create all'inizio della routine in cui sono dichiarate, e automicamente distrutte quando la routine finisce di essere eseguita. La variabile VarGen, invece, è visibile sia nell'evento load del form, sia nella routine prova, proprio perché è stata dichiarata nella sezione delle dichiarazioni generali del form. Faccio notare che se si prova a eliminare l'istruzione Option Explicit quando il progetto viene avvatio non si verifica alcun errore e nella finestra immediata viene stampata la riga: 2 2 Questo succede perché senza l'istruzione Option Explicit durante l'esecuzione vengono create DUE variabili VarLoc: una dichiarata esplicitamente nella routine Prova e distrutta alla fine della routine, l'altra dichiarata implicitamente nell'evento load del form e a cui viene assegno il valore 2, che viene poi correttamente visualizzato nella finestra immediata. Dato che in una applicazione possono esserci ben più di un unico form, ci si può chiedere se le variabili dichiarate a livello di modulo in un certo form siano visibili anche negli altri form: la risposta è positiva solo se nella dichiarazione delle variabili si usa la parola chiave Public, ad es.: Public VarGen As Integer questa parola chiave specifica appunto che la variabile dichiarata è pubblica, cioè è visibile in tutta l'applicazione a cui appartiene il form in cui è dichiarata; utilizzando invece la parola chiave Private o la classica Dim, la variabile sarà privata e quindi visibile solo nel form in cui è dichiarata. Visto che le variabili locali vengono create all'inizio della routine in cui sono dichiarate e distrutte alla fine, ne deriva che se la stessa routine viene richiamata più volte, la variabile viene creata e distrutta altrettante volte, ed ogni volta la variabile creata non ha alcuna connessione con la variabile omonima creata la volta precedente. Se ad esempio modifichiamo la nostra routine Prova in questo modo: Public Sub Prova () Dim VarLoc As Integer VarLoc=VarLoc + 1 Debug.Print VarLoc End Sub E nell'evento Load scriviamo: Private Sub Form_Load() Prova

Page 5: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

5

Prova End Sub

e proviamo ad avviare il progetto, vedremo che nella finestra immediata viene scritto: 1 1 e non, come qualcuno si potrebbe aspettare: 1 2 Se si desidera che una variabile locale conservi il proprio valore tra una chiamata e l'altra della routine, bisogna dichiararla con la parola chiave Static: Public Sub Prova() Static VarLoc As Integer VarLoc = VarLoc + 1 Debug.Print VarLoc End Sub Se proviamo ancora ad eseguire il progetto, vedremo che questa volta nella finestra Immediata appare scritto: 1 2 La variabile VarLoc viene quindi creata solo una volta (la prima volta che la routine viene eseguita) e viene distrutta solo quando chiudiamo l'applicazione; tuttavia questa variabile è ancora una variabile locale, quindi non è utilizzabile all'esterno della routine. Il motivo per cui VarLoc assume il valore 1 dopo l'istruzione:

Varloc = Varloc + 1 è presto detto: in Visual Basic ogni variabile numerica viene automicamente inizializzata al valore 0 quando viene creata; le variabili stringa, invece, vengono inizializzate con una stringa vuota, ossia con zero caratteri.

Page 6: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

6

Terza lezione - Le routine in Visual Basic Le routine, come le variabili, devono essere dichiarate: la dichiarazione avviene specificando la parola chiave Sub seguita dal nome della routine e da due parentesi tonde. Ad esempio: Sub Form_Load() La parola Sub può essere preceduta dalle parole chiave Private o Public, a seconda che la routine debba essere visibile solo nel form corrente o in tutto il progetto. Per indicare dove finisce la routine è necessario scrivere End Sub dopo l'ultima istruzione appartenente alla routine. Quindi: End Sub Le routine risultano molto comode quando si ha bisogno di eseguire più volte uno stesso gruppo di istruzioni, in modo che quando si ha necessità di eseguire una certa operazione, è sufficiente richiamare quella routine anziché riscrivere ogni volta le medesime istruzioni. Un aspetto da non trascurare è infatti anche la leggibilità del codice, ovvero la sua facilità di comprensione: utilizzando le routine per eseguire operazioni complesse è molto più semplice capire come funziona un programma Dim x As Integer Private Sub Quadro() 'qui inizia la routine Dim y As Integre 'dichiaro una variabile locale y = x ^ 2 'calcolo il quadro Debug.Print y 'stampo il risulto End Sub 'qui finisce la routine Public Sub Form_Load () x = 2 'imposto la variabile Quadro 'calcolo il quadro e stampo il risulto x = 5 Quadro End Sub Qui abbiamo utilizzato una routine di nome "Quadro" che calcola il quadrato di un numero.

Nell'esempio qui sopra abbiamo impostato una variabile dichiarata a livello di modulo (la variabile x) in modo che potesse essere utilizzata anche nella routine: in realtà ciò non è necessario, infatti è possibile utilizzare il passaggio di parametri alla routine. Un parametro è una variabile che viene comunicata alla routine, la quale può utilizzarla più o meno come se fosse una sua variabile locale: in questo modo è possibile travalicare i limiti imposti dall'area di visibilità delle variabili. Ad es., se noi avessimo dichiaro la variabile x non nella sezione delle dichiarazioni ma all'interno dell'evento Load, avremmo ottenuto un errore del tipo mostrato in figura perché la variabile non sarebbe stata visibile nella routine quadro. Invece utilizzando il passaggio di parametri questo problema non sussiste più. Per indicare a Visual Basic che la nostra routine vuole uno o più parametri bisogna elencare i parametri, o argomenti, all'interno delle parentesi nella dichiarazione della routine: Private Sub Quadro (Param As Integer ) Dim y As Integer y = Param ^ 2 Debug.Print y End Sub L'indicazione dell'argomento segue le stesse regole della dichiarazione delle variabili, eccezion fatta per la parola chiave Dim (o Private o public) che in questo caso NON va inserita: l'argomento di una routine è utilizzabile solo all'interno di quella routine. Per indicare più parametri bisogna separarli con la virgola: ad es: ... (Param1 As Integer , Param2 As String ...) ... Il nome del parametro non ha nulla a che vedere col nome della variabile passata come argomento (nel nostro caso la variabile x): nel caso in cui i nomi fossero uguali, all'interno della routine verrebbe comunque utilizzato il parametro e non la variabile originaria. All'interno dell'evento load del form potremo ora scrivere: Public Sub Form_Load() Dim x As Integer x = 2 Quadro x x = 5 Quadro x End Sub Nuralmente l'argomento da passare alla routine può essere una variabile dichiarata da noi, ma anche un valore fisso: possiamo quindi fare a meno, nel nostro caso, di utilizzare la variabile x e scrivere direttamente: Public Sub Form_Load() Quadro (2) 'oppure Quadro 2 Quadro (5) 'oppure Quadro 5 End Sub

Page 7: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

7

ottenendo il medesimo risultato: ogni volta che viene chiamata la routine quadro, la variabile param assumerà di volta in volta il valore 2, 5. Avrete sicuramente capito che per eseguire una routine è sufficiente scriverne il nome, eventualmente seguito dagli argomenti richiesti dalla routine: gli argomenti andranno separi da virgole nel caso siano più di uno. E' però possibile anche utilizzare l'istruzione Call, seguita dal nome della routine e dai parametri, questa volta però obbligoriamente racchiusi tra parentesi: Call Quadro (2) oppure: Call Quadro (2, 3, Pippo) se gli argomenti sono diversi. L'uso delle parentesi sarà fondamentale nell'uso delle funzioni.

Page 8: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

8

Quarta lezione - Le funzioni in Visual Basic La differenza tra una routine e una funzione è che la prima esegue un certo numero di istruzioni, la seconda esegue un certo numero di istruzioni e in più restituisce un valore, che quindi può essere memorizzato in una variabile. L'uso delle funzioni è comodo quando è opportuno sapere quale sia il risultato finale delle operazioni eseguite : ad es., la funzione potrebbe restituire un valore di errore se qualcosa è andato storto durante la sua esecuzione, oppure potrebbe restituire il risultato di un'operazione come quella eseguita dalla routine quadro che abbiamo visto nella lezione precedente. Per dichiarare una funzione bisogna usare la parola chiave Function al posto di Sub; inoltre è sempre meglio, se possibile, specificare il tipo di dati restituito dalla funzione. Private Function Quadro (Param As Integer ) As Long Quadro=Param ^ 2 Debug.Print Quadro End Function

Il valore che la funzione deve restituire deve essere assegnato al nome della funzione che viene quindi trattato come se fosse una variabile; perciò rispetto alla routine Quadro (v.lez. precedente) si può fare a meno di dichiarare una variabile locale a cui assegnare il risultato dell'elevamento a potenza. Inoltre, possiamo fare a meno di usare l'istruzione Debug.Print all'interno della funzione, perché il valore che vogliamo visualizzare è quello restituito dalla funzione e quindi è visibile anche all'esterno di essa. Nell'evento Load del form, anziché scrivere: Debug.Print Quadro(2) Si noti l’uso delle parentesi tonde: queste vanno sempre indicate se si vuole che la funzione restituisca effettivamente un valore. Non si deve usare l’istruzione Call per richiamare una funzione perché questa impedisce che la funzione restituisca effettivamente un valore. Per quanto riguarda il passaggio di parametri, valgono le stesse regole che abbiamo visto per le routine; a questo proposito c'è da sapere un'altra cosa: i parametri possono essere preceduti dalla parola chiave ByVal o ByRef. Queste parole chiave specificano, rispettivamente, che il parametro viene passato per valore o per riferimento: senza entrare troppo nei dettagli, è sufficiente dire che nel primo caso la funzione (o la routine) conosce soltanto il valore della variabile passata come argomento, mentre nel secondo caso conosce, per così dire, la variabile stessa, potendo quindi intervenire direttamente su di essa. Concretamente ciò significa che se la variabile è passata per valore, la funzione (o la routine) potrà eseguire operazioni sul valore della variabile ma non potrà modificarla; se invece la variabile è passata per riferimento, la funzione potrà modificare direttamente la variabile. Un esempio chiarirà tutto: creiamo una funzione con due argomenti, uno passato per valore, l'altro per riferimento e facciamo qualche operazione su di essi: Private Function Prova ( ByVal Valore As Integer , _ ByRef Riferimento As Integer ) As Integer Valore = Valore + 1 Riferimento = Riferimento + 1 Prova = Valore + Riferimento End Function La funzione non fa altro che incrementare di 1 i due argomenti e restituirne la somma. Ora dichiariamo, nell'evento Load del form, due variabili e passiamole alla funzione: Private Sub Form_Load() Dim Var1 As Integer , Var2 As Integer Dim Risultato As Integer Var1 = 3 Var2 = 10 Risultato = Prova(Var1, Var2) Debug.Print Risultato Debug.Print Var1, Var2 End Sub Eseguendo il progetto, noteremo che nella finestra immediata compaiono i valori:

15 è il risultato della funzione ((3+1)+(10+1)=15); la variabile Var1, che è stata passata per valore ha conservato il valore che aveva prima della chiamata della funzione, cioè 3; invece Var2, che è stata passata per riferimento, è stata effettivamente modificata durante l'esecuzione della funzione, e infatti dopo la chiamata ha assunto il valore 11, cioè il valore originario più 1. Se non viene specificata né ByVal né ByRef, Visual Basic penserà automicamente che la variabile è stata passata per riferimento: questa infatti è l'impostazione predefinita. Un'altra parola chiave che può precedere gli argomenti è Optional: questa specifica che l'argomento seguente non è obbligatorio, e in tal caso è possibile indicare un valore di default che l'argomento deve assumere nel caso in cui l'istruzione chiamante la funzione (o la routine) ometta

Page 9: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

9

effettivamente il parametro. Ad es.: Private Function Prova (A As Integer , Optional B As Integer = 1) As Integer Prova = A + B End Function se nell'evento Load del form scriviamo: Private Sub Form_Load() Debug.Print Prova(2) Debug.Print Prova(2, 3) End Sub vedremo nella finestra immediata: 3 5 Nel primo caso, infatti, il parametro B è omesso e quindi assumerà per default il valore 1. Come per le routine, anche le variabili locali di una funzione possono essere dichiarate Static per indicare che il loro valore viene mantenuto tra una chiamata e l'altra della funzione (v.lez. 2): se si vuole che TUTTE le variabili locali siano statiche, si può dichiarare la funzione in questo modo: Private Static Function Prova() As Integer Dim A As String 'variabile stica Dim B As Long 'variabile stica End Function Le variabili locali saranno statiche anche se nella loro dichiarazione non è sta specificata la parola chiave Static. Oltre alle funzioni dichiarate esplicitamente, è possibile utilizzare anche funzioni predefinite : Abs(numero) Restituisce un valore che specifica il valore assoluto di un numero Asc(stringa) Restituisce un valore intero che rappresenta il codice di carattere nella tabella ASCII

corrispondente alla prima lettera di una stringa Chr(codicecarattere) Restituisce un valore stringa che contiene il carattere associato nella tabella dei codici ascii

al codice di carattere specificata CStr(numero) Converte in stringa un qualsiasi valore numerico Date Restituisce la data corrente di sistema Exp(numero) Restituisce l'esponenziale di numero, vale a dire e^ numero dove e è base dei logaritmi

naturali Hex(numero) Restituisce un valore stringa che rappresenta il valore esadecimale di un numero IsNumeric(espressione) Restituisce un valore boolean che indica se un'espressione essere valutata come numero Log(numero) Restituisce un valore Double che specifica il logaritmo naturale di un numero Now Restituisce la data e l'ora correnti del sistema Oct(numero) Restituisce un valore stringa che rappresenta il valore ottale di un numero Sgn(numero) Restituisce il segno di un numero Sqr(numero) Restituisce le radice quadrata di un numero Time Restituisce l'ora di sistema Val(stringa) Restituisce i numeri inclusi in una stringa sotto forma di valore numerico di tipo appropriato Int(numero) La funzione non fa altro che troncare la parte decimale di un numero restituendo solo la

parte intera Rnd Genera numeri casuali restituendo un numero (più o meno) casuale compreso tra 0 (incluso)

e 1 (escluso), ovvero tra 0 e 0,99999. Per generare un numero tra 0 e 13 basta fare: Int(14 * Rnd)

Timer Il valore restituito dalla funzione Timer, rappresenta il numero di secondi trascorsi dalla mezzanotte del giorno corrente

Randomize parametro L'istruzione serve ad inizializzare il generatore di numeri casuali (i numeri "casuali" generati da un qualunque computer non sono veramente casuali, poiché sono generati in modo deterministico, seguendo regole ben precise; solo che queste regole sono tali da garantire, entro certi limiti, una sorta di casualità nei numeri generati, che per questo vengono definiti più correttamente "pseudo-casuali"). Parametro è un valore di avvio. Spesso si usa Randomize Timer

Page 10: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

10

Quinta lezione – Il primo programma in Visual Basic Ora che conosciamo le basi fondamentali della programmazione, possiamo avvicinarci alla creazione del nostro primo programma: il classico "Hello World!", ovvero un programma che non fa altro che visualizzare un messaggio di saluto. Per fare ciò cominciamo col creare un nuovo progetto e a inserire nel form una Label, cioè un'etichetta: il controllo Label si trova sulla casella degli strumenti che solitamente si trova sul bordo sinistro dello schermo, ed è quello indicato dall'icona "A". Una Label è un controllo che permette di visualizzare una stringa: una volta inserita sul form, potremo vedere le sue proprietà nella finestra delle proprietà, posta sulla destra dello schermo; le proprietà possono essere visualizzate in ordine alfabetico o per Categoria: scegliendo l'ordine alfabetico, vedremo innanzitutto la proprietà Name che è la prima dell'elenco e che definisce il nome con cui si può fare riferimento al controllo all'interno del codice, come si può leggere anche nella descrizione fornita nella parte inferiore della finestra delle proprietà. Il nome predefinito, per qualunque controllo, è dato dal nome del tipo di controllo (nel nostro caso Label) più un numero che viene incrementato ogni volta che si aggiunge un altro controllo dello stesso tipo. Diamo un'occhiata ad altre proprietà interessanti: la proprietà Caption ad es., assume il valore "Label1": provando a modificare questo valore (basta cliccarci sopra una volta e scrivere) vedrete che cambierà anche la stringa visualizza sul form (per ora lasciamo pure "Label1"); pertanto sarà questa la proprietà che dovremo opportunamente impostare per visualizzare il messaggio di saluto. Prima di vedere come, inseriamo sul form anche un CommandButton, cioè un pulsante, che troviamo anch'esso sulla casella degli strumenti.

Nella finestra delle proprietà, modifichiamo la proprietà Caption assegnando il valore "Saluta!" (senza le virgolette). La posizione dell'etichetta e del pulsante sul form può essere cambiata semplicemente puntando il mouse sul controllo e trascinandolo nella posizione voluta. Ora andando sulla finestra del codice (cliccando due volte sul form, oppure sulla prima icona della finestra del progetto, facendo attenzione ad aver selezionato la voce "Form1" nella medesima finestra): selezioniamo la voce Command1 dall'elenco degli oggetti e la voce click dall'elenco delle routine; ci troviamo,

ovviamente, nella parte di codice che verrà eseguita quando si fa click sul pulsante. Ora, all'interno di questa routine aggiungiamo: Label1.Caption = "Hello World!" oppure: Label1.Caption = "Salve Mondo!"

Avviamo il progetto premendo F5; cliccando sul pulsante "Saluta" il testo dell'etichetta diventerà "Hello World!". Quello che succede dovrebbe essere evidente: cliccando sul pulsante viene scatenato l'evento Click relativo ad esso, e viene quindi eseguita l'istruzione che abbiamo inserito noi, e che imposta il valore della proprietà caption dell'etichetta a "Hello World!". Si dice che questa proprietà viene impostata in fase di esecuzione, ovvero mentre il programma è in esecuzione; la proprietà caption del pulsante, invece, è sto impostato in fase di progettazione, ovvero quando abbiamo "disegnato" la nostra applicazione. Volendo, avremmo potuto impostare la proprietà Caption dell'etichetta già in fase di esecuzione: in tal caso non avremmo avuto bisogno del pulsante "Saluta". Proviamo ora a migliorare un po' la nostra applicazione: di solito è buona norma inizializzare il valore di proprietà o variabili che andranno in seguito modificate; ad esempio, prima di premere il pulsante "Saluta", l'etichetta mostrava la stringa "Label1", cosa non molto bella a vedersi: quindi è meglio annullare la proprietà Caption. E' possibile farlo in fase di progettazione, cancellando "Label1" nella finestra delle proprietà e premendo Invio; in fase di esecuzione, bisogna usare l'istruzione: Label1.Caption = "" dove tra le virgolette non ci devono essere spazi: è una "stringa nulla", di lunghezza zero, che non contiene alcun carattere. Questa istruzione dovremmo metterla in una routine che viene eseguita subito, non appena l'applicazione viene avviata: il posto più adatto è senz'altro la routine Load del form, quella che abbiamo usato per i nostri esempi nelle lezioni precedenti; infatti l'evento Load del form viene generato prima della visualizzazione della finestra. Se volessimo poter annullare, ossia cancellare, il saluto, dovremmo inserire sul form un altro pulsante: assegnate il valore "Annulla" (sempre senza le virgolette) alla proprietà Caption e, nella routine Click (del Command2, non del Command1!) ripetete l'istruzione: Label1.Caption = "" E' buona norma, inoltre, inserire un pulsante per uscire dal programma, anche se non è necessario in quanto basta premere la X in alto a destra nel form per chiudere l'applicazione; per terminare un programma, bisogna "scaricare" tutti

Page 11: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

11

i form attualmente caricati in memoria (nel nostro caso solo il form Form1): nella routine Click del pulsante Command3, quindi, dovremo scrivere: Unload Form1 L'istruzione unload serve appunto ad eliminare dalla memoria del computer i riferimenti al form di nome Form1, e di conseguenza a terminare l'applicazione; l'istruzione determina la generazione dell'evento Unload, che è il corrispettivo dell'evento Load di cui si è detto sopra; analogamente, esiste anche l'istruzione Load che serve per "caricare" un form in memoria. Al posto di "Form1" è possibile utilizzare la parola chiave Me, che indica, in questo caso, il form corrente, ossia quello a cui appartiene la riga di codice che sta per essere eseguita. La Caption del pulsante Command3 andrebbe impostata, per esempio, a "Esci". Se proviamo ad eseguire l'applicazione, vedremo inizialmente solo i tre pulsanti "Saluta", "Annulla" ed "Esci": premendo "Saluta", il programma visualizzerà il messaggio di saluto, premendo "Annulla" questo messaggio scomparirà e premendo "Esci" chiuderemo il programma. Questo esempio è ovviamente molto semplice, ma cercate di apprezzare il fatto che abbiamo creato un'applicazione completa scrivendo soltanto 4 righe di codice. Per migliorare ulteriormente il nostro programma potremmo, ad es., cambiare la stringa che compare nella barra del titolo del form (nel nostro caso "Form1"): anche in questo caso si tratta della proprietà Caption (del form); basta andare nella finestra della proprietà, selezionare il form dalla casella a discesa, selezionare la proprietà Caption e scrivere, ad esempio: "Programma di esempio Hello World" Posizionando i pulsanti sul form, probabilmente non sarete riusciti (almeno non al primo colpo) a farli delle stesse dimensioni: per renderli uguali basta selezionarli tutti insieme, come si fa per selezionare più file in Gestione Risorse, cioè disegnando un rettangolo torno ad essi

oppure cliccandoci sopra tenendo premuto il tasto Ctrl; dopodichè, andate sul menù Formato - Rendi uguale e scegliete Entrambe: i tre pulsanti avranno tutti la stessa altezza e larghezza. Nel caso non siano allineati, potete selezionarli e andare sul menù Formato - Allinea e scegliere la voce opportuna. Inoltre, è opportuno modificare i nomi dei vari controlli: ad esempio, il nome dell'etichetta potrebbe essere "lblHelloWorld" (senza spazi, mi raccomando); quello dei pulsanti "cmdSaluta", "cmdAnnulla", "cmdEsci"; naturalmente in tal caso bisogna modificare anche le istruzioni del codice. Così: Label1.Caption = "" diventa: lblHelloWord.Caption = "" e così via. Il motivo per cui i nomi sono preceduti da lbl o cmd ve lo spiegherò la prossima volta.

Page 12: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

12

Sesta lezione – Convenzioni. Cominciamo a vedere quali sono le convenzioni di scrittura del codice, cioè le regole che ogni programmatore dovrebbe seguire per permettere di standardizzare il codice. Le convenzioni più semplici sono quelle che riguardano la denominazione di oggetti e variabili: secondo tali convenzioni è bene utilizzare un prefisso di due o tre caratteri specifico per ogni tipo di oggetto o variabile: ad es., se utilizziamo un CommandButton dovremmo usare il prefisso cmd; per le etichette (c.d. Label) il prefisso è lbl , per i form è frm , e così via. Leggendo un codice di questo tipo: frmMain.Show lblFileName.Caption="c:\pippo.txt" cmdSave_Click saremmo subito in grado di capire con quali oggetti del linguaggio stiamo lavorando. Analogo discorso vale per le variabili: innanzitutto è bene usare una lettera per indicarne l'area di validità: g per le variabili globali o pubbliche, m per quelle private ma dichiarate a livello di modulo (quindi nella sezione dichiarazioni di un form, ad esempio); per le variabili locali delle routine non si usa alcun prefisso. Poi bisognerebbe utilizzare un altro prefisso per indicare il tipo di variabile: str per le stringhe, int per gli integer, lng per i long, ecc. Ad esempio: gstrUserName indica una variabile pubblica che contiene il nome dell'utente (e quindi si tratta di una stringa). Ci sono poi delle convenzioni per la strutturazione del codice, ovvero l'inserimento di commenti e l'uso di una formattazione adeguata del codice: ad esempio, ogni subroutine o funzione dovrebbe includere un commento che ne indichi lo scopo, il significato delle variabili richieste in input, il valore restituito, e ogni altra informazione non direttamente intuibile dal codice ma che serve a capire meglio cosa fa e come funziona la routine. Anche il codice è soggetto ad una opportuna formattazione utilizzando dei rientri. Nella figura si notano i blocchi if…end if e for…next, che sono istruzioni nidificate, scritti con una opportuna indentatura che ne mette in evidenza il livello gerarchico.

Page 13: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

13

Settima lezione – Interfaccia grafica e controlli standard. L’interfaccia presentata da VB verso l’utente è creata per mezzo di oggetti grafici (finestra, bottoni, icone,..) attraverso i quali avviene tutta l’interazione tra l’utente e l’applicazione. Il Form è la finestra dell’applicazione su cui è possibile disegnare oggetti grafici, definiti controlli , che accettano l’input dell’utente o visualizzano l’output. Ciascun controllo della casella degli strumenti dispone di caratteristiche predefinite che ne rappresentano le proprietà. Alcune di queste

caratteristiche sono reimpostate, ma possono essere modificate dal programmatore. Oltre ai controlli standard è possibile utilizzare controlli aggiuntivi attraverso Progetto->Componenti ( o con il click destro sulla casella degli strumenti) e selezionando il controllo desiderato dalla finestra di dialogo che si apre. La programmazione è fatta quindi da:

• Oggetti o Form o Controlli

• Proprietà degli oggetti • Eventi • Metodi

Tutti gli oggetti hanno un nome ed un tipo, più altre proprietà che dipendono dall’oggetto. Il controllo (control) è un oggetto che viene disegnato sul form per creare

l’interfaccia tra utente e applicazione. Puntatore (pointer)

Consente di selezionare, spostare o ridimensionare form o controlli.

Casella di testo (Text Box)

Crea un box dove l’utente può inserire o modificare una stringa di caratteri. Serve sia per l’input che per l’output. Può contenere più righe ed è possibile scorrerla.

Pulsante di comando (Command Button)

Bottone di comando per iniziare o terminare un’elaborazione. Si attiva facendo click su di esso o premendo la barra spaziatrice dopo averlo selezionato.

Etichetta (Label)

Visualizza un messaggio o un’intestazione che l’utente non può modificare. È’ utile per visualizzare informazioni per l’utente, titoli o descrizioni del contenuto delle caselle di testo.

Casella di controllo (Check Box)

Quadratino con eventuale crocetta per gestire le scelte dell’utente del tipo si/no o vero/falso. Consente di attivare o disattivare un’opzione. Il segno di spunta indica che l’opzione attiva. Si possono attivare anche più opzioni contemporaneamente.

Pulsante di opzione (Optino Button)

Permette di attivare un’opzione scelta tra un gruppo di opzioni. E’ possibile selezionare un solo pulsante del gruppo; quando si seleziona un’opzione (pallino presente), viene disattivata quella precedentemente attiva.

Casella di riepilogo (List Box)

Consente di creare un elenco che l’utente po’ scorrere e/o selezionare una o più voci.

Casella Combinata (Combo Box)

Consente all’utente di operare una scelta scrivendola nel box di testo o selezionando dall’elenco a discesa associato. Essa è l’associazione di una casella di testo ed una di riepilogo. Ne sono disponibili tre tipi. Permette di presentare all’utente lunghi elenchi senza occupare spazio nel form.

Casella di riepilogo delle unità disco (Drive List Box)

Permette all’utente di selezionare il disco (A:,C: ..) durante l’esecuzione dell’applicazione.

Casella di riepilogo delle directory (Directory List Box)

Permette all’utente di selezionare directory o sottodirectory del disco durante l’esecuzione dell’applicazione.

Casella di riepilogo dei file (File List Box)

Permette all’utente di selezionare i file durante l’esecuzione dell’applicazione. Consente di visualizzare tutti i file di una determinata directory, effettuando anche dei filtri sul tipo.

Cornice (Frame)

Crea una cornice adatta a contenere dei controlli, raggruppandoli in modo sia grafico che funzionale. E’ spesso usata per racchiudere più gruppi di option button.

Barra di scorrimento orizzontale (Horizontal scroll bar)

Crea una barra di scorrimento pr muoversi all’interno dei form o liste di grandi dimensioni. E’ anche usata per l’impostazione di valori.

Barra di scorrimento verticale (Vertical scroll bar)

Crea una barra di scorrimento pr muoversi all’interno dei form o liste di grandi dimensioni. E’ anche usata per indicare la posizione in un range di valori Viene aggiunta automaticamente quando il numero di righe conteneti dati supera la

Page 14: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

14

dimensione del controllo. Casella Immagine (Picture box)

Crea il contenitore per grafici e immagini nei formati BMP, ICO, WMF, JPG, GIF. Permette di inserire anche immagini animate.

Immagine (Image)

Visualizza immagini nei formati BMP, ICO, WMF, JPG, GIF. Può essere utilizzata come pulsante di comando.

Linea (line)

Disegna linee orizzontali, verticali o oblique. E’ utilizzato per suddividere graficamente i contenuti di un form complesso in sottosezioni.

Forma (Shape)

Mette nel form figure ipo rettangoli, cerchi ellissi.

Contenitore OLE (OLE)

Consente al programmatore di creare applicazioni che possono visualizzare e modificare dati provenienti da altre applicazioni (disegni, fogli elettronici, grafici).

Timer (timer)

Consente l’uso di un orologio per far partire un’esecuzione con uno specifico intervallo di tempo. Consente di impostare determinate azioni ad intervalli regolaridi tempo. Rimane nascosto durante l’esecuzione.

Dati (Data)

Consente di visualizzare, modificare, aggiornare dati di un database esistente.

Finestre di dialogo comuni (Common Dialog Box)

Consente di visualizzare numerose finestre di dialogo di uso comune nelle applicazioni Wndows come Apri, Salva con nome, Stampa, Colori e Carattere. Non è visibile in fase di esecuzione.

I form ed i controlli posseggono un insieme di caratteristiche predefinite dette proprietà. Le proprietà stabiliscono:

• L’ aspetto, cioè il colore, la dimensione e il nome dell’oggetto; • le sue funzionalità, cioè la possibilità di spostare, ridimensionare, ridurre e icona o ingrandire l’oggetto.

Le principali proprietà degli oggetti di uso più frequente sono: Name Determina il nome utilizzato nel codice per identificare il controllo; e vivace il nome della

variabile nel caso delle variabili Alignment Determina l’allineamento di un controllo del testo di un controllo Appearance Determina la forma del disegno di un controllo (Flat, 3D) BackColor Imposta il colore di sfondo di un oggetto ForeColor Imposta il colore di primo piano utilizzato del testo e la grafica di un oggetto BorderStyle Imposta lo stile del bordo di un oggetto Caption Per un forma determina il testo visualizzato sulla barra del titolo, per un controllo ho

determina il testo visualizzato nel controllo stesso Enabled Determina se il controllo è attivato, cioè se in grado di rispondere agli eventi generati

dall’utente Font Specifica le caratteristiche del font utilizzato per i caratteri; tale proprietà è un oggetto esso

stesso; le sue proprietà fondamentali sono: FontName, FontBold, FontStrikethru, FontUnderline.

Height (altezza) e Width (larghezza)

Impostano le dimensioni di un oggetto

MousePointer Imposto il valore che indica il tipo di puntatore visualizzato quando il mouse si trova in corrispondenza di una determinata parte dell’oggetto.

MouseIcon Fornisce un’icona personalizzata quando la proprietà MousePointer è impostata a 99 TabIndex Imposta l’ordine di tabulazione di un oggetto all’interno di un form Visible Indica se l’oggetto è visibile o nascosto Ciascun oggetto riconosce specifiche azioni provocate dall’utente o dal sistema operativo, il clic di un pulsante, l’apertura di un form, l’inserimento di dati in una casella di testo. Queste azioni vengono definite eventi. In risposta ad essi il programmatore può inserire del codice che sarà eseguito nel momento in cui si verificherà l’evento. Il nome di una routine di evento è composto dal nome dell’oggetto e dal nome dell’evento separati dal segno _. Ciascun form e ciascun controllo in VB rispondono ad un gruppo predefinito di eventi. Ad esempio un pulsante di comando risponde ai seguenti eventi: Click, DragOver, DragDrop, KeyDown, KeyPress, KeyUp, MouseDown, MoouseMove, MouseUp. Un particolare tipo di eventi e riguarda il focus o evidenziazione degli oggetti: nell’ambiente Windows il clic e del mouse e l’input dalla tastiera possono essere ricevuti da una sola finestra, un solo form o un solo controllo alla volta. Si può dire che l’oggetto su cui si trova l’evidenziazione possiede il focus. Gli eventi collegati al focus sono: GotFocus ( acquisizione del focus) e LostFocus ( perdita del focus) . Un altro evento comune a più controlli di Visual Basic è l’evento change che viene generato quando il contenuto del controllo è stato modificato. Gli eventi caratteristici dell’oggetto form sono: Load (il form viene caricato in memoria), Unload ( il form viene rimosso dalla memoria), Activate ( un form diventa la finestra attiva, cioè acquista il focus), Deactivate ( un form non è più la finestra attiva cioè perde il focus). I metodi sono le funzioni disponibili nel linguaggio Visual Basic associate a ciascun controllo od oggetto dell’interfaccia grafica, ad esempio il metodo Move cambia la posizione del controllo. Il metodo Show associato ad un form lo carica in memoria e lo visualizza.

Page 15: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

15

Oltre agli oggetti grafici visti finora, esistono degli oggetti software utilizzati per la gestione del processo in esecuzione.

È un oggetto che consente di specificare il titolo dell’applicazione, il percorso ed il nome del file eseguibile, controlla inoltre se è in esecuzione o meno un’istanza precedente dell’applicazione

App

Le proprietà principali dell’oggetto App sono: • App.Path restituisce il percorso dell’applicazione • App.Title restituisce il titolo dell’applicazione • App.Helpfile restituisce il nome del file della guida in linea • App.EXEName restituisce il nome del file eseguibile dell’applicazione • App.LegalCopyright restituisce informazioni sul copyright • App.Comments restituisce i commenti sull’applicazione • App.ProductName restituisce il nome del prodotto • App.Major e App.Minor restituiscono la versione del programma • App.PrevIstance consente di verificare se è già in esecuzione un’altra istanza del programma • App.hInstance fornisce un handle dell’applicazione. Alcune di queste informazioni sono inserite dal finestra del progetto

Err Contiene informazioni relative agli errori di runtime Screen Gestisce i form in base alla loro posizione sullo schermo e controlla in fase di esecuzione il puntatore

del mouse all’esterno dei form dell’applicazione Debug Viene utilizzato da rinviare l’output alla finestra Debug in fase di esecuzione Printer Consente di comunicare con una stampante di sistema ( inizialmente la stampante predefinita).

L’insieme Printers raccogliere informazioni sulle stampanti disponibili nel sistema Gestisce il testo e le immagini grafiche negli appunti di Windows. È possibile utilizzare quest’oggetto per consentire all’utente di copiare, tagliare e incollare testo o immagini grafiche nell’applicazione in esecuzione.

ClipBoard

Clipboard.Clear consente di ripulire l'area degli appunti cancellando ogni suo contenuto Clipboard.SetData va utilizzata nel caso si voglia copiare nella Clipboard della grafica Clipboard.SetText se si tratta di copiare solo testo Clipboard.GetData e Clipboard.GetText consentono di incollare il contenuto della Clipboard all'interno di uno specifico oggetto

Page 16: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

16

Ottava lezione – Operatori Booleani e struttura IF. Ricordiamo brevemente i principali operatori logici

And (congiunzione), Or (disgiunzione), Not (negazione), Xor (exclusive Or )

In Visual Basic ci sono altri due operatori logici disponibili, che sono utilizzati molto raramente ma che potrebbero comunque essere utili: l'equivalenza (Eqv) e l'implicazione (Imp):

In parole povere, l'Eqv è la negazione dell'Xor: infatti due espressioni sono equivalenti se sono uguali (entrambe false o entrambe vere); l'Imp corrisponde più o meno alla costruzione "se… allora" con l'uso di una condizione sufficiente ma non necessaria, ad esempio "se x>y, allora x>y/2": questa implicazione è falsa solo se fosse x>y ma xy affinché sia x>y/2.

L'istruzione principale che fa uso di espressioni booleane è il costrutto "if condizione then istruzione" che, come dice il nome, esegue una o più istruzioni se si verifica una certa condizione. Ad esempio: If lblName.Visible = True Then lblName.Caption = "Pippo" End if

aggiorna la proprietà Caption dell'etichetta lblName se questa etichetta è visibile: il tipo della proprietà Visible, infatti, è proprio Boolean. Quando Visual Basic deve eseguire un'istruzione come quella riportata, prima di tutto verifica se l'espressione compresa tra le parole chiave If e Then è vera o falsa: se l'etichetta è visibile (cioè se la proprietà visible è uguale a True), la condizione è verifica e quindi sarà eseguita l'istruzione seguente la parola chiave Then; altrimenti la condizione non sarà verificata e l'istruzione sarà del tutto ignorata. L’istruzione elseif permette di testare ulteriori condizioni all’interno della struttura IF. If strName = "Pippo" Then frmProva.Show frmProva.lblName.Caption = "Pippo" ElseIf strName = "Topolino" Then frmProva.Show frmProva.lblName.Caption = "Minnie" ElseIf strName = "Pluto" Then frmProva.Show frmProva.lblName.Caption="Orazio" Else frmProva.Hide End If

All'interno di ogni blocco If…Then è possibile inserire qualunque istruzione, anche un'altra If…Then (si parla dei cosiddetti blocchi annidati); ad esempio si potrebbe fare: If intX > 10 Then If intX > 100 Then intY = intX / 2 Else intY = intX + 10 End If ElseIf intX > 5 Then intY = 0 Else bValue = True End If

Le condizioni da valutare possono essere espressioni anche molto complesse, utilizzando gli operatori logici che abbiamo visto nella lezione precedente. Nel caso di condizioni multiple (diversamente dal linguaggio C) Visual Basic le valuta sempre tutte, e nel caso di controlli pesanti bisognerebbe tenerne conto, facendo in modo che vengano valutate solo le espressioni strettamente necessarie. I valori True e False in realtà non sono altro che numeri, e precisamente la parola chiave true corrisponde al valore -1 e la parola chiave false corrisponde al valore 0. Più precisamente, un valore numerico viene interpreto da VB come true se è diverso da 0, anche se il valore predefinito di true è -1, ed è interpretato come false quando è uguale a 0. In VB esiste anche un particolare costrutto condizionale: IIF(condizione, ris_vero,ris_falso) che valuta la condizione e ritorna ris_vero se la condizione è vera, ritorna ris_falso se è falsa. Esempio: un lInizio = IIf (lFine > 1, lFine, 2) Assegna a LInizio il valore di LFine se la condizione è vera, altrimenti gli assegna 2.

AND True And True = True True And False = False False And True = False False And False = False

OR True Or True = True True Or False = True False Or True = True False Or False = False

XOR True Xor True = False True Xor False = True False Xor True = True False Xor False = False

EQV True Eqv True = True True Eqv False = False False Eqv True = False False Eqv False = True

IMP True Imp True = True True Imp False = False False Imp True = True False Imp False = True

Operatori in confronto = uguale < minore <= minore uguale > maggiore >= maggiore uguale <> diverso

Page 17: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

17

Nona lezione – Nozioni avanzate sulle variabili. Finora abbiamo visto i tipi Byte, Integer, Long, String e Boolean; naturalmente ce ne sono diversi altri, ad esempio: Date, utilizzato per memorizzare le date e le ore, che occupa 8 byte in memoria e che rappresenta una data compresa tra il 1/1/100 e il 31/12/9999; Single, utilizzo per memorizzare valori frazionari a precisione singola (4 byte) compresi tra circa -3,4*10^38 e circa 3,4*10^38; Double, che memorizza valori frazionari a precisione doppia (8 byte) compresi tra circa -1,8*10^308 e circa 1,8*10^308; Currency, che memorizza valori frazionari con quattro decimali (8 byte), solitamente utilizzato per calcoli con valori monetari; Object, che memorizza un riferimento a un oggetto qualunque, come un form, un textbox, un file, ecc. I tipi Single e Double sono gestiti in modo diverso rispetto ai valori interi come Integer e Long: infatti i bit al loro interno sono divisi in due gruppi, la mantissa e l'esponente, secondo la notazione scientifica in base allo standard IEEE; per questo motivo i Single e i Double sono in grado di gestire numeri molto grandi o molto piccoli, ma talvolta hanno difficoltà a trattare le operazioni con numeri interi e con le approssimazioni. Per quanto riguarda il tipo String, finora abbiamo considerato solo le stringhe a lunghezza variabile, ma in realtà ci sono anche le stringhe a lunghezza fissa, che si dichiarano in questo modo: Dim Nome As String * [lunghezza della stringa] Mentre una stringa di lunghezza variabile occuperà in memoria 10 byte più il numero di byte necessari per la stringa vera e propria, una stringa di lunghezza fissa occuperà solo il numero di byte indicato nella dichiarazione della variabile: questo perché, se la stringa è di lunghezza variabile, Visual Basic dovrà utilizzare memoria aggiuntiva (10 byte, in questo caso) per conservare informazioni quali, appunto, la lunghezza effettiva della stringa. Esistono poi i dati definiti dall'utente, o meglio dal programmatore, che consistono in un insieme di sottovariabili ciascuna col suo tipo specifico; ad esempio io posso definire un mio tipo di variabile in questo modo: Type Persona

Name As String * 30 X As Integer Y As Integer

End Type dove Persona naturalmente è un nome scelto a caso, e successivamente dichiarare una variabile di questo tipo: Dim Cliente As Persona la variabile Cliente occuperà in memoria tanto spazio quanto è necessario per l'insieme dei suoi membri, cioè 2+2+30=34 byte, e si potrà assegnare un valore a ciascuno dei suoi membri scrivendo, ad esempio: Cliente.X = 10 Cliente.Y = 2000 Cliente.Name = "Plu to" Nella prima lezione avevo detto che la sintassi per la dichiarazione di variabili è la seguente: Dim Nome As Tipo In realtà la seconda parte ("As Tipo") si può omettere: in tal caso, per default, la variabile dichiara sarà di tipo Variant. Questo particolare tipo di dati è in grado di contenere qualunque altro tipo di dati, tranne che quelli definiti dall'utente e le stringhe di lunghezza fissa: in virtù di questa sua caratteristica, il tipo variant ha una grande flessibilità, che consente di utilizzarlo per memorizzare dati che a priori potrebbero assumere diversi tipi. Ad esempio, è possibile fare una cosa del genere: Dim V As Variant 'oppure semplicemente: Dim V V = 13.5 V = "Pippo" V = 4000 La flessibilità del tipo Variant ha ovviamente un rovescio della medaglia: poiché un Variant può assumere valori di vario tipo, VB deve memorizzare, oltre al dato in sé, anche altre informazioni sul tipo di dato; per questo un Variant impegna 16 byte aggiuntivi oltre a quelli necessari per memorizzare il dato, se si tratta di un dato numerico, e ben 22 byte aggiuntivi se il dato contiene caratteri. Non solo, ma poiché non si sa a priori di che tipo è il dato memorizzato in un Variant, ogni volta che questo dato viene utilizzato, Visual Basic deve perdere tempo a convertirlo opportunamente nel tipo più approprio: infatti ogni variabile di tipo Variant assume di volta in volta un sottotipo che indica per l'appunto quale tipo di dati sarebbe più appropriato per il valore assegnato alla variabile Variant. Così, nell'esempio precedente, la variabile V assumerà i sottotipi Double, String e Integer: per rendersene conto è sufficiente utilizzare la funzione TypeName(NomeVar) che restituisce una stringa corrispondente al sottotipo della variabile NomeVar; oppure la funzione VarType(nomevar) che invece restituisce un Integer corrispondente. Da tutto ciò risulta che il tipo Variant deve essere utilizzato solo se è giustificato da un bisogno di flessibilità: se un programmatore sa che una variabile assumerà sempre e soltanto valori compresi, ad esempio tra 1000 e 100000, dovrebbe dichiarare questa variabile come Long, perché così facendo otterrà un vantaggio in termini di utilizzazione della memoria e di velocità di esecuzione. Spesso è necessario convertire un tipo di variabile in un altro: la conversione più frequente è forse quella da numero a stringa e viceversa (cioè da 34 a "34" e viceversa), ma talvolta capita anche di dover convertire un Integer in un Long, o un Single in un Integer, o un Long in Date, ecc. Esistono perciò delle apposite funzioni di conversione del tipo, che iniziano con "c" seguito dall'abbreviazione del tipo restituito:

Page 18: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

18

Funzione Tipo Restituito Intervallo

CBool Booleano Qualsiasi espressione numerica o stringa valida

CByte Byte Da 0 a 255

CCur Currency Da -922.337.203.685.477,5808 a 922.337.203.685.477,5807

CDate Date Qualsiasi espressione di da valida

CDbl Double Da -1,79769313486232E308 a -4,94065645841247E-324 per valori negivi; da 4,94065645841247E-324 a 1,79769313486232E308 per quelli positivi

CDec Decimal +/-79.228.162.514.264.337.593.543.950.335 per numeri con fattore di divisione zero, ovvero numeri senza decimali. Per i numeri con 28 decimali l'intervallo è +/-7,9228162514264337593543950335. Il numero minatore possibile diverso da zero è 0,0000000000000000000000000001

CInt Integer Da -32.768 a 32.767; le frazioni vengono arrotonde

CLng Long Da -2.147.483.648 a 2.147.483.647; le frazioni vengono arrotonde

CSng Single Da -3,402823E38 a -1,401298E-45 per valori negivi; da 1,401298E-45 a 3,402823E38 per valori positivi

CStr String I valori restituiti da CStr dipendono dall'argomento della funzione

CVar Variant Lo stesso intervallo di Double per valori numerici. Lo stesso intervallo di String per valori non numerici

Naturalmente il parametro passato a queste funzioni deve poter assumere un valore che rientra nell'intervallo specifico del tipo restituito: ad esempio non è possibile scrivere: CInt (100000.45) perché il valore 100000 è superiore al massimo consentito per un Integer.

Operatori matematici Visual Basic supporta tutti e quattro gli operatori matematici: quando combina due valori di diverso tipo applica automaticamente la coercision (o tipizzazione forzata) cioè converte il cibo più semplice in quello più completo (ad esempio da Integer a Long). / operatore di divisione : converte sempre il risultato in Double, quindi lo converte in base al tipo di risultato. \ effettua la divisione intera eliminando la parte decimale del quoziente. ^ operatore esponenziale Mod estrae il resto di una divisione tra valori al numero intero.

Operatori bit-wise (di bit) Permettono di operare su singoli bit degli operandi: AND permette di destare uno o più bit di un numero OR permette di impostare uno o più bit di un numero NOT inverte i bit di un operando XOR calcola l’ or esclusivo tra due operandi.

Operatori di arrotondamento La funzione Int tronca un numero all’intero minore o uguale al suo argomento Print Int(1.2) stampa 1 Print Int(-1.2) stampa -2

Operatori di conversione Per convertire una stringa in un numero si può utilizzare la funzione Val( ) Per convertire un numero da decimale a es decimale o ottale esistono le funzioni Hex( ) e Oct( )

Funzione di formattazione La funzione Format( ) è estremamente complessa e permette di soddisfare gran parte dei requisiti di formattazione richiesti.

Format(espressione, [Formato], …) Di solito bastano i primi due parametri, gli altri servono normalmente le date. Stringa riformato può essere fornita sia tramite nomi (General Number, Standard, Percent, Scienific, Yes/no, True/False,On/Off), sia tramite formati personalizzati. Esempi di formati personalizzati: “#,###.00” due cifre decimali e separatori delle migliaia “#.#%” valori percentuali “#.###E+” notazione scientifica con un segno per l’esponente “#.###E-“ notazione scientifica con un segno solo per l’esponente negativo “##,###.00;( ##,###.00); ;N/A” due cifre decimali per i numeri positivi, negativi tra parentesi, nulla per 0, N/A per i valori Null.

Page 19: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

19

Decima lezione – Vettori e matrici. Un problema abbastanza comune nella programmazione è quello di dover fare la media tra un discreto numero di valori, ad esempio 20 valori; in tal caso dovrei dichiarare 20 variabili diverse, impostare il valore opportuno per ciascuna di esse, sommarle e infine dividere la somma per 20! E' chiaro che questo modo di procedere è a dir poco laborioso: in questi casi è estremamente conveniente utilizzare i vettori , ovvero un insieme di variabili dello stesso tipo e con lo stesso nome, distinguibili le une dalle altre solo tramite un indice. La dichiarazione di un vettore di variabili si fa scrivendo tra parentesi il numero di elementi che deve avere il vettore: per esempio nel nostro caso potremmo scrivere: Dim Var(20) As Integer Avremo così a disposizione 20 variabili (anzi, in realtà 21 come spiegherò tra poco) di tipo Integer di nome Var: la prima variabile che ci interessa sarà Var(1), la seconda Var(2), ecc. fino alla ventesima, Var(20). Nella dichiarazione, il numero indicato tra parentesi indica il limite superiore del vettore, ovvero il valore massimo che può assumere l'indice: se provassimo a scrivere, ad esempio: var(21) = 1000 otterremmo un errore, perché il limite massimo dell'indice è 20. Il limite superiore deve essere compreso nell'intervallo di valori valido per il tipo Long (-2147483648/+2147483647): da ciò segue che è possibile specificare come limite superiore anche un valore negativo, ma bisogna tenere presente un paio di cose. Prima di tutto, così come c'è un limite superiore, c'è anche un limite inferiore per l'indice: se non è specificato nella dichiarazione, questo limite inferiore è per default 0; pertanto scrivendo: Dim Var(10) As Integer l'indice di questo vettore potrà andare da 0 a 10, e quindi il vettore avrà 11 elementi; se si desidera che l'indice parta sempre da 1 anziché da 0, è possibile utilizzare l'istruzione: Option Base 1 Questa istruzione, come l'analoga Option Explicit va inserita nella sezione generale del form. Però è anche possibile indicare entrambi i limiti, quello inferiore e quello superiore, nella dichiarazione stessa, usando la parola chiave To: Dim Var(1 To 10) As Integer indica un vettore con 10 elementi, il cui indice va da 1 a 10; analogamente si potrà scrivere: Dim Var(10 To 20) As Long oppure: Dim Pippo(-5 To 32) As String e così via. La seconda cosa da tenere presente è che, ovviamente, il limite inferiore deve sempre essere minore del limite superiore: perciò è sbagliato scrivere Dim Var(10 To 0) As Integer ed è anche sbagliato scrivere: Dim Var(-5) As Integer perché in questo caso il limite inferiore implicito è 0 o 1, che è maggiore di -5. Oltre ai vettori è possibile utilizzare anche matrici, che non sono altro che vettori a più dimensioni (o meglio, i vettori sono matrici a una sola dimensione). Ad esempio, supponiamo di voler memorizzare le dimensioni di 100 scatole: non ci basterà un vettore con 100 elementi, perché per ogni scatola avremo bisogno di 3 variabili per le 3 dimensioni (altezza, larghezza, profondità), pertanto dovremo utilizzare una matrice: Dim Scatole(1 To 100, 1 To 3) As Integer o anche: Dim Scatole(99,2) As Integer In entrambi i casi (se non avete inserito l'istruzione Option Base 1) avremo una matrice con 100 * 3 = 300 elementi, ovvero con 100 "righe" e 3 "colonne". Per indicare che si vogliono usare più dimensioni, quindi, bisogna separare i limiti di ogni dimensione con una virgola. E' possibile inoltre dichiarare una matrice dinamica, il cui numero di elementi può cambiare nel corso dell'esecuzione del programma: a questo scopo è però necessario usare una parola chiave apposita, ReDim, e dichiarare la matrice senza indicarne le dimensioni: Dim Var() As Long 'dichiarazione della matrice: 'non è indicata la dimensione della matrice e successivamente, in un altro punto del codice: ReDim Var(120) As Long 'ridimensionamento della matrice In tal caso è anche possibile utilizzare una variabile, anziché un'espressione costante, per indicare il limite inferiore e/o superiore della matrice, ad esempio: ReDim Var(x) As Long L'importante è ricordare che il ridimensionamento di una matrice riguarda esclusivamente il numero di elementi, non il loro tipo, né tantomeno il nome della matrice. A proposito del tipo degli elementi, è interessante notare che se essi sono Variant possono contenere a loro volta altre matrici o vettori:

Page 20: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

20

Dim Vettore(3) As Long Dim MatriceVariant(5,2) MatriceVariant(2,0) = Vettore MatriceVariant(2,1) = 10 MatriceVariant(1,2) = "stringa" Le istruzioni precedenti definiscono un semplice vettore di quattro elementi e una matrice di 18 (6 righe per 3 colonne) elementi Variant, ad uno dei quali è stato assegnato il nostro vettore: perciò l'elemento 2,0 della matrice non è semplicemente un numero, o una stringa, o un qualunque altro tipo elementare di dato, ma è esso stesso un vettore di 4 elementi. Per accedere a uno dei quattro elementi di MatriceVariant(2,0) bisogna usare questa sintassi: e e maMatriceVariant(2,0)(i) 'i varia da 0 a 3 E' come se la matrice bidimensionale MatriceVariant avesse, nel caso dell'elemento 2,0 (e SOLO per quell'elemento), una terza dimensione data dai 4 elementi del nostro vettore iniziale. Naturalmente il vettore e la matrice restano variabili (o meglio, insiemi di variabili) distinte e indipendenti, e per rendersene conto basta mettere alla prova queste semplici istruzioni: Dim vettore(3) As Long Dim MatriceVariant(5,2) Vettore(2) = 10 MatriceVariant(1,1) = Vettore Vettore(2) = 20 Debug.Print Vettore(2), MatriceVariant(1,1)(2) Nella finestra di debug si leggeranno i valori 20 e 10, perché MatriceVariant(1,1) non risente delle modifiche successive all'assegnazione del vettore all'elemento della matrice. Ritorniamo un momento a parlare di vettori dinamici. Quando effettuo un ridimensionamento di un vettore dinamico è possibile usare la funzione Ubound che restituisce il valore dell’indice più alto del vettore (0 se c’è un solo elemento, 3 se è dimensionato a V(2), ecc.). Inoltre quando ridimensioniamo un vettore il valore degli elementi precedentemente presenti verrebbe perso, a meno che non si utilizzi la frase Preserve che permette di mantenere in memoria i valori già assegnati.

Page 21: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

21

Undicesima lezione – Cicli For...Next. Spesso utilizzando i vettori, si deve effettuare la stessa elaborazione su più di un elemento (di solito tutti). Per utilizzare in modo efficiente i vettori non bisogna trattare gli elementi come se fossero variabili completamente distinte. Supponiamo ad es. di voler inizializzare gli elementi di un vettore a un certo valore: non avrebbe molto senso scrivere: Dim Vettore(2) As Long Vettore(0) = 10 Vettore(1) = 10 Vettore(2) = 10 perché in tal caso sarebbe come utilizzare tre variabili v1, v2, v3, distinte e indipendenti le une dalle altre: in altre parole, non si sfrutterebbe la loro appartenenza a un solo vettore che le comprende tutte. Talvolta è necessario agire in questo modo, ma spesso è molto più conveniente sfruttare la possibilità di accedere ad ogni elemento tramite il suo indice, e questo si fa usando i cicli. Un ciclo non è altro che un gruppo di istruzioni che vengono eseguite ripetutamente, ovvero ciclicamente, fino a che una certa condizione risulta verificata. Di cicli ne esistono vari tipi in Visual Basic, ma quello in assoluto più utilizzo è il ciclo For...Next. Questo ciclo è identificato da due istruzioni, poste rispettivamente all'inizio e alla fine del ciclo: For contatore = inizio To fine [istruzioni] Next contatore dove contatore indica una variabile numerica che "conta" quante volte devono essere eseguite le istruzioni comprese nel ciclo: essa assume un valore iniziale (inizio) e viene incrementa dall'istruzione Next fino a raggiungere il valore finale (fine). Il ciclo viene eseguito fintantoché il valore di contatore è minore o uguale a fine; il nostro esempio precedente risulterebbe trasformato così: Dim Vettore(2) As Long Dim i As Integer 'contore per il ciclo For i = 0 To 2 Vettore(i) = 10 Next i Alla prima esecuzione del ciclo i assume valore 0 e quindi il primo elemento del vettore è inizializzato a 10. Alla seconda esecuzione i è uguale a 1 ed è inizializzato il secondo elemento. Alla terza esecuzione i è uguale a 2 ed è inizializzato il terzo elemento; dopodiché i supera il valore 2 e quindi il ciclo termina.

Nella sintassi standard, le istruzioni contenute all'interno del ciclo sono eseguite fintantoché contatore risulta minatore o uguale a fine: ciò significa che, quando il ciclo termina, la variabile contatore ha un valore pari a fine + 1, perché nell'ultima esecuzione del ciclo risulta contatore = fine e l'istruzione Next incrementa ulteriormente il contatore. Questa è una caratteristica tipica dei cicli "For", che si riscontra anche negli altri linguaggi di programmazione: e non potrebbe essere altrimenti, in quanto l'esecuzione del ciclo termina proprio quando contatore supera il valore fine. Nella sintassi standard appena descritta, l'incremento del contatore è di una unità ad ogni esecuzione del ciclo, ma è possibile modificare il valore dell'incremento usando la clausola Step dopo il valore fine: For contatore = inizio To fine Step incremento [istruzioni] Next contatore All'inizio del ciclo il valore del contatore è uguale a inizio, alla seconda esecuzione del ciclo è uguale a inizio+incremento, alla terza esecuzione è uguale a inizio+incremento+incremento e così via fino a che il contatore diventa maggiore del valore fine. Il valore di incremento viene sommato algebricamente al valore corrente del contatore: ciò significa che l'incremento può anche essere negativo, determinando così una diminuzione progressiva del valore del contatore: in questo caso il ciclo cesserà di essere eseguito quando il contatore diventa minore del valore finale specificato. Perché il ciclo funzioni correttamente, quindi, il valore iniziale dovrà essere maggiore del valore finale, ad es. il ciclo seguente viene eseguito tre volte, per i=10, i=8, i=6; all'uscita dal ciclo sarà i=4: Dim i as Integer 'contatore For i = 10 To 5 Step -2 [istruzioni] Next i Si è detto che il contatore è una variabile numerica, senza specificare il suo tipo: infatti, benché esso sia solitamente un Integer, è possibile anche utilizzare valori frazionari come Single o Double, e lo stesso vale per i valori inizio, fine e incremento. Tuttavia, è sempre preferibile utilizzare valori interi per motivi di precisione: le variabili di tipo Single o Double, infatti, commettono errori di precisione che, per quanto piccoli, non sono affatto trascurabili; basta un errore di un milionesimo per far credere a Visual Basic che il valore finale sia stato superato e determinare anzitempo la fine del ciclo. Si consideri ad esempio il ciclo seguente: Dim i as Single For i = 0.6 To 0.8 Step 0.1 Debug.Print i Next i

Page 22: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

22

Debug.Print i In teoria esso dovrebbe essere eseguito per tre volte, con il contatore i che vale 0.6, 0.7 e 0.8; invece esso è eseguito soltanto due volte, per i = 0.6 e i = 0.7: quando i viene ulteriormente incremento non vale 0.8, bensì 0.8000001, che essendo maggiore di 0.8 determina l'interruzione del ciclo. Per questo motivo è sempre buona norma usare valori interi sia per il contatore che per i valori di inizio, fine e incremento, in quanto con valori interi il microprocessore non commette quegli errori di imprecisione che possono determinare comportamenti anomali. Naturalmente i valori iniziale e finale del contatore, ovvero il numero di iterazioni, non devono necessariamente essere stabiliti esplicitamente durante la scrittura del codice: essi possono essere determinati durante l'esecuzione del programma semplicemente utilizzando delle variabili aggiuntive: ad esempio, il programma potrebbe chiedere all'utente quali debbano essere i valori di inizio e fine del contatore e memorizzare questi valori in due variabili da usare nell'istruzione For: Dim i as Integer 'contatore Dim intInizio as Integer , intFine as Integer 'valori iniziale e finale intInizio= Val ( InputBox ("Inserisci il valore iniziale del contatore:")) intFine= Val ( InputBox ("Inserisci il valore finale del contatore:")) For i = intInizio To intFine Debug.Print i Next i In questo esempio si è fatto uso della funzione InputBox, che richiede all'utente l'inserimento di un valore in una casella di testo: tale valore è quello restituito dalla funzione, e poiché è di tipo stringa esso deve essere convertito in numero traverso la funzione Val. È chiaro che se l'utente inserisce nella casella un valore che non può essere convertito in numero (ad es. "a56bc"), sarà generato un errore causato dalla funzione Val. Come per altri blocchi di istruzioni, anche per i blocchi For…Next è possibile usare la nidificazione, ovvero includere un blocco For all'interno di un altro blocco For: For i = 1 To 10 For k = 5 To 22 [istruzioni] Next k Next i La cosa importante è non intersecare mai due cicli distinti, ovvero non fare mai una cosa del genere: For i = 1 To 10 'inizio PRIMO ciclo For k = 5 To 22 'inizio SECONDO ciclo [istruzioni] Next i 'fine PRIMO ciclo Next k 'fine SECONDO ciclo Così facendo si genera un errore di sintassi, perché l'istruzione "Next i" non corrisponde all'istruzione "For k" che la precede: il secondo ciclo non è interamente contenuto nel primo, ma si sovrappone ad esso generando confusione. Volendo, è possibile anche omettere il nome del contatore nell'istruzione Next, e in tal caso Visual Basic assumerà automaticamente che esso si riferisce all'istruzione For immediatamente precedente For i = 1 To 10 For k = 5 To 22 [istruzioni] Next ' Visual Basic assume che l'istruzione sia: Next k Next ' Visual Basic assume che l'istruzione sia: Next i Spesso è necessario interrompere l'esecuzione di un ciclo se si verifica una determina condizione: Visual Basic mette a disposizione del programmatore un'istruzione apposita: Exit For , che sposta il punto di esecuzione del programma all'istruzione immediatamente successiva all'istruzione Next relativa al ciclo interrotto. Solitamente questa istruzione si fa dipendere da un blocco If che controlla il verificarsi di una "condizione di uscita": For i = 1 To 10 If i = 8 Then Exit For Debug.Print i Next i Debug.Print "ciclo interrotto" Il ciclo precedente, che semplicemente visualizza il valore del contatore, teoricamente dovrebbe essere eseguito dieci volte ma in realtà è eseguito solo otto volte, perché all'ottava esecuzione la condizione i = 8 risulta verificata determinando l'uscita dal ciclo (senza stampare il valore del contatore) e la visualizzazione del messaggio "ciclo interrotto"; si noti che questo messaggio sarebbe visualizzato in ogni caso, al termine del ciclo. I "puristi" della programmazione non vedono di buon occhio l'utilizzo dell'istruzione Exit For, perché in questo caso il ciclo non termina solo con l'ultima istruzione "Next", come ci si potrebbe aspettare in condizioni normali, ma potrebbe terminare anche all'interno del ciclo stesso: ciò determina un'eccezione alla normale esecuzione del codice e pertanto potrebbe complicarne la comprensione e la modifica. In effetti utilizzare l'istruzione Exit For non è l'unico modo per interrompere un ciclo: sapendo che esso termina quando il contatore supera il valore finale, la soluzione più intuitiva sarebbe quella di assegnare al contatore un valore maggiore del limite finale in modo che il ciclo non prosegua oltre: For i =1 To 10 If i = 8 then i =11 Debug.Print i

Page 23: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

23

Next i Debug.Print "ciclo interrotto" Nell'esempio precedente, quando i=8 il programma assegna al contatore il valore 11, cioè un valore superiore al limite di 10 specificato nell'istruzione For; in questo modo il ciclo non è interrotto direttamente, e infatti l'istruzione Debug.Print i è eseguita normalmente anche quando i=8, però l'istruzione Next i verifica che il contatore ha supero il limite e quindi determina la fine del ciclo e la visualizzazione del messaggio "ciclo interrotto". Tuttavia, da un punto di vista stilistico questa soluzione è ancora peggiore della precedente, perché il valore del contatore non dovrebbe mai essere modificato direttamente all'interno del ciclo stesso: un metodo del genere può complicare molto il debug e l'eventuale modifica del codice perché può generare errori imprevisti e generalmente difficili da identificare.

Page 24: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

24

Dodicesima lezione – Cicli Do...Loop. Visual Basic mette a disposizione del programmatore vari tipi di cicli iterativi; nell'ultima lezione abbiamo visto il ciclo principale (For… Next), ora vedremo un altro ciclo molto importante: il Do…Loop. Come il ciclo For…Next, anche il ciclo Do…Loop esegue un gruppo di istruzioni finché risulta verificata (o falsificata, a seconda del punto di vista) una determinata condizione: questa condizione deve essere preceduta da una parola chiave che indica se il proseguimento del ciclo è subordinato alla verità o falsità della condizione. Le due parole chiave che possono essere utilizzate sono While e Until : la prima indica che la condizione specifica deve risultare vera affinché il ciclo prosegua, la seconda indica che la condizione deve risultare falsa affinché il ciclo prosegua. Ecco un esempio di ciclo Do…Loop: Dim i as Integer i = 1 Do While i<10 i = i+1 Debug.Print i Loop Debug.Print "i vale " + cstr (i)+": il ciclo è terminato" Questo ciclo incrementa e stampa il valore della variabile i fintantoché essa resta minatore di 10: quando i assume il valore 10 la condizione i<10 risulterà falsa, e poiché nel ciclo è specifica la parola chiave While, il ciclo si interromperà e il controllo passerà all'istruzione successiva all'istruzione Loop. Lo stesso identico ciclo può essere espresso anche utilizzando la parola chiave Until: Dim i as Integer i = 1 Do Until i>=10 i = i+1 Debug.Print i Loop Debug.Print "i vale " + cstr (i)+": il ciclo è terminato" Avendo utilizzato Until, è necessario invertire la condizione di controllo affinché i due cicli siano equivalenti: nel primo esempio il ciclo era eseguito mentre (o se) i<10 è vera, nel secondo esempio il ciclo è eseguito fintantoché i>=10 è falsa, poiché il valore iniziale di i è sempre 1. In termini più generali, dato un ciclo Do While: Do While condizione [istruzioni] Loop il ciclo Do Until equivalente sarà Do Until Not condizione [istruzioni] Loop Da questi esempi appare con evidenza una forte analogia con il ciclo For visto sopra: in effetti le differenze sono ben poche, tant'è vero che qualunque ciclo For può essere espresso come un ciclo Do e viceversa. L'uso di un ciclo al posto di un altro va deciso in base a questioni di convenienza: si sceglie l'istruzione più semplice, più immediata, più facilmente comprensibile: negli esempi appena considerati il ciclo For è leggermente preferibile al ciclo Do, perché è più intuitivo e consente di evitare l'istruzione di incremento della variabile i, che in questi casi funge da "contatore": è proprio l'istruzione For…Next che si occupa di inizializzare e incrementare la variabile, e così il programmatore deve solo preoccuparsi di stamparne il valore. In generale, il ciclo For è preferibile quando si conosce con esattezza il numero di iterazioni, ossia quando si sa per quante volte il ciclo deve essere eseguito; il ciclo Do è preferibile invece quando è necessaria più flessibilità, quando il numero di iterazioni non può essere conosciuto a priori. Ad esempio, si supponga di dover eseguire ciclicamente un gruppo di istruzioni finché l'utente non dice "basta!": non è possibile sapere in anticipo di quanta pazienza disponga l'utente, perciò è opportuno ricorrere a un ciclo Do che controlli il verificarsi di una condizione. In casi come questi, solitamente si fa ricorso all'utilizzo di una variabile flag di tipo booleano, che assuma il valore vero (o falso, a seconda della convenienza) quando l'utente decide di interrompere il ciclo: Dim blnFlag as Boolean 'flag di controllo del ciclo Do While blnFlag Debug.Print Rnd () Loop Questo semplice ciclo continua a visualizzare numeri casuali finché la variabile blnFlag è vera: il ciclo si interromperà quando il flag, a seguito di un'azione dell'utente o al verificarsi di altre condizioni, assumerà il valore False. Per esempio, si inserisca in un Form un pulsante di comando e un'etichetta di testo: si imposti la Caption del CommandButton a "Avvia" e nella routine Click si scriva Private Sub Command1_Click() If blnFlag Then Command1.Caption = "Avvia" blnFlag = False

Page 25: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

25

Else Command1.Caption = "Interrompi" blnFlag = True End If Do While blnFlag Label1.Caption = CStr ( Rnd()) DoEvents Loop End Sub La subroutine controlla innanzitutto il valore del flag (che naturalmente deve essere dichiarato a livello di modulo): se è falso (impostazione predefinita iniziale per tutte le variabili booleane), esso diventa vero e il ciclo Do successivo può essere eseguito dando il via alla visualizzazione dei numeri casuali; altrimenti diventa falso e quindi il ciclo Do si interrompe; inoltre viene modificata la Caption del pulsante per far capire all'utente l'effetto della pressione del pulsante stesso. Nel ciclo Do compare l'istruzione DoEvents, che restituisce temporaneamente il controllo al sistema operativo per consentirgli di gestire altre operazioni accumulatesi durante l'esecuzione del nostro programma: senza questa istruzione, a causa del modo con cui Windows gestisce il multitasking, il programma si bloccherebbe nell'esecuzione del ciclo, perché la pressione del pulsante non avrebbe alcun effetto. Detto con parole poco precise, il programma è così impegnato ad eseguire il ciclo Do che non ha il tempo di gestire gli altri input forniti dall'utente (come la pressione del pulsante), né di aggiornare l'aspetto degli altri componenti del Form (l'etichetta non mostra nulla), a meno che non ci sia un'istruzione esplicita che obblighi il nostro programma a cedere momentaneamente il controllo al sistema operativo: questo è appunto il compito dell'istruzione DoEvents. Senza di essa l'unico modo per interrompere il programma è premere la combinazione di tasti ctrl+alt+canc se il programma è sto compilato; se invece è eseguito all'interno dell'IDE di Visual Basic basta premere ctrl+pausa. L'eliminazione dell'istruzione DoEvents impedisce di modificare il flag blnFlag una volta che il ciclo Do è cominciato: la variabile booleana pertanto resta sempre True, e di conseguenza il ciclo non si interromperà mai; questo è un semplice esempio di ciclo infinito. La presenza di cicli infiniti è uno dei classici bug commessi da programmatori alle prime armi, ma anche da programmatori un po' più esperti: quando la condizione di controllo del ciclo dipende da diversi fattori può essere difficile rendersi conto dell'errore commesso, anche perché di norma l'errore sarà tanto più "nascosto" quanto più si presenta raramente nel corso dell'esecuzione. Per questo motivo è necessario stare bene attenti a fornire una condizione di uscita dal ciclo: se c'è il rischio che la condizione di controllo resti sempre vera (se si usa While) o sempre falsa (se si usa Until), può essere opportuno utilizzare ancora l'istruzione Exit; nel caso del ciclo For l'istruzione corretta era Exit For, nel caso del ciclo Do l'istruzione corretta è Exit Do. L'esempio precedente potrebbe quindi essere riscritto in questo modo: Private Sub Command1_Click() If blnFlag Then Command1.Caption = "Avvia" blnFlag = False Else Command1.Caption = "Interrompi" blnFlag = True End If Do While True 'ciclo virtualmente infinito Label1.Caption = CStr ( Rnd()) DoEvents If Not blnFlag Then Exit Do 'condizione di uscita dal ciclo Loop End Sub Il ciclo è potenzialmente infinito, perché la condizione di controllo non è una vera e propria condizione, ma è un valore letterale costante (True) che in quanto tale non potrà mai diventare False: la condizione di uscita è quindi ottenuta tramite un controllo interno al ciclo, che esamina il valore del flag: se questo è falso, significa che l'utente vuole interrompere il ciclo, pertanto Not blnFlag sarà True e sarà eseguita l'istruzione Exit Do che passa il controllo all'istruzione successiva al ciclo (in questo caso End Sub). La clausola While o Until può trovarsi alternativamente dopo l'istruzione Do o dopo l'istruzione Loop: Do While|Until condizione [istruzioni] Loop oppure Do [istruzioni] Loop While|Until condizione La differenza consiste nel momento in cui è controllato il valore di condizione: nel primo caso il controllo avviene all'inizio di ogni iterazione, nel secondo caso alla fine di ogni iterazione. Ciò significa che se per ipotesi la condizione risulta subito falsa (o vera, se si usa Until), nel primo caso il ciclo non sarà eseguito mai, mentre nel secondo caso sarà eseguito solo una volta, perché la condizione è controllata dopo l'esecuzione delle istruzioni. La condizione di controllo del ciclo può naturalmente essere rappresentata da un'espressione booleana anche complessa, come la seguente:

Page 26: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

26

Do While blnFlag And (intUsers > 1 Or _ intUsers = -1) And ((lngCount Xor lngMax) = 20) [istruzioni] Loop In questi casi bisogna tenere presente che la condizione è sempre e soltanto una, che viene valutata tenendo conto complessivamente del valore delle singole parti e degli operatori logici utilizzati: quando l'intera espressione è vera, il ciclo prosegue, quando diventa falsa il ciclo si interrompe. Trasformare un ciclo del genere nel corrispondente Do Until…Loop può diventare molto complicato se si cerca di convertire ogni parte della condizione nel corrispondente opposto: in questo caso, l'equivalente sarebbe Do Until Not blnFlag Or (intUsers <= 1 And _ intUsers <> -1) Or ((lngCount Xor lngMax) <> 20) [istruzioni] Loop Ma la cosa più semplice è premettere un Not all'intera condizione: Do Until Not (blnFlag And (intUsers > 1 Or _ intUsers = -1) And ((lngCount Xor lngMax) = 20)) [istruzioni] Loop Infine, come per i cicli For, anche i cicli Do possono essere nidificati a più livelli: ogni istruzione Loop corrisponderà all'istruzione Do immediatamente precedente, in modo che ogni ciclo sia interamente contenuto nel ciclo più esterno, come nell'esempio seguente: Do While condizione1 Do [istruzioni2] Loop Until condizione2 [istruzioni1] Loop

Page 27: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

27

Tredicesima lezione – Struttura Select Case. Terminato il discorso sui cicli, passiamo a considerare un'altra istruzione utilizzata spesso per controllare il flusso del programma: l'istruzione Select case. Essa analizza un'espressione ed esegue istruzioni differenti in base al suo valore. Detto così sembra che l'istruzione Select case sia del tutto simile all'istruzione If, e in effetti è così: infatti è possibile esprimere una Select case come un blocco If con un adeguato numero di clausole ElseIf. La scelta tra le due di solito dipende da considerazioni di convenienza e di leggibilità del codice, perché spesso un blocco Select risulta strutturalmente più semplice di un blocco If. La sintassi dell'istruzione Select Case è la seguente: Select Case espressione Case valore-1 Istruzioni-1 Case valore-2 Istruzioni-2 … [Case Else istruzioni-else] End Select Espressione è una variabile, una proprietà o una qualunque espressione che può assumere diversi valori e che va confrontata coi valori elencati nei vari "casi"; nel caso in cui il valore dell'espressione sia valore-1, saranno eseguite le istruzioni istruzioni-1 (che ovviamente possono essere più di una); se il valore è valore-2, saranno eseguite le istruzioni istruzioni-2, e così via, per tutti i casi elencati. Se espressione assume un valore che non rientra in quelli specificati, sarà eseguito il blocco di istruzioni istruzioni-else, se è presente: infatti, come per l'istruzione If, anche nella Select Case il blocco Else è facoltativo; inoltre, come si è visto più volte, anche per questa istruzione vale la regola di indicarne la fine con l'istruzione End Select. Ecco un esempio di istruzione Select case: Select Case lblEtichetta.Caption Case "Testo1" lblEtichetta.FontSize = 12 Case Else lblEtichetta.FontName = "Arial" lblEtichetta.FontSize = 11 End Select Nel caso in cui fosse necessario eseguire lo stesso blocco di istruzioni in corrispondenza di più valori di espressione, l'elenco di questi valori va separato con la virgola; ad esempio, il blocco precedente può essere modificato in questo modo: Select Case lblEtichetta.Caption Case "Testo1", "Testo2", "" lblEtichetta.FontSize = 12 Case Else lblEtichetta.FontName = "Arial" lblEtichetta.FontSize = 11 End Select L'elenco di valori con cui va confrontata l'espressione può assumere anche altre forme, che risultano particolarmente utili quando l'espressione da controllare è di tipo numerico: è possibile infatti indicare un intervallo di valori usando l'operatore To o usando l'operatore Is seguito da un operatore di confronto, come nell'esempio seguente Select Case lblEtichetta.FontSize Case Is < 8, 12 To 14, 18 lblEtichetta.FontSize = 12 Case Else lblEtichetta.FontName = "Arial" End Select In questo esempio la dimensione del carattere dell'etichetta sarà imposto a 12 punti se esso è minore di 8, compreso tra 12 e 14 (estremi inclusi), oppure uguale a 18; altrimenti la dimensione del font non sarà modificata ma il tipo di carattere diventerà Arial. La clausola Else, pur non essendo obbligatoria, è comunque opportuna per gestire i casi "imprevisti", ad esempio generando un messaggio di errore per notificare all'utente che il valore dell'espressione non rientra in quelli previsti. Infine, come per l'istruzione If, anche le istruzioni Select Case possono essere nidificate: ovvero, dopo ogni clausola Case le istruzioni da eseguire possono includere un altro blocco Select Case, il quale a sua volta ne può contenere un altro, e così via.

Page 28: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

28

Quattordicesima lezione - Stringhe Tra le funzioni predefinite in Visual Basic rivestono particolare interesse le funzioni stringa: tali funzioni permettono di manipolare e di modificare stringhe di caratteri. LCase(stringa) Restituisce la stringa specificata come parametro con tutti i caratteri maiuscoli convertiti in minuscolo. Lascia

inalterati tutti gli altri caratteri. Instr([inizio,]stringa1, stringa2 [,confronto])

Restituisce un intero che specifica la posizione della prima occorrenza di una stringa all'interno di un'altra. Inizio, se specificato, indica il numero del carattere da cui iniziare alla ricerca. Stringa1 indica la stringa dove eseguire la ricerca, stringa2 è la stringa da ricercare. confronto assume i valori vbTextCompare (ricerca case in sensitive), vbBinaryCompare (ricerca case sensitive) (Default). Option Compare Text 'confronto testuale Option Compare Binary 'confronto binario Istruzioni che determinano a livello di modulo l'impostazione predefinita per confrontare le stringhe

InstrRev(stringa1, stringa2[, inizio[, confronto]])

Restituisce la posizione di un'occorrenza di una stringa inclusa in un'altra a partire dalla fine della stringa.

Left(stringa,lunghezza) Restituisce una stringa composta da un numero di caratteri uguale alla lunghezza ed estratti dalla stringa specificata come parametro, a partire da sinistra

Len(stringa) Restituisce un intero che indica il numero di caratteri presenti in una stringa Mid(stringa, inizio[,lunghezza]) Estrae da stringa un numero di caratteri uguale a lunghezza a partire dal carattere di posizione = inizio. Se il

parametro lunghezza è o mi sono vengono restituiti tutti i caratteri dalla posizione inizio alla fine della stringa Right(stringa,lunghezza) Restituisce una stringa composta da un numero di caratteri uguale alla lunghezza ed estratti dalla stringa

specificata come parametro, a partire da destra UCase(stringa) Restituisce la stringa specificata come parametro con tutti i caratteri minuscoli convertiti in maiuscolo. Lascia

inalterati tutti gli altri caratteri. LTrim(stringa), RTrim(stringa) Trim(stringa)

Consentono, rispettivamente, di ottenere una copia di una stringa senza spazi iniziali, spazi finali o senza spazi iniziali e finali.

StrComp() permette di eseguire un confronto fra due stringhe. La funzione restituisce il valore -1 nel caso in cui la prima stringa sia minore della seconda, 0 se vale il viceversa

Str è una funzione molto importante che permette di convertire un valore numerico in una stringa di carattere String(numcar,”car”) Permette di creare una stringa di caratteri “car” ripetuti per la lunghezza specificata da numcar Space(numcar) Restituisce una stringa costituita dal numero specificato di spazi. Replace(source, find, replace,[ start], [count], [metodo])

Trova e sostituisce rapidamente sottostringhe

Split( .. ) Trova ed isola tutti gli elementi delimitati in una stringa. Ritorna normalmente uno array Join( …) È il complementare di Split; accetta un array di stringhe ed un carattere delimitatore e ricrea la stringa originale Filter ( … ) Analizza rapidamente un array, cercando una sottostringa e restituisce un altro array contenente solo gli

elementi che includono la sottostringa ricercata Format ( … ) Permette di formattare le stringhe

L’operatore & permette di accodare una stringa ad un'altra. Il confronto tra due stringhe si fa con l’operatore = che determina se due stringhe sono proprio uguali. Esiste anche l'operatore Like : questo operatore, in base all'impostazione definita con l'istruzione Option Compare (l'impostazione predefinita è sempre Binary), restituisce un valore booleano che indica la corrispondenza tra due stringhe, permettendo anche l'uso dei caratteri jolly; ad es.:

"Abraini" like "Abr?i*" restituisce True "Abraini" like "abr?i*" restituisce True (se si è specifico Option Compare Text)

I caratteri jolly possono comparire solo nella stringa di destra dell'operatore like, ovvero nel "criterio" con cui si confronta la stringa:

sStringa Like sCriterio

Ovviamente caratteri come asterisco e punto di domanda possono comparire anche nell'espressione a sinistra, ma non vengono interpretati come caratteri jolly; per chi non lo sapesse, il preciso significato di questi particolari caratteri è il seguente:

* zero o più caratteri ("" Like "*" restituisce True, come anche "abc" Like "*c") ? un qualunque carattere (uno e uno solo però: "abc" Like "?abc" restitu isce False)

Vediamo qualche altro esempio: ESPRESSIONE RISULTATO "abc" Like "*abc" True "abc*" Like "*abc" False (l'asterisco a sinistra di Like è un caratte re come gli altri) "abc*" Like "*abc?" True "*" Like "?" True "" Like "?" False

Esiste poi un altro carattere "jolly" utilizzabile con l'operatore Like (l'asterisco e il punto di domanda hanno validità universale, questo no): # una e una sola cifra da 0 a 9 Ad es. "abc0k" Like "*#?" restituisce True, come anche "abc0k" Like "*??" oppure anche "abc0k" Like "*": una cifra è pur sempre un carattere, pertanto è riconosciuto dai caratteri jolly * e ?, ma all'occorrenza è possibile identificarlo come cifra usando #. Infine, è possibile specificare un determinato intervallo di caratteri tra parentesi quadre; ad es., al posto di usare # per le cifre è possibile usare l'intervallo [0-9]:

Page 29: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

29

"abc0k" Like "*[0-9]?" restituisce true C'è tutta una sintassi particolare, e anche un po' complessa, per usare compiutamente le opportunità offerte dall'operatore Like, ma anche un uso semplice con i tre caratteri jolly più utilizzati (*, ?, #) è già molto potente. Ad es., per verificare che un codice alfanumerico corrisponda (almeno nella forma) a un codice fiscale, basta scrivere:

sCodice Like "[A-Z][A-Z][A-Z][A-Z][A-Z][A-Z]##[A-Z]##[A-Z]## #[A-Z]" ESEMPI:

Stringa1=”ciao” Stringa2=” a ” Stringa3=”tutti” Stringa=Stringa1 & Stringa2 & Stringa3 Debug.print Stringa

Nella finestra di Debug verrà visualizzata la frase: ciao a tutti

Le istruzioni: Debug.print Len(stringa) Debug.print Left(stringa,5) Debug.print Right(stringa,5) Debug.print Mid(stringa,6,1) Debug.print UCase(stringa)

Visualizzeranno: 12 ciao tutti a CIAO A TUTTI

Ancora: Stringa = String(5, "*") 'Associa a Stringa il valore ***** Spazi = Space(10) 'Restituisce una stringa chiamata Spazi costituita da 10 spazi.

Page 30: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

30

Quindicesima lezione - Debug e gestione degli errori Il debug è la procedura che permette a uno sviluppatore di scovare e correggere i "bug", ovvero gli errori e le imperfezioni presenti nel codice sorgente di un'applicazione: poiché anche in applicazioni semplici è quasi impossibile evitare del tutto errori o semplici sviste, è necessario sempre rivedere il funzionamento del programma sviluppato con l'aiuto degli strumenti di debug per verificare che tutto funzioni correttamente. Anzi, nella stragrande maggioranza dei casi le operazioni di debug sono molto più lunghe e complesse dello sviluppo vero e proprio dell'applicazione, e la complessità del debug è direttamente proporzionale (se non addirittura più che proporzionale) alla complessità dell'applicazione da testare. L'IDE di Visual Basic cotiene un intero menù è dedicato al debug del codice: al suo interno ci sono varie voci che consentono allo sviluppatore di eseguire la propria applicazione istruzione dopo istruzione ( "passo-passo" o single step- tasto F8) o routine dopo routine (step over Misc+F8), di vedere in ogni momento il valore di tutte le variabili utilizzate dall'applicazione, di interrompere o modificare il flusso di esecuzione delle istruzioni, impostando dei breakpoint (tasto F9), far eseguire l’applicazione fino ad un certo punto. Quando un progetto viene avviato dall'IDE di Visual Basic e si verifica un errore, è lo stesso IDE a interrompere l'esecuzione del codice mostrando il punto in cui si verifica l'errore e consentendo quindi di effettuare il debug di quella porzione di codice; ovviamente però ciò non accade se l'errore si verifica quando il programma è già stato compilato: infatti in tal caso non c'è l'IDE di Visual Basic a supportare i comandi di debug e, se non è stato previsto un modo per intercettare e possibilmente correggere gli errori di run-time, l'unico esito possibile è il blocco dell'applicazione. Occorre quindi escogitare un modo per permettere al programma stesso di sapere quando si verifica un eventuale errore e provvedere, se possibile, alla sua correzione permettendo la normale continuazione dell'esecuzione del codice: si tratta del cosiddetto error handling, ovvero intercettazione degli errori. Visual Basic mette a disposizione una comoda istruzione per implementare l'error handling : l'istruzione On error goto. questa istruzione ordina al programma di saltare a un certo punto del codice, identificato da un'etichetta, quando si verifica un errore; solitamente la struttura di una routine con l'error handling è simile alla seguente:

Sub Prova() 'dichiarazioni di variabili '… On Error GoTo ErrorHandling 'istruzioni proprie della routine '… '… Exit Sub ErrorHandling: 'codice destinato all'intercettazione dell'errore '… '… End Sub

Si possono notare diverse cose: innanzitutto, l'istruzione che permette l'intercettazione degli errori (On Error GoTo) è la prima istruzione eseguibile della routine, subito dopo le dichiarazioni di variabili; questo perché è importante intercettare un errore in qualunque punto del codice avvenga, infatti l'intercettazione viene abilitata solo dall'istruzione On Error GoTo in poi: se tale istruzione fosse posta, supponiamo, a metà routine, un eventuale errore che si verificasse prima di essa non sarebbe intercettato. L'istruzione On Error GoTo avverte che quando si verifica un errore l'esecuzione del programma deve saltare al punto identificato dall'etichetta "ErrorHandling", che si trova in fondo alla routine, subito dopo l'istruzione Exit Sub (Exit Function nel caso di funzioni): dopo l'etichetta ci sono le istruzioni che esaminano l'errore verificato (tipicamente con una Select Case e tentano di risolverlo. L'etichetta è preceduta dall'istruzione Exit Sub per un motivo molto semplice: evitare che la parte di codice destinata a intercettare gli errori (ovvero le istruzioni successive all'etichetta) sia eseguita ad ogni esecuzione della routine. Senza Exit Sub, infatti, le istruzioni di error handling sarebbero eseguite in ogni caso, indipendentemente dal verificarsi o meno di un errore e ciò può comportare a sua volta degli errori, oltre ad essere logicamente scorretto. Per assicurarsi quindi che quelle istruzioni siano eseguite solo quando effettivamente si verifica un errore, occorre farle precedere da un'istruzione che interrompa la routine nel caso in cui non ci sia stato alcun errore: l'istruzione Exit Sub, per l'appunto. Quando si verifica un errore di run-time, Visual Basic imposta le proprietà dell'oggetto Err, che devono essere esaminate al fine di capire cosa è successo e come reagire: ogni errore standard definito in Visual Basic è identificato da un numero e da una descrizione (proprietà "Number" e "Description" dell'oggetto Err); vediamo ad esempio questo pezzo di codice: Dim nRisultato as Integer nRisultato= CLng(txtNumeratore(mnIndex).Text) / CLng(txtDenominatore(mnIndex).Text)

dove la variabile mnIndex è un Integer dichiarata a livello di modulo che indica quali elementi delle due matrici di controlli TextBox "txtNumerore" e "txtDenominatore" occorre considerare; per il momento non ci interessa sapere come viene calcolato mnIndex, né cosa indichino esattamente le variabili coinvolte; basta sapere che anche in un'istruzione semplice come questa i possibili errori sono almeno quattro: 1) mnIndex non è compreso tra i limiti inferiore e superiore delle matrici di controlli: "indice non compreso nell'intervallo" (errore 9); 2) il contenuto dei TextBox non è un numero, e di conseguenza la funzione CLng() fallisce: "Tipo non corrispondente" (errore 13);

Page 31: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

31

3) txtDenominatore(mnIndex).Text è uguale a "0": "divisione per zero" (errore 11); 4) il rapporto tra i numeri contenuti nei due TextBox è esterno all'intervallo -32768/+32767 valido per gli integer: "Overflow" (errore 6) Per intercettare un'eventuale errore scriviamo allora un'apposita routine:

Dim nRisultato as Integer On Error GoTo Errore nRisultato= CLng(txtNumeratore(mnIndex).Text) / CLng(txtDenominatore(mnIndex).Text) Exit Sub 'oppure Exit Function, a seconda dei casi Errore: Select Case Err.Number

Case 6 'Overflow MsgBox "Il numeratore è troppo grande", vbOkOnly Case 9 ' indice non compreso nell'intervallo MsgBox "Non esiste un TextBox con indice " & _ CStr(mnIndex), vbOkOnly Case 11 ' divisione per zero MsgBox "Il valore inserito in txtDenominatore" & _ " deve essere diverso da zero", vbOkOnly Case 13 ' Tipo non corrispondente MsgBox "Non hai inserito un valore numerico", vbOk Only

End Select End Sub 'termine della routine

In questo semplice caso ci siamo limitati a visualizzare il tipo di errore riscontrato, senza tentare di risolverlo; d'altra parte sarebbe un compito abbastanza arduo da fare automaticamente, senza ricorrere all'aiuto dell'utente. In altri casi invece è più semplice risolvere in modo automatico l'errore; supponiamo ad esempio di voler aprire un file inesistente in sola lettura:

Open "c:\pippo.txt" For Input Access Read as #1

Poiché l'apertura del file è in sola lettura, se esso non esiste non sarà automicatamente creato (cosa che invece accadrebbe se il file fosse aperto anche in scrittura); per risolvere il problema possiamo intercettare l'errore:

On Error GoTo Errore Open "c:\pippo.txt" For Input Access Read as #1 Exit Sub Errore: If Err.Number=53 Then ' descrizione: impossibile tr ovare il file Open "c:\pippo.txt" For Output Access Write as #1 Close 1 Resume End If End Sub

In questo caso, se il file non esiste viene creato tentando di aprirlo in modalità di scrittura, dopodiché il controllo torna all'istruzione che ha generato l'errore grazie all'istruzione "Resume". Per ora basti notare che esiste un modo più semplice ed elegante di evitare questo errore banale, ovvero controllare in anticipo se il file esiste, prima della sua apertura:

If Len(Dir$("C:\pippo.txt"))=0 Then Open "c:\pippo.txt" For Output Access Write as #1 Close 1 End If Open "c:\pippo.txt" For Input Access Read as #1

La funzione Dir() restituisce il nome del file indicato come argomento: se restituisce la stringa nulla (di lunghezza zero), significa che il file non esiste: quindi viene aperto in scrittura (cioè creato) e subito chiuso; dopodiché viene normalmente aperto in lettura; se invece esiste già, viene aperto soltanto aperto in lettura. L'istruzione Resume, riprende l'esecuzione dopo il completamento di una routine di gestione degli errori. Solitamente è usata in due modi: Resume, riprende l'esecuzione dalla stessa istruzione che ha causato l'errore; Resume Next, riprende l'esecuzione dall'istruzione successiva a quella che ha provocato l'errore. L'istruzione Resume Next può anche essere usata insieme all'istruzione On Error: in questo modo si dice al programma che, ogni volta che si verifica un errore, il problema deve essere ignorato e l'esecuzione deve passare all'istruzione successiva. Per fare questo è sufficiente scrivere:

On Error Resume Next

Page 32: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

32

Sedicesima lezione – Gestione dei files Un file è un agglomerato di informazioni residente su un supporto di memorizzazione di massa, ovvero su un dispositivo caratterizzato dalla capacità di mantenere i dati anche dopo lo spegnimento e il successivo riavvio del sistema. Di solito si tratta di un'unità a disco fisso o rimovibile. Le informazioni contenute in un file non devono essere necessariamente di tipo omogeneo. Esiste infatti la possibilità di creare dei file strutturati, in grado cioè di contenere elementi di pari caratteristiche, oppure composti da informazioni di natura anche profondamente diversa. Visual Basic permette di creare 3 diversi tipi di file, con accesso sequenziale o casuale.

File ad accesso sequenziale Le strutture più elementari sono i file ad accesso sequenziale, il cui uso è in genere riservato alla memorizzazione delle informazioni testuali. Si tratta di strutture organizzate in righe, da utilizzare quando si desidera salvare dei documenti da stampare oppure per la memorizzazione di limitate quantità di dati (come ad esempio quelle riguardanti le impostazioni di un programma). Il vantaggio offerto dai file ad accesso sequenziale è rappresentato dalla semplicità con cui è possibile accedere al loro contenuto mediante un qualsiasi editor di testo, come il Blocco Note di Windows. Sono di questo tipo, ad esempio, i file Win.ini e System.ini, contenenti le informazioni riguardanti la configurazione dell'ambiente Windows a 16 bit. L'organizzazione dei dati, tuttavia, fa sì che le strutture di questo tipo non siano adatte a contenere una grande quantità di informazioni, a causa del dilatarsi dei tempi di accesso dovuto al fatto che la ricerca di un particolare dato può comportare la lettura dell'intero file. L'apertura di un file sequenziale Un file, di qualsiasi tipo esso sia, per poter essere utilizzato deve necessariamente essere aperto. È possibile effettuare ciò per mezzo del comando, la cui sintassi, per le strutture ad accesso sequenziale, è la seguente:

Open <percorso_file> [For <modalità>] As [#]<numero_identificatore> [Len=<lunghezza_record>]

dove <percorso_file> è una stringa che identifica il percorso del file che si desidera creare o leggere..Dopo aver specificato il nome del file da gestire, è necessario indicare la modalità con cui si desidera accedere ad esso. La scelta è fra Input , Output e Append. Nel primo caso, il file è aperto in lettura, ovvero è utilizzato esclusivamente per reperire delle informazioni senza effettuare su di esse alcuna modifica. È evidente che l'apertura di un file in questa modalità richiede che esso sia stato in precedenza creato sul disco, altrimenti provoca la notifica di un errore.Diversamente accade invece per i file aperti in output. In questo caso, infatti, si provoca la generazione di una nuova struttura e la sovrascrittura del file eventualmente già presente sul disco con il nome specificato dopo la parola chiave Open. Com'è facile intuire, l'accesso in output ha il fine di permettere la scrittura delle informazioni sui file. In alcuni casi, tuttavia, risulta necessario inserire all'interno di uno di essi dei nuovi dati senza distruggere quelli inseriti in una o più sessioni precedenti. La modalità da utilizzare per raggiungere tale scopo è denominata Append. Dopo aver dichiarato l'uso che si desidera fare del file, è necessario assegnare ad esso un numero, che ne costituisce un identificatore univoco. Tale valore deve essere un intero compreso fra 1 e 511 e va specificato dopo la parola chiave As. Per le strutture non destinate alla condivisione con altre applicazioni, è opportuno utilizzare i numeri compresi fra 1 e 255, riservando i rimanenti ai file che devono essere resi accessibili da più processi nello stesso momento. Si noti che, per compatibilità con il linguaggio BASIC classico, il numero di identificazione si può far precedere dal carattere #. L'ultimo parametro che resta da esaminare è quello che definisce la lunghezza di ogni blocco di informazioni interessato dalle operazioni di lettura o scrittura. Esso è opzionale e rappresenta la dimensione dello spazio di memoria temporanea (denominato buffer) allocato dal sistema. Tale valore non può essere superiore a 32767. Se il comando Open rende possibile accedere a un file e crea per esso un identificatore, l'effetto contrario, ovvero il rilascio della struttura e l'eliminazione del numero di riferimento, è sortito dall'istruzione Close. Si supponga di aver aperto un file e di aver assegnato ad esso l'identificatore 1. La riga

Close #1 determina la fine dell'uso della struttura da parte del programma, pur rendendone possibile la successiva riapertura. Il numero di riferimento ritorna così ad essere utilizzabile per la gestione di un altro file. Si supponga di voler realizzare un'applicazione in grado di visualizzare in una casella di testo il contenuto del file di sistema Win.ini. In primo luogo, è necessario disegnare un form contenente una textbox, che si suppone denominata txtTesto. È poi necessario fare in modo che all'avvio del programma essa sia riempita con il testo contenuto nel file da leggere. A tal fine, si può associare il seguente codice all'evento Load del form:

Private Sub Form_Load() Dim Riga As String txtTesto.Text = "" Open "c:\windows\win.ini" For Input As #1 Do Until EOF(1)

Line Input #1, Riga txtTesto.Text = txtTesto.Text & Riga & Chr(13) & Chr(10)

Loop Close #1 End Sub

Page 33: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

33

Dopo aver eliminato i caratteri eventualmente presenti nella textbox, la procedura provvede ad aprire in input il file, che si suppone contenuto nella cartella "C:\Windows" e ad associargli il numero identificatore 1. Tutte le operazioni che in seguito sono effettuate sul file sono prodotte da istruzioni riceventi tale valore come parametro.Il file da leggere è notoriamente composto da testo organizzato in righe. Lo scopo dell'applicazione illustrata in questo esempio è di leggere tutte le righe e di copiarle, una di seguito all'altra, nella textbox. A tal fine è necessario creare un ciclo in grado di svolgere le operazioni di lettura. La condizione che deve causare il termine delle iterazioni è rappresentata dal raggiungimento della fine del file. Ciò si verifica quando tutti i dati sono stati letti. Il file, tuttavia, potrebbe anche essere vuoto. È pertanto necessario fare in modo che il ciclo preveda il test all'ingresso, ovvero che la condizione sia specificata accanto alla parola chiave Do, al fine di evitare le iterazioni quando essa risulti vera già immediatamente dopo l'esecuzione del comando Open. Un file sequenziale può essere paragonato a un nastro magnetico. Per sapere se l'ipotetica testina di lettura ha raggiunto la posizione di fine, è necessario ricorrere alla funzione EOF (End Of File), alla quale, come di consueto, va passato come parametro il numero identificatore della struttura a cui si desidera far riferimento. Il valore restituito è di tipo logico e vale True se è raggiunta la fine del file; ovviamente, in caso contrario, il risultato è False. La lettura di una riga di un file di testo è effettuata per mezzo dell'istruzione Line Input . Essa prevede due parametri; il primo è costituito ancora una volta dall'identificatore del file su cui è eseguita l'operazione. Il secondo, invece, è rappresentato dalla variabile di tipo stringa destinata ad ospitare la riga di testo da leggere. Nell'esempio è stata utilizzata la variabile denominata Riga. In esso, il dato letto è aggiunto al contenuto della casella testuale per mezzo dell'operatore di concatenazione di stringhe (&). Si noti che per passare alla riga successiva della textbox si fa uso di una sequenza composta dal carattere di ritorno del carrello (Chr(13)) e da quello di avanzamento di una riga (Chr(10)). Si supponga ora di voler realizzare un programma in grado di effettuare l'esatto contrario del precedente, ovvero di trasferire su un file di testo il contenuto di una textbox. La sua implementazione risulta estremamente semplice. In pratica richiede esclusivamente l'uso di un'istruzione Print .

Private Sub btnSalva_Click () Dim Stringa As String Open "archivio.dat" For Output As #1 Stringa = txtStringa.Text Print #1, Stringa Close #1 End Sub

I file ad accesso casuale I file ad accesso casuale sono caratterizzati dall’organizzazione molto rigida in strutture dette record. Un file è quindi composto da un numero variabile di record accodati. Al fine di comprendere meglio il concetto, si pensi a uno schedario, quale ad esempio l’anagrafica dei clienti di un’azienda. L’archivio è composto da schede aventi tutte la stessa dimensione e contenenti lo stesso tipo di informazione. Ogni scheda rappresenta un record. Per poter inserire in un file più informazioni, anche di tipo non omogeneo, raggruppate in "schede", è necessario riunirle in un’unica struttura. Si deve quindi creare un nuovo tipo di dati. Tale operazione è eseguita per mezzo della struttura Type (già vista nelle nona lezione), la cui sintassi è:

Type <nome> <nome_campo_1> As <tipo_1> <nome_campo_2> As <tipo_2> … <nome_campo_n> As <tipo_n> End Type

All’interno della struttura devono essere dichiarati gli elementi che la compongono, che sono denominati campi. Per ognuno di essi deve essere specificato il tipo di dati che lo caratterizza. I campi possono essere anche di tipo totalmente diverso. Si possono infatti definire dei record contenenti contemporaneamente delle informazioni di tipo testuale, numerico e logico. Ad esempio, la seguente dichiarazione è corretta:

Type Automobile Marca As String*50 Modello As String*50 Cilindrata As Integer Diesel As Boolean

End Type

Si noti che sono stati dichiarati due campi di tipo alfanumerico, uno di tipo logico e uno numerico intero. La struttura è denominata Automobile. In questo modo si è provveduto ad aggiungere un nuovo tipo di dati a quelli standard previsti da Visual Basic. È quindi possibile dichiarare la variabile MiaVettura, di tipo Automobile digitando:

Dim MiaVettura As Automobile Le variabili definite come record prevedono, data la propria conformazione, una modalità di assegnamento dei valori leggermente diversa rispetto a quella prevista dalle strutture convenzionali. In genere, si esegue un’operazione di assegnamento per ogni campo, secondo la sintassi:

<variabile>.<campo> = <valore> Come per le strutture sequenziali, l’apertura di un file ad accesso casuale avviene per mezzo dell’istruzione Open che, in questo caso, assume la forma:

Open <percorso_file> For Random As [#]<identificatore> Len = <lunghezza_record>

dove percorso_file indica il percorso completo del file che si desidera aprire, mentre identificatore costituisce un numero utilizzato per contraddistinguere in modo univoco tale struttura e pertanto va fornito come parametro a tutti i comandi che sono destinati a gestirla. Si noti che la modalità di accesso è indicata per mezzo della parola chiave Random, che deve essere obbligatoriamente specificata, indipendentemente dal tipo di operazione che si desidera

Page 34: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

34

effettuare sul file, sia essa di lettura o scrittura. Si noti altresì che anche il parametro Len è obbligatorio. Esso deve contenere l’esatta dimensione del record che costituisce l’unità di informazione memorizzata nel file. Qualora essa non sia nota, può essere determinata per mezzo della funzione Len. Ad esempio, volendo assegnare alla variabile DimRec la dimensione del record MiaVettura, è necessario digitare:

DimRec = Len(MiaVettura) Il contenuto della variabile DimRec costituisce il valore da passare come ultimo parametro all’istruzione Open per consentire la gestione di un file composto da elementi di tipo Automobile. Analogamente ai file sequenziali, anche le strutture ad accesso casuale devono essere chiuse dopo l’uso per mezzo dell’istruzione Close. La lettura di un record contenuto in un file ad accesso casuale avviene per mezzo dell’istruzione Get, caratterizzata dalla seguente sintassi:

Get [#]<identificatore>, <posizione>, <variabile> dove <identificatore> rappresenta il numero che univocamente identifica il file oggetto dell’operazione di lettura e <variabile> è il nome della variabile in cui i dati letti devono essere posti. Il parametro <posizione> indica la posizione del record da leggere. Si tratta di un valore intero compreso fra 1 e il numero dei record presenti nel file. Ad esempio, si supponga di voler accedere al quarto record presente nel file di identificatore 1 e di voler porre il suo contenuto nella variabile Dato. Ciò è possibile per mezzo della riga:

Get #1, 4, Dato Solo in un caso il valore del parametro <posizione> può essere omesso; ciò si verifica in occasione dell’effettuazione di operazioni di lettura in sequenza; l’assenza del numero indicante la posizione provoca infatti l’accesso al record successivo a quello corrente. Non possono tuttavia essere omesse le virgole di separazione. Ad esempio, la sequenza

Get #1, 4, Dato Get #1,, Dato1

provoca la lettura del quarto e del quinto record del file identificato dal numero 1. Per scrivere il contenuto di un record in un file ad accesso casuale è possibile utilizzare l’istruzione Put, la cui sintassi è pressoché identica a quella del comando Get:

Put [#]<identificatore>, <posizione>, <variabile> In questo caso, la variabile indicata come terzo parametro contiene il dato da scrivere. Ad esempio, la riga

Put #1, 5, Dato scrive il contenuto della variabile Dato nel quinto elemento del file identificato dal numero 1. Il valore assunto dal parametro <posizione> assume un’importanza fondamentale, in quanto determina se è aggiunto un nuovo record all’archivio o se ne è sovrascritto uno già esistente. Quest’ultima evenienza si verifica quando è indicata una posizione già occupata da un elemento. Per aggiungere un nuovo record al file, invece, è necessario indicare un valore pari al numero totale dei record incrementato di un’unità.

La cancellazione logica di un record Il metodo più semplice per cancellare un record consiste nel sovrascriverlo con un elemento vuoto. In questo modo, tuttavia, non è possibile recuperare lo spazio da esso occupato sul disco. Si tratta cioè di una cancellazione logica, non fisica, in quanto Visual Basic non dispone di un’istruzione in grado di rimuovere un record e di recuperare automaticamente lo spazio da esso occupato. È possibile sfruttare a proprio vantaggio la possibilità di effettuare solo una cancellazione logica dei record contenuti in un file per fare in modo che degli elementi eventualmente eliminati per sbaglio possano essere agevolmente recuperati. Ciò è possibile aggiungendo un campo booleano alla struttura dei record e facendo in modo che il programma che accede all’archivio consideri cancellati tutti gli elementi caratterizzati dal contenere il valore logico True all’interno di questo campo. L’eliminazione di un record comporta quindi la semplice variazione del valore di un suo campo. Analogamente, è possibile recuperare un elemento cancellato per errore impostando nuovamente al valore False il campo booleano. La struttura Automobile può pertanto essere modificata come segue:

Type Automobile1 Marca As String*50 Modello As String*50 Cilindrata As Integer Diesel As Boolean Cancellato As Boolean End Type

La cancellazione fisica di un record Quando la quantità di informazioni da gestire diventa elevata, la necessità di recuperare lo spazio occupato dai record cancellati diventa evidente, sia per evitare lo spreco di spazio sul disco, sia per non ridurre drasticamente i tempi di accesso alle informazioni costringendo il programma a leggere dei dati inutili. Come già osservato in precedenza, Visual Basic non dispone di un’istruzione in grado di provvedere automaticamente alla cancellazione fisica di un record. Tuttavia, la scrittura di una simile procedura non presenta un livello di difficoltà elevato. Essa deve solo creare un nuovo file e copiare al suo interno tutti i record non vuoti. Successivamente, deve eliminare il primo file ed assegnare il suo nome alla nuova struttura. È ciò che fa la procedura di seguito descritta, che riceve come parametro il nome del file da compattare, che si suppone composto da record di tipo Automobile1:

Sub CompattaFile(ByVal NomeFile As String) Dim ID_old As Integer Dim ID_new As Integer Dim Dato As Automobile1 Dim Lunghezza As Integer Lunghezza = Len(Dato) ID_old = FreeFile Open NomeFile For Random As ID_old Len = Lunghezza ID_new = FreeFile

Page 35: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

35

Open "Temp.dat" For Random As ID_new Len = Lunghezza Do While Not EOF(ID_old)

Get ID_old, , Dato If Not Dato.Cancellato Then

Put ID_new, , Dato End If

Loop Close ID_old, ID_new Kill NomeFile Name "Temp.dat" As NomeFile End Sub

Si noti l’uso della funzione FreeFile, che restituisce un numero adatto ad essere utilizzato come identificatore di file ed evita così il rischio di utilizzare degli identificatori già in uso in altre parti del programma. La procedura provvede a leggere in modo sequenziale il file di cui è specificato il nome come parametro e a copiare in un file denominato Temp.dat tutti i record per i quali il campo Cancellato assume il valore False. Si noti che le operazioni di lettura e scrittura sono eseguite sequenzialmente, in quanto è stato omesso il valore indicante la posizione nelle istruzioni Get e Put. Il ciclo di copiatura termina quando sono esauriti i record da leggere. Quando ciò avviene, la funzione EOF (End Of File), già descritt, restituisce il valore True. Dopo aver copiato tutti i record non cancellati logicamente, la procedura provvede a chiudere entrambi i file. Si noti che a tal fine utilizza un’unica istruzione Close, in cui gli identificatori dei file da chiudere sono separati da una virgola. Il passo successivo consiste nel sostituire il file originale con quello creato. Ciò comporta l’esecuzione di due operazioni: la cancellazione del file di origine e la ridenominazione di quello generato dalla procedura. L’eliminazione avviene per mezzo dell’istruzione Kill , la cui sintassi è

Kill <Nome_file> Il file Temp.dat è quindi rinominato per mezzo dell’istruzione Name, che è caratterizzata dalla seguente sintassi:

Name <Vecchio_nome> As <Nuovo_nome> I file rivestono un’importanza fondamentale nella maggior parte delle applicazioni, in quanto consentono di trattare una quantità di dati superiore a quella che può essere contenuta nella memoria dell’elaboratore. Inoltre, trattandosi di strutture permanenti, permettono di mantenere tali informazioni anche dopo lo spegnimento o il riavvio del sistema. L’utilizzo di strutture ad accesso casuale rende ancora più evidenti i vantaggi offerti dai file, permettendo una maggiore flessibilità d’uso. Come già si era visto, per verificare se un file esiste già si può usare la funzione Dir (nomepercorso), nome percorso indica una stringa che specifica il nome del file da verificare. La funzione restituisce una stringa di lunghezza se il file non viene trovato. La funzione Lof (numeroFile) restituisce le dimensioni in Byte di un file aperto.

Page 36: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

36

Diciassettesima lezione – Gli oggetti Un oggetto è un insieme di codice e dati che è possibile utilizzare indipendentemente da altri oggetti poiché rappresenta un insieme a sé stante. Esempi tipici ed evidenti di oggetti sono i controlli che abitualmente inseriamo su un form: pulsanti, caselle di testo, checkbox e così via. Ma anche lo stesso form è un oggetto, così come il font di un testo, un database, un documento word o un grafico di excel. Fondamentalmente, un oggetto in Visual Basic è rappresento da una classe che ne definisce le caratteristiche: in particolare, la classe di un oggetto definisce le sue proprietà, i suoi metodi e i suoi eventi. Per rendersi conto in modo semplice ed efficace di cosa ciò significhi, basta dare un'occhiata al "visualizzatore oggetti" (o "object browser"), che si apre premendo F2 dall'IDE o tramite il menù "visualizza"; se date un'occhiata alle voci con l'icona del modulo di classe vi accorgerete che essa è associata non solo ai normali controlli visibili sulla casella degli strumenti, ma anche all'oggetto ErrObject, all'oggetto StdFont, all'oggetto App ecc. Tutti questi oggetti hanno un'interfaccia (un insieme di metodi, eventi, proprietà) definiti nelle rispettive classi, che quindi ne rappresentano il "modello" valido per tutte le istanze dell'oggetto. Infatti, quando un programmatore manipola un oggetto tramite la sua interfaccia, in realtà non ha a che fare direttamente con la classe dell'oggetto, ma con una sua istanza, ovvero con una copia direttamente utilizzabile. Se mi è consentito un paragone filosofico, il rapporto che c'è tra una classe e le sue istanze è in qualche modo analogo a quello che intercorre tra le "idee" platoniche e le sue manifestazioni concrete sul nostro mondo. Ogni istanza di una classe è indipendente dalle altre, così che in uno stesso form è possibile inserire ad es. 4 textbox senza che debba esserci alcuna reciproca connessione tra di essi: ognuna di queste istanze è gestibile in modo del tutto indipendente dalle altre, ma la loro interfaccia è comune perché è definita per tutte dalla medesima classe TextBox. L'indipendenza reciproca delle istanze, naturalmente, non impedisce che esse possano interagire tra di loro e con altri tipi di oggetti. La classe, oltre a contenere il codice per la gestione dell'interfaccia, contiene anche dati da esporre, di norma, tramite le proprietà; tali dati si dice che sono "incapsulati" nell'oggetto, e ovviamente sono replicati per ognuna delle sue istanze. Per creare un oggetto, quindi, è sufficiente inserire in un progetto un modulo di classe, definirne le proprietà, i metodi e gli eventi e scrivere il codice e i dati necessari per consentirne la corretta funzionalità: vediamo come fare queste dichiarazioni con una semplice classe di esempio. Creiamo una classe di nome "clsUomo" che rappresenta un essere umano: tra le proprietà attribuibili ad esso ci può essere ad es. il nome, il peso, l'altezza, il sesso ecc. Per fare in modo che l'interfaccia della classe Uomo esponga la proprietà "Nome" occorre dichiarare questa proprietà nel modo seguente:

Public Property Get Nome() as String Nome = sName End Property Public Property Let Nome(sNewName as String) sName = sNewName End Property

Occorre innanzitutto notare che le dichiarazioni sono due: una per leggere il valore della proprietà (Property Get), e una per modificare tale valore (Property Let); la Property Get funziona sostanzialmente come una funzione, che restituisce il contenuto di una variabile, in questo caso sName; solitamente essa è dichiarata come variabile privata del modulo di classe:

Private sName as String

Quando invece il programmatore accede alla proprietà Nome per modificarne il valore, viene richiamata la procedura Property Let, a cui viene passato come argomento il nuovo nome da assegnare alla proprietà, e tale valore è assegnato via codice alla variabile di modulo sName, in modo che una successiva chiamata della Property Get restituisca il nome appena modificato. Esiste anche un altro tipo di routine per modificare una proprietà: si tratta della Property Set, che va utilizzata qualora la proprietà faccia riferimento a un oggetto; questo accade perché Visual Basic richiede di utilizzare l'istruzione Set per assegnare un riferimento a un oggetto, mentre per i tipi di dati fondamentali non è richiesta alcuna istruzione particolare (l'istruzione Let era necessaria nelle vecchie versioni del basic ed è sta mantenuta per compatibilità). Per quale motivo è opportuno utilizzare una coppia di routine Property anziché dichiarare a livello di modulo una variabile pubblica Nome? Anche questo secondo metodo consentirebbe di leggere e scrivere a proprio piacimento il valore della variabile; ma il problema è proprio questo: usando una variabile pubblica non ci sarebbe alcun controllo sulla correttezza dell'uso della "proprietà" Nome. Uno potrebbe assegnare a questa variabile qualunque valore, anche palesemente inadatto a descrivere il nome di un essere umano; invece implementando una coppia di routine Property è possibile scrivere del codice atto ad evitare che a tale proprietà siano assegnati valori non adeguati, ad es. nomi del tipo "123&g#", oppure nomi troppo lunghi o troppo corti. Inoltre, con una variabile pubblica non sarebbe possibile implementare una proprietà di sola lettura; cosa che risulta invece molto semplice con le routine property: basta infatti cancellare la routine Property Let (o Property Set)! Ad es. la proprietà "Sesso" potrebbe essere una tipica proprietà di sola lettura (a meno di esigenze particolari):

Public Property Get Sesso() as Boolean Sesso = True End Property

(in questo caso bisogna solo decidere se il valore True corrisponde a maschio o femmina: eventualmente è possibile utilizzare un tipo di dati diverso dal booleano). Come le proprietà descrivono le caratteristiche di un oggetto, i metodi rappresentano le azioni che l'oggetto può compiere: un essere umano, ad es., può correre, mangiare, dormire, pensare ecc. Ciascuna di queste azioni può essere eseguita tramite un apposito metodo; ad es. possiamo implementare un metodo "Scrivi" che consenta di scrivere qualcosa su un certo form: tale metodo non sarà altro che una procedura Sub pubblica, la quale accetterà come

Page 37: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

37

parametri in ingresso la frase da scrivere e il form su cui scrivere (eventualmente si potrebbero aggiungere parametri aggiuntivi come le coordinate o il font della frase da scrivere; la proprietà AutoRedraw del form deve essere impostata a True):

Public Sub Scrivi (frmScrivi as Form, sFrase as Str ing) frmScrivi.Print sFrase End Sub

Se si desidera che il metodo restituisca un valore (ad es. per controllare la corretta esecuzione del metodo), si può usare una funzione al posto di una subroutine. Infine, gli eventi sono quegli elementi dell'interfaccia che non sono richiamati da chi utilizza l'oggetto ma sono generati direttamente dall'oggetto; quando si verifica qualcosa che si ritiene opportuno segnalare al client (ovvero al componente che utilizza l'oggetto), è l'oggetto stesso che genera l'evento corrispondente. Per un essere umano, i tipici eventi potrebbero essere "Nascita", "Morte", "Matrimonio", ecc. Per poter generare un evento, in una classe deve essere innanzitutto presente la sua dichiarazione:

Public Event Nascita(dtData as Date, bSesso as Boolean)

La generazione vera e propria dell'evento avviene però con l'istruzione RaiseEvent; supponiamo ad es. che l'interfaccia della classe clsUomo esponga il metodo "GeneraFiglio": in tale metodo sarà generato l'evento Nascita:

Public Sub GeneraFiglio(sNome as String) Dim fSesso as Single Dim bSesso as Boolean fSesso=Rnd bSesso=False

If fSesso>0.5 then bSesso=True End If RaiseEvent Nascita(Date, bSesso) End Sub

Il sesso del nascituro viene determinato casualmente con la funzione Rnd, dopodiché viene ufficializzata la nascita del figlio in data odierna: quando ciò accade, nel client l'esecuzione passerà alla routine Sub Nascita che avrà per argomenti la data di nascita e il sesso del neonato. Ad es. in questa routine si potrebbe creare una nuova istanza della classe Uomo con le caratteristiche del neonato. Per inserire una proprietà, un metodo o un evento in una classe si può anche ricorrere alla funzione "Inserisci routine" del menù "Strumenti"; tutto quello che occorre fare è selezionare il tipo di routine da inserire: "Property" per le proprietà, "Event" per gli eventi, "Sub" o "Function" per i metodi. Finora abbiamo visto la costruzione dell'interfaccia tramite una classe: ora vediamo come utilizzare questa classe dal lato client. Prima di tutto bisogna dichiarare una o più variabili di tipo clsUomo:

Dim uPrimoUomo as clsUomo Dim uSecondoUomo as clsUomo

La "u" di prefisso sta a indicare che la variabile è di tipo "Uomo": si tratta di una convenzione ad hoc per distinguere queste variabili dalle altre. Poi bisogna impostare un riferimento alla classe Uomo; infatti, come dicevo prima, l'utilizzatore dell'oggetto Uomo non lavora direttamente sulla classe che lo definisce ma sulle sue singole istanze: istanze che sono rappresentate dalle variabili di tipo Uomo e che diventano concretamente utilizzabili solo quando contengono un riferimento alla classe. Per fare ciò si utilizza l'istruzione Set:

Set uPrimoUomo = New clsUomo Set uSecondoUomo = New clsUomo

La parola chiave New serve a specificare che abbiamo bisogno di una nuova istanza della classe clsUomo; senza questa parola chiave l'istruzione Set non funzionerebbe, perché clsUomo non è direttamente referenziabile da una variabile. È invece possibile specificare New nella stessa dichiarazione delle variabili:

Dim uPrimoUomo as New clsUomo Dim uSecondoUomo as New clsUomo

Così facendo sarà lo stesso Visual Basic a impostare il riferimento a una nuova istanza della classe per ogni variabile in occasione del suo primo utilizzo nel codice; quando Visual Basic per la prima volta incontrerà una istruzione che invoca una proprietà o un metodo dell'oggetto, ad es.:

uSecondoUomo.Nome = "Piergiovanni"

provvederà a creare una nuova istanza della classe Uomo, ad assegnare alla variabile uSecondoUomo un riferimento a tale istanza, e a modificare il valore della proprietà Nome di questa istanza. La successiva istruzione che coinvolge la variabile uSecondoUomo farà riferimento all'istanza già creata e assegnata alla variabile, finché non sarà implicitamente o esplicitamente distrutta. In questo modo, però, non si ha un pieno controllo sul momento in cui l'istanza della classe viene creata, proprio perché questo compito è lascio a Visual Basic; invece spesso è importante che sia il programmatore a decidere quando l'istanza deve essere creata utilizzando l'apposita istruzione Set, onde evitare ambiguità nel codice. Allo stesso modo, è importante che il programmatore provveda a distruggere esplicitamente il riferimento all'istanza della classe quando questa istanza non è più necessaria; a questo scopo si usa ancora l'istruzione Set:

Set uPrimoUomo = Nothing

La parola chiave Nothing specifica a Visual Basic che l'istanza della classe a cui faceva riferimento la variabile uPrimoUomo deve essere distrutta: in questo modo la quantità di memoria occupata da quell'istanza (ricordo che ogni istanza rappresenta una copia della classe) può essere liberata; la distruzione del riferimento all'istanza è quindi una buona abitudine utile soprattutto nel caso in cui si abbia a che fare con classi complesse e scarse quantità di risorse sul proprio pc. La parola chiave Nothing può essere utilizzata anche per testare se una variabile contiene già un riferimento ad un'istanza della classe oppure no:

If uPrimoUomo is Nothing Then

Page 38: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

38

Set uPrimoUomo = New clsUomo End If

In questo caso si usa l'operatore "Is" e non "=" perché la condizione di uguaglianza non avrebbe significato in questo contesto, dato che Nothing non è una costante con un valore particolare che è possibile confrontare direttamente col contenuto di una variabile. Invece l'operatore Is con la parola chiave Nothing verifica se la variabile uPrimoUomo fa riferimento a un oggetto valido ed esistente oppure no. Una volta creata una nuova istanza della classe ed assegnato un suo riferimento alla variabile considerata, è possibile utilizzare le proprietà e i metodi esposti dall'interfaccia dell'oggetto. Per poter usufruire anche degli eventi dell'oggetto, occorre che la variabile che contiene il riferimento all'istanza sia stata dichiarata con la parola chiave WithEvents:

Dim WithEvents uPrimoUomo as clsUomo

Se la classe Uomo espone degli eventi, questi saranno visibili nella finestra del codice selezionando "uPrimoUomo" dalla casella degli oggetti in alto a sinistra, e uno degli eventi esposti dalla casella delle procedure in alto a destra. In questa routine il programmatore può gestire l'evento, esattamente come si farebbe con l'evento Load del Form, o con l'evento Click di un pulsante. I metodi dell'oggetto vengono richiamati esattamente come si farebbe con altre funzioni o routine, utilizzando la sintassi:

nomeoggetto.metodo parametri

dove "nomeoggetto" indica il nome della variabile che contiene il riferimento a un'istanza dell'oggetto, ad es.: uPrimoUomo.Scrivi Me, "Ciao"

Identica sintassi vale per le proprietà, come si è visto negli esempi precedenti; l'unica particolarità è che quando si assegna un nuovo valore alla proprietà, questo viene passato come parametro alla routine Property Let (o Set), anche se ciò non è immediatatamente visibile al programmatore che utilizza l'oggetto. Ovviamente, come per tutte le procedure, è possibile prevedere specifici argomenti: ad es., per la proprietà Nome potrebbe essere utile specificare se si vuole assegnare il primo o il secondo nome, oppure se si vuole assegnare solo il nome di battesimo o anche il cognome, ecc. In tal caso la routine Property Let avrà sempre un argomento in più rispetto alla corrispondente Property Get: questo argomento in più è proprio il nuovo valore da assegnare alla proprietà. Ad es.:

Public Property Get Nome (bNomeCompleto as Boolean) as String If bNomeCompleto Then Nome = sNome & " " & sCognome Else Nome = sNome End If End Property Public Property Let Nome (bNomeCompleto as Boolean, sNewName as String) Dim nSpace as Integer If bNomeCompleto Then nSpace = InStr(1, sNewName, " ") sNome = Left$(sNewName, nSpace - 1) sCognome = mid$(sNewName, nSpace+1) Else sNome = sNewName End If End Property

La lettura e scrittura di questa proprietà può avvenire ad es. nel modo seguente: uPrimoUomo.Nome(True) = "Paperino Paolino" sNome = uPrimoUomo.Nome(False) 'sNome="Paperino"

Nella prima istruzione la stringa "Paperino Paolino" diventerà il valore del parametro sNewName della routine Property Let. È importante che i tipi di dati coinvolti siano congruenti: ovvero, se la proprietà è di tipo stringa (Property Get … as String), l'ultimo parametro della routine Property Let deve essere anch'esso di tipo stringa (Property Let … (sNewName as String)), altrimenti si ottiene un "Type Mismatch". L'IDE di Visual Basic consente inoltre di specificare quale, tra le proprietà o gli eventi di una classe, deve essere la proprietà o l'evento predefinito: per fare ciò occorre (previa attivazione della finestra del codice del modulo di classe) selezionare la voce "attributi routine" dal menù "Strumenti"; nella finestra di dialogo è possibile scegliere una delle proprietà, metodi o eventi disponibili nell'interfaccia della classe e, tramite le "opzioni" della finestra di dialogo, attivare o disattivare la casella di controllo "predefinita nell'interfaccia utente". Quando una proprietà è predefinita, è possibile evitare di scriverne il nome nel codice, ad es. l'istruzione:

lErrNumber = Err.Number

è equivalente a: lErrNumber = Err

perché la proprietà Number è quella predefinita per l'oggetto Err. Ciò può risultare a volte comodo per il programmatore, ma in generale io sconsiglierei la seconda sintassi, perché non rende immediatamente chiaro che si sta utilizzando una proprietà, né quale proprietà si sta utilizzando; non tutti infatti possono sapere che la proprietà predefinita dell'oggetto Err è Number. La prima sintassi invece è esplicita e più facilmente leggibile; inoltre è anche più veloce perché evita a Visual Basic di capire da solo quale proprietà deve richiamare. Un evento predefinito, ovviamente, non è un evento che si verifica "per default" quando ricorre chissà quale condizione: l'evento predefinito di un oggetto è semplicemente quello che appare nella finestra del codice quando si seleziona

Page 39: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

39

l'oggetto dalla casella in alto a sinistra, o quando si fa doppio click su un controllo. Ad es., l'evento Click è quello predefinito per il pulsante di comando, l'evento Load è quello predefinito per il form, l'evento Change è quello predefinito per la casella di testo. La casella di controllo "predefinita nell'interfaccia utente" non è attiva per i metodi, per ovvi motivi. La stessa finestra di dialogo permette di dare una descrizione ad ogni elemento dell'interfaccia: tale descrizione sarà mostrata nel visualizzatore oggetti e, per le proprietà, anche nella parte inferiore della finestra delle proprietà; inoltre è possibile nascondere il membro al visualizzatore oggetti, scegliere se mostrare o nascondere una proprietà nella finestra delle proprietà e in quale Categoria, e altre opzioni. La medesima finestra di dialogo è visualizzabile anche tramite il visualizzatore oggetti, selezionando un membro dell'interfaccia e scegliendo "proprietà" dal menù che compare premendo il tasto destro del mouse.

Page 40: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

40

Diciottesima lezione – Studiare un'applicazione professionale : il Blocco Note Uno dei modi migliori per imparare un linguaggio di programmazione è provare a replicare un'applicazione "professionale", che conosciamo già e che sappiamo già utilizzare; per cominciare, naturalmente, è bene partire da un'applicazione semplice, ad esempio il Blocco Note di Windows. Innanzitutto bisogna capire da quali controlli è costituita l'applicazione: nel caso

del blocco note è facile vedere che esso comprende un menù e un'area bianca in cui scrivere il testo; quest'area bianca non è altro che un TextBox. Cominciamo allora con l'aprire un nuovo progetto, inseriamo un TextBox sul form e chiamiamolo txtFile, mentre il form lo chiamiamo frmNotePad e come Caption gli diamo "Blocco Note - VBItalia"; trasciniamo txtFile in modo che l'angolo superiore sinistro coincida con l'angolo superiore sinistro di frmNotePad e poi ridimensioniamolo in modo che occupi tutta l'area disponibile in frmNotePad. Lo stesso risulto si può ottenere selezionando txtFile e impostando a 0 le proprietà Top e

Left nella finestra delle proprietà; le proprietà Height e Width vanno invece imposte con lo stesso valore delle proprietà ScaleHeight e ScaleWidth di frmNotePad. Già che ci siamo, impostiamo la proprietà Multiline di txtFile su True, in modo che sia possibile visualizzare il testo su più righe e la proprietà ScrollBars su 2 in modo da visualizzare una barra di scorrimento verticale sulla destra di txtFile. Ora inseriamo il menù, cominciando dal menù File, il più importante: per farlo dobbiamo visualizzare il nostro form e visualizzare l'Editor di Menù dal menù Strumenti, oppure premere l'apposito pulsante sulla barra degli strumenti. L'Editor di Menù permette di impostare le principali proprietà delle voci del nostro menù: prima di tutto bisogna scegliere la Caption, ossia la stringa che appare sul menù, nel nostro caso "File"; poi bisogna impostare il nome del menù, ad es. "mnuFile": il prefisso "mnu" indica, secondo le convenzioni di sintassi, che si tratta appunto di una voce di menù; le altre opzioni per ora potete lasciarle così come sono. Ora che abbiamo il nostro menù File, bisogna inserire le apposite voci: per semplificarci il compito inseriremo solo le voci "Apri", "Salva", "Esci"; clicchiamo quindi sul pulsante "Successivo", che crea un'altra voce di menù, scriviamo la caption "Apri…", scriviamo il nome "mnuApri" e infine premiamo il pulsantino con la freccia verso destra: nella lista dei menù che compare in basso vedremo che la voce "Apri…" è preceduta da tre puntini, i quali indicano che Apri è un sottomenù di File; clicchiamo ancora su "Successivo", scriviamo la caption e il nome per la voce "Salva": VB intuisce che si trstatta ancora di un sottomenù di File, per cui non c'è più bisogno di premere il pulsante con la freccia verso destra; ripetiamo il procedimento per la voce Esci. Ora che abbiamo disegnato il nostro menù File, possiamo premere OK: sul frmNotePad vedremo quindi il nostro menù, e cliccandoci sopra vedremo le sue voci; cliccando infine su una delle voci si aprirà la finestra del codice in corrispondenza della routine click di quella voce di menù. Ora dobbiamo inserire il codice per l'apertura e il salvaggio dei file e per la chiusura dell'applicazione: occupiamoci prima dei file. Per sapere quale file aprire o con quale nome salvare il testo che l'utente ha inserito nel textbox txtFile si potrebbe utilizzare la finestra di dialogo standard di Windows, proprio quella che usa lo stesso Blocco Note o qualunque altra applicazione di Windows, ma per ora ci accontentiamo di un semplice inputbox, ovvero una finestrella che chiede l'inserimento di una stringa: nel nostro caso questa stringa sarà il nome del file. Prima di tutto, però, dobbiamo dichiarare le variabili che ci serviranno: queste saranno il nome del file da aprire o salvare e il contenuto di questo file; cominciamo dunque a inserire, nella routine mnuApri_Click, le istruzioni:

Dim strNomeFile As String Dim strTesto As String StrNomeFile = Inputbox("Inserisci il nome del file: ")

La funzione Inputbox è quella che fa comparire l'omonima finestra: Come parametri richiede obbligatoriamente il prompt, ovvero il messaggio visualizzato nella finestra, e facoltivamente il "titolo" della finestra, cioè la stringa che compare nella barra del titolo; gli altri parametri, tutti facoltativi, per ora non ci interessano. Il valore restituito dalla funzione è proprio ciò che l'utente inserisce nella casella di testo contenuta nella finestra, e noi assegniamo questo valore a una nostra variabile locale. Una volta saputo il nome del file, dobbiamo aprirlo e leggerne il contenuto: per fare questo dobbiamo utilizzare l'istruzione open e quelle ad essa collegate. Abbiamo già studiato l’istruzione Open nela lezione sui Files. Noi conosciamo il nome del file, sappiamo che vogliamo aprirlo per leggerlo (quindi la modalità sarà input) e dato che è il primo file che apriamo possiamo usare 1 come numero di file:

Open strNomeFile For Input As #1

dopodiché dobbiamo leggerne il contenuto: esiste una funzione apposita, Input , che vuole sapere quanti byte deve leggere e da quale file; il numero di byte da leggere è esattamente uguale alla lunghezza del file, che possiamo

Page 41: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

41

recuperare traverso la funzione LOF (Length Of File): strTesto = Input(LOF(1),1)

Il testo letto da Input() viene così memorizzato in strTesto. Ora che abbiamo letto il contenuto del file, possiamo anche chiuderlo:

Close 1

Ricordate di chiudere sempre i file aperti che non vi servono più, perché finché restano aperti non saranno accessibili da altre applicazioni. Ora non ci resta che visualizzare ciò che abbiamo letto:

txtFile.Text = strTesto

Se volete, potete già provare ad avviare il progetto e ad aprire qualche file: per chiuderlo non possiamo ancora usare il menù File->Esci perché non abbiamo inserito le istruzioni necessarie, però è sufficiente cliccare sulla "x" nel form. Dopo aver inserito il codice per il menù mnuApri, scriviamo quello per mnuSalva: questa volta ci serve una sola variabile, e cioè strNomeFile, perché il testo che dobbiamo scrivere sul file è quello contenuto in txtFile, a cui possiamo accedere traverso la proprietà Text; quindi non abbiamo bisogno di una variabile per il testo. Per sapere con quale nome salvare il file, usiamo ancora la funzione InputBox:

Dim strNomeFile As String strNomeFile = InputBox("inserisci il nome del file: ")

Ora dobbiamo nuovamente aprire il file (questa volta per scriverci sopra, quindi in modalità output) e scrivere il contenuto del TextBox:

Open strNomeFile For Output As #1 Print #1, txtFile.Text Close 1

Per scrivere sul file abbiamo uso l'istruzione Print , che ha bisogno di conoscere il numero del file su cui scrivere e i valori da scrivere. Infine dobbiamo scrivere il codice per il menù Esci: qui basterebbe scrivere "Unload frmNotePad" o "Unload me" come avevamo fatto per il progetto "hello world!", ma dobbiamo assicurarci che non ci siano ancora attività in corso; in particolare, nel nostro caso dobbiamo assicurarci che non ci siano file aperti al momento di chiudere l'applicazione. E' vero che ogni file viene chiuso dopo aver letto/scritto su di esso, ma questo è quello che avviene in circostanze normali: è possibile che in certi casi si verifichi un qualche errore che impedisca la chiusura del file nelle routine mnuApri e mnuSalva; il programmatore deve essere abbastanza previdente da includere ulteriori controlli al momento di uscire dall'applicazione. E' vero anche che quando un'applicazione termina, Visual Basic si preoccupa di chiudere tutti i file rimasti aperti, ma un controllo in più non fa mai male: è un po' come spegnere le luci e chiudere il gas quando si esce di casa. Pertanto possiamo scrivere:

Close Unload Me

L'istruzione Close serve a chiudere il file specifico dal numero passo come argomento all'istruzione (ad es., close 1 chiude il file numero 1); se si usa senza argomenti, close chiude tutti i file, aperti con l'istruzione Open, che non sono ancora stati chiusi; dopo aver chiuso tutti i file eventualmente ancora aperti possiamo uscire dall'applicazione con l'istruzione Unload. Il nostro editor personale è così del tutto funzionante, tuttavia è ancora ampiamente migliorabile: ad esempio, potremmo inserire la voce di menù "Nuovo" per creare un nuovo file; questo non significa altro che ripulire il txtFile in modo che l'utente possa scrivere il testo del nuovo file: basterebbe quindi fare:

txtFile.Text = ""

In realtà questo non è sufficiente, perché bisogna controllare se sono state effettuate modifiche al testo dall'ultimo salvaggio: in questo caso, infatti, il programma dovrebbe chiedere gentilmente all'utente se vuole salvare le modifiche. Per realizzare questo controllo abbiamo bisogno di una variabile che ci dica se il testo è cambiato dall'ultimo salvataggio oppure no: dato che le possibilità sono solo due (il testo è cambiato/il testo non è cambiato) è opportuno utilizzare una variabile booleana che valga false se il testo non è cambiato e true se il testo è cambiato; per capire quando il testo cambia si può semplicemente sfruttare l'evento change del txtFile, che viene appunto generato quando il valore della proprietà txtFile.Text cambia. Questa variabile però non può essere locale rispetto alla routine txtFile_Change, perché deve essere visibile anche nel menù Nuovo, quindi bisogna dichiararla a livello di modulo; allora scriviamo, nella sezione dichiarazioni del frmNotePad:

Dim blnTextChanged As Boolean

e nella routine txtFile_Change: blnTextChanged = True

Non basta: non dobbiamo soltanto impostare a true blnTextChanged quando il testo cambia, ma dobbiamo anche impostare la variabile a False quando i cambiamenti vengono salvati su un file; perciò, nella routine mnuSalva_Click scriviamo alla fine:

blnTextChanged = False

Ora torniamo al menù Nuovo: innanzitutto bisogna inserirlo nel menù File, quindi apriamo il menù editor, selezioniamo dalla lista la voce "Apri", premiamo il pulsante "Inserisci" e infine scriviamo la caption "Nuovo" e il nome "mnuNuovo"; ora dall'editor del codice selezioniamo la routine mnuNuovo_Click: qui dobbiamo inserire il controllo per verificare se il testo è cambiato o no. Trattandosi di un controllo, dobbiamo usare l'istruzione If...Then, secondo questo schema:

If blnTextChanged Then ' il testo è cambio, quindi chiediamo ' all'utente se vuole salvare le modifiche Else ' il testo non è cambio, quindi ' basta svuotare il txtFile End If

Page 42: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

42

Per chiedere all'utente se vuole salvare le modifiche, in teoria potremmo utilizzare ancora la funzione inputbox: ma in questo caso è molto più conveniente usare un MessageBox, ovvero una di quelle normalissime finestre di Windows che visualizzano un messaggio chiedendoci cosa vogliamo fare: esattamente la stessa finestra che ci mostra proprio il Blocco Note quando non abbiamo salvato le modifiche a un file. Per far apparire questa finestra dobbiamo usare l'istruzione MsgBox, la cui sintassi è questa:

msgbox prompt, buttons, title, helpfile, context Tralasciando gli ultimi due argomenti, il prompt è il messaggio vero e proprio visualizzato nella finestra; title è invece il titolo della finestra di messaggio; il parametro buttons è un numero che indica lo "stile" del Messagebox, ovvero indica quali pulsanti devono essere associati alla finestra: ad ogni pulsante o combinazione di pulsanti è associata una costante di Visual Basic, così che per visualizzare, ad es., i pulsanti "sì" e "no", basta scrivere vbYesNo al posto del parametro buttons, anche se è possibile scrivere direttamente il valore della costante vbYesNo, e cioè 4. Analoghe costanti sono associate all'icona che è possibile visualizzare nel messaggio: per visualizzare i pulsanti e un'icona è perciò sufficiente fare la somma dei relativi valori. Per i nostri scopi potremmo utilizzare un'istruzione del genere:

MsgBox "Il testo è stato modificato. Vuoi salvare l e modifiche?", _ vbYesNo+vbQuestion, "Conferma salvataggio"

ma questa istruzione non fa altro che visualizzare il messaggio: noi invece vogliamo anche sapere qual è la risposta dell'utente, cioè vogliamo sapere qual è il valore restituito dalla funzione MsgBox; pertanto dobbiamo usare msgbox con le parentesi, come se fosse una funzione e non una semplice istruzione, in modo che restituisca un valore. Tale valore è una costante che rappresenta il pulsante premuto dall'utente: ad es., la costante vbOK vale 1 e indica che l'utente ha premuto il pulsante ok; pertanto noi dovremmo fare un controllo di questo tipo:

Dim intRisposta As Integer intRisposta = MsgBox("Il testo è stato modificato." & _ " Vuoi salvare le modifiche?", _ vbYesNo+vbQuestion, "Conferma salvataggio") If intRisposta = vbYes Then 'salviamo le modifiche Else 'non salviamo le modifiche End If

Per salvare le modifiche dovremmo scrivere istruzioni analoghe a quelle utilizze nella routine mnuSalva_Click: ma chi ce lo fa fare di ripetere le medesime istruzioni, quando abbiamo già una routine bella e pronta? Basterà semplicemente richiamarla. In definitiva, la routine mnuNuovo_click sarà così:

Dim intRisposta As Integer If blnTextChanged Then

intRisposta = MsgBox("Il testo è stato modificato." & _ "Vuoi salvare le modifiche?", _ vbYesNo+vbQuestion, "Conferma salvataggio") If intRisposta = vbYes Then

'richiamo la routine che permette di salvare le mod ifiche mnuSalva_Click

Else txtFile.Text = ""

End If Else

txtFile.Text = "" End If

Per quanto riguarda l'uscita dal programma, questo controllo viene effettuato solo se l'utente sceglie il menù File->Esci, ma non se preme il pulsante "X" in alto a destra nel form. In questo secondo caso, infatti, non viene certo richiamata la routine mnuEsci_click, ma viene generato direttamente l'evento Unload del frmNotePad: pertanto saremo noi a richiamare la routine mnuEsci_click dall'evento Unload:

mnuesci_Click

A questo punto, se si cerca di aprire un file senza avere salvato le modifiche al file correntemente aperto, succederà questo: compare un messaggio con la richiesta di confermare il salvataggio delle modifiche; se si risponde sì, comparirà una finestra per chiedere il nome del file da salvare, dopodiché comparirà un'altra finestra per chiedere il nome del file da aprire. Poiché queste due ultime finestre sono identiche, sarà opportuno differenziarle leggermente per evitare confusioni; nella routine mnuSalva_click basterà a questo scopo specificare il titolo della finestra in questo modo:

strNomeFile = InputBox("Inserisci il nome del file: ", "Salva")

e: strNomeFile = InputBox("Inserisci il nome del file: ", "Apri")

nella routine mnuApri_click che permette di visualizzare la seguente finestra:

Page 43: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

43

C'è un altro problema: quando si apre un file, il suo contenuto viene caricato in txtFile, e di conseguenza viene generato l'evento Change che imposta blnTextChanged a True; il programma perciò penserà che il testo sia stato modificato dall'utente, anche se in realtà è stato semplicemente aperto. Per correggere questo "bug" (i "bug sono gli errori commessi dai programmatori nello sviluppo di un'applicazione), basterà aggiornare blnTextChanged in mnuApri_Click aggiungendo in fondo, DOPO l'istruzione txtFile.Text = strTesto:

blnTextChanged = False

Un altro bug da correggere è quello che si verifica quando il file che abbiamo inserito nell'inputbox non viene trovato: ciò può accadere sia perché abbiamo sbagliato a scrivere il nome del file, sia perché non abbiamo inserito il percorso completo del file; infatti, se manca il percorso, Visual Basic cercherà il file nella directory corrente, che solitamente è quella in cui risiede l'IDE. Per accertarvi di quale sia la directory corrente, potete scrivere, nella finestra immediata:

? curdir

e premere "invio"; "?" è un carattere che nella finestra immediata ha lo stesso significato di Print, curdir è la funzione che restituisce, appunto, la directory corrente. Per ovviare a questo inconveniete useremo, al posto del banale InputBox, le finestre di dialogo standard utilizzate da Windows per scegliere i file da aprire o salvare: queste finestre si chiamano CommonDialog e sono contenute nel file comdlg32.ocx. Il controllo CommonDialog di norma non è presente nella casella degli strumenti, perciò dobbiamo aggiungerla noi: cliccando col tasto destro del mouse sulla casella degli strumenti, apparirà un menù popup; scegliendo la voce Componenti apparirà una finestra con una lista di componenti che è possibile aggiungere a quelli standard già presenti nella casella degli strumenti. Scrollate la lista fino a trovare la voce "Microsoft Common Dialog Control 6.0" (l'ultimo numero potrebbe differire a seconda della versione di Visual Basic installa) e selezionela, poi

premete OK. Nella casella degli strumenti ci sarà un oggetto in più, il controllo Commondialog: selezionatelo e inseritelo sul frmNotePad (non importa in quale punto, tanto non sarà visibile durante l'esecuzione del programma). Questo controllo dispone di diverse interessanti proprietà, che approfondiremo a suo tempo: le cose essenziali da sapere sono che per visualizzare la finestra bisogna utilizzare uno dei metodi Show (nel nostro caso serviranno ShowOpen e ShowSave), e che il nome del file scelto dall'utente è contenuto nella proprietà FileName, insieme al percorso completo; invece il semplice nome del file, senza il percorso, è contenuto nella proprietà FileTitle. Ora, al posto dell'InputBox, possiamo usare: CommonDialog1.ShowOpen

in mnuApri_click, e: CommonDialog1.ShowSave

in mnuSalva_click. Non abbiamo più bisogno della variabile strNomeFile, perché per aprire il file basterà fare:

Open CommonDialog1.FileName For ...

Dato che solitamente col blocco note si aprono i file di testo, impostiamo i tipi di file che è possibile scegliere dalla finestra di dialogo nella casella di riepilogo posta in basso: per fare questo bisogna impostare correttamente la proprietà Filter, secondo questo schema:

descrizione1|filtro1|descrizione2|filtro2

La descrizione è la voce che compare nella casella di riepilogo, mentre il filtro è una stringa che indica quali file visualizzare; il carattere che separa la descrizione dal rispettivo filtro è la pipe (simbolo "|"), che solitamente si trova sulla tastiera sopra "\"; nel nostro caso basterà fare:

CommonDialog1.Filter="File di testo|*.txt|Tutti i f ile|*.*"

Questa riga si può mettere ad esempio nel Form_Load oppure appena prima di visualizzare la finestra di dialogo, o ancora direttamente nella finestra delle proprietà in fase di progettazione; selezionando, nella finestra di dialogo, il tipo "File di testo", saranno visualizzati solo i file con estensione *.txt; selezionando "Tutti i file" saranno visualizzi tutti i file. Ora il nostro blocco note ha un'aspetto un pò più professionale. Restano ancora un paio di cose da fare (veramente ce ne sarebbero diverse, ma per ora ci accontentiamo così): se l'utente prova a ridimensionare la finestra, avrà la spiacevole sorpresa che il TextBox non si adegua alle dimensioni del form. Per rimediare a quest'altro bug, dobbiamo sfruttare l'evento Resize del frmNotePad: questo evento è scatenato da qualunque operazione di ridimensionamento, e noi non dobbiamo fare altro che rendere uguali le dimensioni del txtFile a quelle del frmNotePad; basterà inserire queste due istruzioni:

txtFile.Width = Me.ScaleWidth - 50 txtFile.Height = Me.ScaleHeight - 50

Il "-50" serve solo a lasciare un po' di spazio tra il margine inferiore del txtFile e quello del frmNotePad; ho usato la proprietà ScaleWidth al posto di Width, perché la prima misura l'area interna del form: provate a usare Me.Width e vi accorgerete della differenza. Il secondo problema è che il txtFile è multiline, ma non ha le ScrollBar: è come se nel "vero" Blocco note fosse impostato "A capo automico", e per vedere le righe non visibili nel TextBox dobbiamo usare le frecce per muovere il cursore; per risolvere il problema basterà impostare la proprietà ScrollBars del txtFile su "3 - Both", in modo da avere sia quella orizzontale che quella verticale.

Page 44: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

44

Aggiungiamo un menù "Cerca" del tutto simile a quello del blocco note di windows, anzi con qualcosa in più: la ricerca con caratteri jolly. I nomi e le caption delle voci di menù sono naturalmente a discrezione del programmatore; io seguirò questo standard:

CAPTION NAME Cerca mnuCerca Trova… mnuTrova Trova Successivo mnuTrovaAncora

mnuCerca è quello che compare sulla barra dei menù, gli altri sono sottomenù. Per permettere all'utente di indicare la parola da cercare basterebbe un banale inputbox, ma vale la pena costruire una finestra un po' più sofisticata, con un textbox (txtTrova) per scrivere la stringa da cercare, un pulsante per avviare la ricerca (cmdTrova), uno per chiudere la finestra (cmdChiudi), tre optionbutton (optSu, optGiu, optTutto) per scegliere la direzione di ricerca, un checkbox per abilitare la ricerca case sensitive (chkCaseSens). Il form si può chiamare frmTrova. Il codice di ricerca della stringa sarà tutto racchiuso nel nuovo form appena creato, cosicché il codice del menù "Cerca" sarà molto semplice: la voce mnuTrova dovrà soltanto richiamare la finestra frmTrova:

Private Sub mnuTrova_Click() frmTrova.Show vbModal End Sub

La costante vbModal indica che il form frmTrova è modale (si dice anche "a scelta obbligatoria") rispetto al form che lo richiama (frmNotePad), cioè non è possibile tornare al form originale prima di aver compiuto qualche scelta (anche la sola chiusura) con la finestra in primo piano. La voce mnuTrovaAncora dovrà invece richiamare la routine del pulsante cmdTrova, che scriveremo in seguito:

Private Sub mnuTrovaAncora_Click() frmTrova.cmdTrova_Click End Sub

Per fare ciò però è necessario che la routine cmdTrova_Click sia pubblica e quindi visibile anche da frmNotePad: perciò occorre sostituire "Private" con "Public" nella dichiarazione dell'evento Click:

Public Sub cmdTrova_Click() End Sub

Non è questa un'operazione molto raccomandabile, perché va a modificare delle dichiarazioni generate direttamente dall'IDE di Visual Basic; in realtà non ha molto senso che la routine di un evento sia "pubblica", perché la generazione dell'evento avviene privatamente rispetto al form che contiene il controllo a cui l'evento si riferisce. Richiamare la routine non corrisponde propriamente alla generazione dell'evento, anche se in buona sostanza le due cose sono uguali. In alternativa, è possibile non modificare la dichiarazione dell'evento Click e impostare a True il valore del pulsante cmdTrova:

Private Sub mnuTrovaAncora_Click() frmTrova.cmdTrova.Value=True End Sub

Possiamo ora dedicarci al codice del form frmTrova, cominciando dalla cosa più semplice: la chiusura del form: Private Sub cmdChiudi_Click() Me.Hide End Sub

Il form viene solo nascosto, e non completamente scaricato, perché è sempre possibile continuare la ricerca della stringa specificata usando il menù mnuTrovaAncora, che deve poter accedere alla proprietà Text di txtTrova: se il form venisse scaricato, il contenuto di txtTrova andrebbe perso. In alternativa, si può memorizzare il contenuto del textbox in una variabile pubblica di frmNotePad, il che permetterebbe comodamente di scaricare frmTrova. All'apertura del form, sarebbe bene che il pulsante cmdTrova sia disabilitato, perché il txtTrova è vuoto: se fosse abilitato e l'utente lo premesse subito, bisognerebbe cercare una stringa nulla, o visualizzare un messaggio di errore che avverta di indicare la stringa da cercare; è possibile evitare tutto ciò semplicemente disabilitando per default (ovvero in fase di progettazione) il pulsante, e abilitarlo quando il txtTrova contiene qualche carattere, sfruttando l'evento Change:

Private Sub txtTrova_Change() If Len(txtTrova.Text) Then cmdTrova.Enabled = True Else cmdTrova.Enabled = False End If End Sub

Prima di scrivere la routine di ricerca, è opportuno specificare l'istruzione Option Compare Binary nella sezione delle dichiarazioni del form: questo perché è semplice impedire un confronto case sensitive usando le funzioni Lcase o Ucase, ma è complicato tornare a un confronto case sensitive con l'operatore Like se l'impostazione di default è Option Compare Text. Veniamo ora alla routine cmdTrova_Click: volendo scrivere una routine abilitata alla ricerca con caratteri jolly (per semplicità gli stessi usati dall'operatore like: *, ?, #), è opportuno procedere in questo modo: data l'impossibilità di cercare direttamente una stringa che contenga caratteri jolly, occorre suddividere il testo cercato in più parti, isolando il testo "puro" dai caratteri jolly. Ad es., se l'utente vuole cercare "abc*", non bisognerà trovare esattamente "abc*", bensì "abc": qualunque stringa cominci con "abc" soddisferà i requisiti indicati dall'utente. Più complesso è il caso di una stringa del tipo "##a*123??": in questo caso bisognerà cercare la lettera "a", oppure i numeri "123", e successivamente verificare che i caratteri circostanti corrispondano al criterio indicato. È ovvio che specificare soltanto "*" o "?" come testo da cercare non ha molto senso. Come prima cosa, occorre eliminare gli asterischi iniziali e finali: cercare "*pippo*" è del tutto equivalente a cercare "pippo", ma il secondo caso è per noi molto più facile da trattare:

Public Sub cmdTrova_Click()

Page 45: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

45

Dim sTestoPuro(1) As String Dim lCount As Long Dim lInizio As Long Dim lFine As Long Do lInizio = lInizio + 1 Loop While Mid$(txtTrova.Text, lInizio, 1) = "*" lFine = Len(txtTrova.Text) Do While Mid$(txtTrova.Text, lFine, 1) = "*" lFine = lFine - 1 Loop txtTrova.Text = Mid$(txtTrova.Text, lInizio, lFine - lInizio + 1)

End Sub

Prima si cerca il primo carattere non-asterisco, poi si cerca l'ultimo carattere non-asterisco e infine si estrae il testo compreso tra i primi e gli ultimi asterischi (asterischi esclusi): questo sarà il vero testo da cercare. A questo punto occorre isolare il testo "puro" dai caratteri jolly:

Public Sub cmdTrova_Click() Dim sTestoPuro(1) As String Dim lCount As Long Dim lInizio As Long Dim lFine As Long Do lInizio = lInizio + 1 Loop While Mid$(txtTrova.Text, lInizio, 1) = "*" lFine = Len(txtTrova.Text) Do While Mid$(txtTrova.Text, lFine, 1) = "*" lFine = lFine - 1 Loop txtTrova.Text = Mid$(txtTrova.Text, lInizio, lFine - lInizio + 1) 'primo testo "puro" lInizio = 0 Do lInizio = lInizio + 1 Loop While Mid$(txtTrova.Text, lInizio, 1) Like "[? #]" lFine = lInizio Do lFine = lFine + 1 Loop Until Mid$(txtTrova.Text, lFine, 1) Like "[*?# ]" Or _ lFine >= Len(txtTrova.Text) sTestoPuro(0) = Mid$(txtTrova.Text, lInizio, lFine - lInizio) 'ultimo testo "puro" lInizio = lFine Do lInizio = lInizio + 1 Loop While Mid$(txtTrova.Text, lInizio, 1) Like "[* ?#]" lFine = lInizio Do lFine = lFine + 1 Loop Until Mid$(txtTrova.Text, lFine, 1) Like "[*?# ]" Or _ lFine >= Len(txtTrova.Text) sTestoPuro(1) = Mid$(txtTrova.Text, lInizio, lFine - lInizio - 1)

End Sub

Per cercare una sequenza di testo "puro", si cerca il primo carattere non-jolly, poi si va avanti fino a trovare un altro carattere jolly o ad arrivare alla fine della stringa; infine si estrae il testo trovato. Le sequenze di testo "puro" da cercare sono due: la prima e l'ultima. Quello che sta in mezzo in fondo non ci interessa, perché una volta trovati gli estremi ci basterà confrontare il testo compreso tra questi estremi con il criterio indico dall'utente: l'operatore Like ci renderà molto semplice questo confronto. Se ad es. l'utente cerca "pippo*abc*def*carlotta", a noi basta cercare "pippo" e "carlotta", dopodiché confronteremo l'intero testo compreso tra "pippo" e "carlotta" con la stringa "pippo*abc*def*carlotta" ricercata dall'utente. Se la sequenza di testo "puro" è solo una, la ricerca potrebbe complicarsi un po' nel caso in cui siano presenti degli asterischi (ad es. "#pippo*?#"). Complicazioni possono sorgere anche nel caso in cui non esiste alcun testo "puro" nella stringa specifica dall'utente: la stringa da cercare infatti conterrebbe solo caratteri jolly; in tali condizioni bisogna distinguere il caso in cui occorre cercare cifre dagli altri casi. Infatti, se può avere un senso cercare ad es. "#*#", non ha molto senso cercare "*?*", che si ridurrebbe banalmente a "*", ovvero tutto il testo del file e qualunque suo sottoinsieme!

Page 46: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

46

Diciannovesima lezione – I Menù Abbiamo visto come sia possibile includere in un Form, una barra di menù. Qui approfondiremo l’uso dei menù. Ogni elemento del menù (menù, sottomenù, voce di menù o linea di separazione) è un controllo menù. L’Editor di menu consente la definizione di ciascun controllo con l’impostazione delle relative proprietà. Per creare un controllo menu occorre impostare almeno la proprietà Caption (che indica il testo da visualizzare) e la proprietà Name (che indica il nome con cui fare riferimento al controllo nel codice). I pulsanti Inserisci, Elimina, Freccia a sinistra, Freccia a Destra, Freccia su e Freccia giù permettono l’impostazione grafica desiderata di menù e sottomenù. Si possono creare dei segni di separazione tra i comandi con una voce costituita da un (-). Si può anche creare un tasto di accesso rapido ad una voce di menù: per fare questo basta far precedere il carattere desiderato da &. Può svolgere la funzione di tasto di scelta rapida anche un tasto funzione. La proprietà Visible indica se il controllo è visibile o nascosto; la proprietà Enabled indica se è abilitato o meno. La proprietà Checked indica se accanto alla voce deve apparire un segno di spunta. Queste stesse proprietà possono essere modificate dinamicamente dal codice in esecuzione. La proprietà index permette di creare una matrice di controlli menù. Una matrice di controlli menù è un insieme di voci dello stesso menù che hanno lo stesso nome e che condividono la stessa routine di evento; si accede ai singoli controlli per mezzo della proprietà index partendo dal valore 0 e proseguendo in successione. Utilizzando una matrice di controlli menù è possibile aggiungere un controllo in fase esecuzione: per fare questo si può usare l'istruzione Load indicando il nome del controllo e come indice il valore successivo all'ultimo esistente. L'istruzione Unload permette di eliminare una voce di menù da una matrice di controlli menù. Con il controllo menu si possono anche gestire in menù di scelta rapida (quelli visualizzati quando si fa click destro su un controllo). Per visualizzare in Form un menù di scelta rapida bisogna utilizzare il metodo PopupMenu. Il menù da utilizzare va creato con l’Editor di menù disattivando la proprietà Visible per il controllo (il controllo non è visibile). Nelle routine di evento MouseUp e MouseDown va verificato se è stato usato il pulsante destro del mouse (il valore di Button, il primo argomento, deve essere uguale a vbRightButton), ed in tal caso di chiamare il metodo PopupMenu.

Dim ncontr As Integer Private Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbRightButton Then PopupMenu menu_cmd1 End If End Sub Private Sub Command2_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbRightButton Then PopupMenu menu_cmd2 End If End Sub Private Sub fine_Click() End End Sub Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbRightButton Then PopupMenu menu End If End Sub Private Sub help_Click() MsgBox "esempio di uso di menù", vbInformation, "informazioni" End Sub Private Sub m1_Click() MsgBox "hai usato il popup menù" End Sub Private Sub m2_Click() MsgBox "hai usato il popup menù" End Sub Private Sub mess1_Click() MsgBox "prova" End Sub

Page 47: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

47

Ventesima lezione – Controlli: Approfondimenti In questo capitolo forniremo maggiori informazioni su controlli già visti nella lezione 7. Tra le innumerevoli proprietà fornite dai vari oggetti ne esiste un insieme condiviso da molti di essi.

Proprietà comuni Left Top Width Height Riguardano il contenitore del controllo: per il form è lo schermo mentre per i controlli in

generale è il form stesso. Top e Left determinano la posizione del controllo rispetto al contenitore; Width e Height ne definiscono le dimensioni. L’unità di misura è il twip ma possono essere utilizzate altre unità di misura impostando la proprietà ScaleMode del contenitore.

ForeColor BackColor Influenzano il colore del testo e il colore di sfondo. Il comportamento dipende da altre proprietà come BackStyle per le etichette e Style per i CommandButton. Per specificare il colore si possono usare o costanti simboliche (vbRed. ..) o numeriche in formato esadecimale (&Hffff00) nella logica RGB. È possibile usare anche la funzione RGB( red,green,blue) specificando i valori (0-255) per i tre colori componenti.

Font Specifica il font di caratteri da usare per visualizzare stringhe di testo. È esso stesso un oggetto che espone le proprietà Name, Size, Bold, Italic, Underline, Strikethrought.

Caption Text Rappresentano la stringa di caratteri che appare all’interno di un controllo. Normalmente Caption riguarda controlli che non permettono di modificare tale stringa al contrario della proprietà Text

Parent Disponibile solo in fase di esecuzione restituisce riferimento al form che ospita il controllo; è di sola lettura quindi non è possibile spostare un controllo da un form ad un altro

Container Disponibile solo in fase di esecuzione restituisce riferimento al contenitore che ospita il controllo; è di lettura/scrittura quindi è possibile spostare un controllo da un contenitore ad un altro. Occorre usare il comando set: Set Text1.Container=Picture1 sposta Text1 nel contenitore Picture1

Enabled Visible Abilita o disabilita un controllo a gestire eventi (Enabled); rende visibile o invisibile un controllo

hWind È disponibile solo in fase di esecuzione ed è di sola lettura; restituisce il valore intero 32 bit che Windows usa internamente per identificare un controllo

TabStop TabIndex Identifica l’ordine con cui viene spostato lo stato attivo dei controlli quando l’utente preme TAB.

MousePointer MouseIcon Influenzano la forma del cursore del mouse quando passa sopra un controllo. MouseIcon serve a creare un mouse personalizzato quando MousePointer è impostato 99; per caricare l’icona per il mouse si usa l’istruzione Load( ).

Tag Non ha particolare significato; può essere utilizzata come contenitore per un qualunque dato correlato al controllo definito dal programmatore.

Value Il significato di questa proprietà varia da controllo a controllo ma comunque rappresenta un valore numerico oppure booleano.

Index È la proprietà chiave della costruzione di array di controlli Appareance Dà ai controlli un aspetto tridimensionale o piatto Align Definisce l’allineamento del controllo rispetto al bordo della finestra che lo contiene. BorderStyle Serve per eliminare il bordo intorno al controllo o per aggiungerlo ToolTip sono piccole caselle di testo normalmente gialle che appaiono in molte applicazioni

Windows quando posizionare il puntatore del mouse su un controllo

Metodi comuni Move Permette di cambiare la posizione di un controllo e le dimensioni

Formato Move Left, Top, Width, Height Refresh Provoca il ridisegno del controllo SetFocus Sposta lo stato attivo o focus sul controllo ZOrder Influenza la visibilità del controllo: il valore di uno ci posta il controllo dietro a tutti gli

altri, senza parametri lo posiziona davanti agli altri controlli

Eventi comuni

Click DoubleClick Si verifica quando l’utente fa click con il pulsante sinistro del mouse sul controllo Change Si verifica se il contenuto del controllo cambia; notare che su CheckBox e OptionButton

la variazione del controllo provoca un evento click

Page 48: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

48

GotFocus LostFocus Si verificano quando il controllo riceve lo stato attivo o lo perde. Spesso è usato per il controllo di un campo e la notifica di un valore non corretto: per tali casi è meglio usare l’evento Validate e la proprietà CausesValidation

KeyDown KeyPress KeyUp

Si è video quando l’utente preme un tasto mentre un controllo riceve l’input. Prima si verifica KeyDown, quindi KeyPress e infine KeyUp. Con KeyPress è possibile controllare e anche scatare il valore del tasto premuto impostandolo a 0 nella relativa routine di risposta. KeyDown KeyUp ricevono due parametri KeyCod e Shift: il primo è il codice fisico (in sola lettura) del tasto premuto, il secondo indica lo stato dei tasti Ctrl, Maiusc e Alt. Se la proprietà KeyPreview del Form contenitore del controllo è True, questi eventi vengono prima inviati al form poi al controllo.

MouseDown MouseUp MouseMove

Verificano rispettivamente quando viene fatto un clic con il pulsante del mouse, quando il pulsante viene rilasciato o quando il mouse viene spostato in un controllo. Alla routine di evento vengono forniti un insieme di parametri: lo stato dei tasti Maiusc/Ctrl/Alt, le coordinate x e y del cursore del mouse. Un evento clic si verifica dopo una sequenza MouseDown .. MouseUp

L’oggetto Form

BorderStyle Imposta per il controllo la possibilità di ridimensionamento Caption Il testo che appare sulla barra del titolo ControlBox Importa la presenza del menù di sistema MinButton MaxButton In vostra presenza dei relativi pulsanti di riduzione a icona e ingrandimento WindowState Imposta se visualizzare il Form a tutto schermo, ridotto a icona o normale StartupPosition Utile che si vuol far apparire il form nel centro dello schermo Moveable rendere la finestra non spostabile SkowInTaskbar Il form viene mostrato nella barra delle applicazioni se impostata a Truer AutoRedraw Indica se il contenuto del form viene salvato su una bitmap persistente permettendo un

veloce ridisegno. Attenzione all’occupazione di memoria

Ciclo di vita di un form Sequenza di eventi che si verificano al caricamento di un form in memoria e alla sua eliminazione Initialize E il primo evento che si verifica, appena il codice fa riferimento al forme prima della

sua predisposizione sul video. Qui si può inserire il codice di inizializzazione delle variabili

Load Tutto il codice viene caricato in memoria e viene allocato lo spazio video per il form. Esso non è ancora visibile, lo diventerà solo se è stato attivato tramite il metodo Show.

Resize Prima di diventare visibile viene chiamato questo evento. Può essere utilizzato per posizionare i controlli sul form.

Activate Si verifica quando il form diventa form attivo dell’applicazione corrente. Può essere utilizzato per aggiornare il contenuto del form con dati che potrebbero essere stati modificati in un altro form

Paint Viene generalmente disegnata anagrafica del form. Non si verifica s’è impostata la proprietà AutoRedraw a True

Deactivate Avviene quando l’utente passa ad un altro form dell’applicazione o se viene impostata la sua proprietà visibile a false o ho chiamato il suo metodo Hide

QueryUnload Si verifica quando il form sta per essere scaricato. Ha due parametri: il primo permette di interrompere lo scaricamento del form (Cancel=True), il secondo specifica la causa dello scaricamento

Unload Se non annullate dell’operazione di scaricamento viene provocato l’evento Unload, che costituisce l’ultima possibilità di impedire la chiusura del form.

La Collection Controls

Questa proprietà restituisce una collezione contenente tutti controlli caricati sul form. Facciamo due esempi di uso:

for i=0 to Controls.Count – 1 Controls(i).Tag=” ” Next i

Pulisce la proprietà Tag di tutti controlli presenti. Dim ct as Control For Each ct in Controls ct.Tag=” ” Next

Fa la stessa cosa utilizzando un ciclo For Each … next

L’oggetto TextBox

Page 49: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

49

Esso rappresenta il modo naturale per immettere dati in un programma: sono quindi controlli più utilizzati nelle applicazioni Windows. Vediamo le proprietà più comuni di questo controllo. Text È sicuramente l’avrebbe dato importante; contiene i dati immessi nel Textbox. Era proprietà

predefinita di quest’oggetto. MultiLine Va messa a True se il testo immesso è composto da più righe. ScrollBars Se Multiline=True Visualizza le basse di scorrimento Alignment Permette di allineare il testo a sinistra, a destra o al centro della casella Locked Permette di impedire all’utente di modificare il contenuto del controllo MaxLength 0 (predefinito) significa che se vuoi immettere qualsiasi numero di caratteri,un valore positivo

limita la lunghezza del contenuto del campo PasswordChar Server nel caso di campi password per impostare il carattere da visualizzare al posto di quelli

effettivamente digitati. Generalmente si usa * Font È l’oggetto che rappresenta il font di caratteri da usare per la visualizzazione ToolTipText Permette di aiutare l’utente a capire l’utilità del controllo BorderStyle È possibile impostare il bordo del controllo: 0 =None SelStart Utilizzabile a RunTime, imposta o restituisce la posizione del cursore (caret), cioè il punto di

inserimento nel testo digitato. 0 significa che il caret si trova all’inizio del testo SelLength Restituisce il numero dei caratteri della porzione di testo evidenziato all’utente, 0 se non c’è testo

evidenziato. SelText Imposta o restituisce la porzione di testo evidenziata dall’utente CausesValidation Questa proprietà (impostata a True) permette di innescare l’evento Validate quando la TextBox

perde il focus. Nella routine Validate va messo il codice che controlla l’input del test inserito

Eventi TextBox Gli eventi KeyDown KeyPress KeyUp Change MouseDown MouseMove sono già stati descritti. Validate è innescato quando la textbox perde il focus e la proprietà CauseValidation è True. L’evento è anche innescato quando si richiama il metodo ValidateControls del Form contenitore del controllo.

Private Sub txtRequired_Validate(Cancel As Boolean) ' Testa ceh il campo non sia vuoto If txtRequired.Text = "" Then MsgBox "Per Favore immettere un valore valido", vbExclamation Cancel = True End If End Sub

Il testo della TextBox normalmente non può contenere CR-LF (quando premo invio) né Tab.

L’oggetto Label Normalmente il controllo Label è usato per offrire un sottotitolo descrittivo ed una chiave di accesso rapido per altri controlli, come TextBox, ListBox, e ComboBox che non possiedono la proprietà Caption. La proprietà Caption della Label è la proprietà predefinita. Occorre fare attenzione a mettere la sua proprietà TabIndex ad un valore inferiore di 1 rispetto al controllo associato. Proprietà importanti sono:

• Caption (contenete la stringa da visualizzare) • BorderStyle (per fornire al controllo un bordo tridimensionale), • Alignment (per allineare il contenuto del controllo a destra o a sinistra) • WordWrap (per estendere la stringa su più righe, invece di troncarla al bordo della Label) • AutoSize ( per lasciare al controllo la possibilità di ridimensionarsi automaticamente) • BackStyle (se impostato a 0 rende lo sfondo trasparente) • UseMnemonics (in collegamento ai database permette di utilizzare la & senza che venga interpretata come hot

ey) La gestione dell’evento Click può servire, ad esempio, per creare delle aree sensibili su delle picture (trasparente e senza bordo),magari impostando anche il ToolTip. Qualche volta può servire la gestione dell’evento Ch’ange, specie se il controllo è associata ad un database.

L’oggetto Frame Come la Label può creare una Caption a controlli che ne sono sprovvisti. E’ normalmente utilizzato come contenitore di altri controlli, detti controlli secondari o figli. Lo spostamento di un frame sposta anche tutti i controlli in esso contenuti.

L’oggetto CommandButton Il loro uso è molto semplice: basta disegnarlo sul form, impostarne la Caption e gestire l’evento Click. Tra le proprietà importanti troviamo Default (utile a considerarlo come controllo predefinito quando l’utente preme l’invio) e Cancel (utile a considerarlo come controllo predefinito quando l’utente preme ESC); la proprietà runtime Value impostata o

Page 50: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

50

restituisce lo stato del controllo (true = premuto). ' Questa azione attiva l’evento Click del controllo . Command1.Value = True

Gli eventi di interesse sono: KeyDown, KeyUp, KeyPress, MouseDown, MouseMove, MouseUp, GotFocus e LostFocus.

L’oggetto CheckBox Servono per offrire una scelta del tipo Si/No, Vero/falso. Facendo click si commuta la scelta. Le proprietà più comuni di questo controllo sono: Caption La stringa descrittiva del controllo Value Visualizza/imposta lo stato del controllo (1=Checked). Il valore è numerico. Alignment La posizione della Caption nel controllo L’unico evento importante è l’evento Click, attivato quando viene alterato lo stato del controllo.

L’oggetto OptionButton I controlli optionbutton (o pulsanti di azione - anche detti radiobutton) vanno sempre utilizzati in gruppi di due o più perché offrono un numero di scelte che si escludono a vicenda. Ogni volta che si fa clic su un pulsante del gruppo questo passa ad uno stato selezionato mentre tutti gli altri controlli diventano selezionati. Sono simili nel funzionamento ai controlli checkbox. Le proprietà più comuni sono: Caption La stringa descrittiva del controllo Value Visualizza/imposta lo stato del controllo (true=selezionato). Il valore è booleano. Proprietà predefinita Alignment La posizione della Caption nel controllo Style Cambia l'aspetto del controllo (1-Graphical lo trasforma in un pulsante) Picture Nel caso di controllo grafico rappresenta l’icona da visualizzare DownPicture È l’icona che rappresenta lo stato premuto DisablePicture È l’icona che rappresenta lo stato disabilitato MaskColor È il colore da considerare come trasparente UseMaskColor Impostato a TRUE permette l'uso della proprietà maskcolor I controlli optionbutton solo spesso riuniti in un controllo frame.

L’oggetto ListBox È un controllo che permette all'utente di creare un elenco di scelte tra le quali selezionare quella desiderata. Alcune proprietà sono selezionabili sono in fase di creazione e non modificabili durante l'esecuzione. Sorted Crea un elenco in cui le voci sono automaticamente ordinate conseguenza alfabetica (true) Columns L'aspetto di default contiene una sola colonna e una barra di scorrimento verticale; si possono però

avere barre di scorrimento orizzontali e colonne multiple TopIndex imposta o restituisce l'indice della prima voce visibile dell'area di riepilogo ItemData Consente di associare un valore intero 32 bit a ogni voce caricata nella listbox. Può servire per

associare una chiave numerica ad ogni elemento dell'elenco NewIndex contiene la posizione (l’indice) in cui è stato inserito un nuovo elemento in fase di esecuzione ListCount Restituisce il numero di voci nel controllo; utilizzabile in abbinamento alla proprietà list Text Restituisce la stringa effettiva della voce selezionata (se ListIndex >=0) ListIndex In fase di esecuzione indica quale voce è stata selezionata dall'utente, restituendone l'indice (su base

0). Il valore -1 indica che l'utente non ha selezionato alcuna voce. È possibile anche assegnare un valore a ListIndex per selezionare una voce in fase di esecuzione oppure impostarlo a -1 per deselezionare tutte le voci

MultiSelect 1-Semplice 2-Multipla: nel caso di selezione multipla è possibile selezionare più voci della lista SelCount Utilizzabile in abbinamento a MultiSelect restituisce il numero di voce selezionate al momento Selected È un valore booleano che restituisce true se una voce è selezionata

For i=0 to list1.listcount – 1 If list1.selected(i) then print list1.list(i) Next i

Altre proprietà invece possono essere modificate in fase di esecuzione: IntegralHeight Permette di impostare l'altezza manualmente oppure di adattarla alla dimensione del Font utilizzato in

modo da visualizzare sempre righe intere di testo List Elenco dei valori da visualizzare la finestra aggiunti in fase di progettazione. I valori possono anche

essere aggiunti usando il metodo additem. Style Aggiunge una casella di controllo alle singole voci dell'elenco per la selezione I metodi a disposizione sono i seguenti:

Page 51: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

51

AddItem Permette di aggiungere elementi all'elenco. Il prototipo è List1.AddItem <voce> [, <posizione>] La posizione (partendo da 0) rappresenta appunto la posizione fisica all'interno dell'elenco in cui aggiungere la voce ed ha precedenza rispetto alla proprietà sorted. Dopo l'aggiunta di un elemento viene settata la proprietà NewIndex che contiene la posizione in cui è stato inserito questo elemento

RemoveItem Elimina una voce dall'elenco. Il formato è: List1.RemoveItem <posizione>

Clear Rimuove tutti gli elementi dall'elenco Gli eventi a cui reagisce il controllo sono i seguenti: Click Si verifichi ogni volta le viene selezionata una nuova voce DblClick Si verifichi ogni volta le viene selezionata una nuova voce. Può servire per effettuare qualche

operazione particolare nel form Scroll Attivato quando ci si sposta da una voce selezionata ad un'altra magari cambiandola proprietà

TopIndex (che imposta o restituisce l'indice della prima voce visibile dell'area di riepilogo). Permette di sincronizzare un controllo listbox con un altro controllo di solito anche esso listbox.

Click MouseDown MouseUp

Il cui effetto è già conosciuto

L’oggetto ComboBox

È composto da un controllo listbox e da un controllo textbox. Questo controllo è simile al controllo listbox, condividendone metodi, proprietà ed eventi (sorted, list, integraheight, additem, removeitem, clear, listcount, listindex, itemdata, topindex, newindex, click, dblclick, scroll). Non supporta colonne multiple e selezioni multiple. Allo stesso modo condivide metodi ed eventi del controllo textbox (selstart, sellength, seltext, locked, keydown, keypress, keyup, gotfocus, lostfocus, validate). La proprietà più caratteristica è la Style che impostata ad 0 offre una casella di testo in cui immettere un valore della lista o di selezionarne uno nell'elenco discesa, rendendo visibile l'elenco solo su richiesta; la scelta 1 oltre al funzionamento precedente crea una lista sempre visibile; la scelta 2 non permette l'inserimento di dati ma solo la consultazione e la selezione. Il controllo con l'elenco discesa non fornisce l'evento Change né gli eventi associati alla tastiera. Interessante è l'evento DropDown che viene attivato subito prima di mostrare l'elenco discesa (Style=0 e 2) permettendo magari di riempire l'elenco subito prima di visualizzarlo

L’oggetto PictureBox È uno dei controlli più potenti tra quelli messi a disposizione da Visual Basic; per molti versi è simile al controllo form, non solo perché può funzionare come contenitore di altri controlli ma anche perché supporta diverse proprietà grafiche AutoRedraw, ClipCOntrol, HasDC, FontTransparent, CurrentX, CurrentY, Drawxxm Fillxx, Scalexx. Supporta inoltre diversi metodi grafici: Cls, PSet, Point, Line, Circle, ScaleX, ScaleY, TextWidth, TextHeight. Picture permette di caricare immagini direttamente dalla finestra proprietà. È possibile caricare immagini con

estensione bmp, dib, wmf, emf, gif, jpeg, ico, cur. In fase di esecuzione occorre utilizzare la funzione LoadPicture(“<nome immagine>”) per caricare l'immagine che va che va assegnata alla proprietà Picture. Se si specifica un parametro vuoto è possibile cancellare l'immagine corrente. È possibile avviare un'immagine da un controllo PictureBox ad un altro semplicemente assegnando la proprietà Picture.

BorderStyle permette di decidere se visualizzare un bordo AutoSize impostata a True permette al controllo di ridimensionarsi automaticamente per adattarsi all'immagine

assegnata Align Serve per allineare il controllo a uno dei quattro bordi del form Eventi: Resize Permette di intercettare il ridimensionamento dell'immagine, magari per spostare e ridimensionare i

controlli contenuti nel PictureBox Metodi: PaintPicture Consente di eseguire numerosi effetti grafici, tra cui zoom, scorrimento, panoramica, affiancamento,

capovolgimento e molti effetti di dissolvenza. Esso esegue una copia pixel per pixel da un controllo origine ad uno di destinazione. Permette inoltre di ridimensionare l'immagine mentre viene trasferita. Permette inoltre di creare delle animazioni.

L’oggetto Image

È un controllo più semplice rispetto al precedente. Esso non porta metodi grafici o proprietà AutoRedraw o ClipControls e non può funzionare come contenitore. Vengono però caricati più rapidamente e consumano meno memoria e risorse sistema. Sono windowless, cioè privi di finestra. Possono caricare bitmap e i margini Jpeg e Gif. La proprietà principale è ovviamente la Picture, che permette di caricare l'immagine utilizzando la funzione LoadPicture. Il

Page 52: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

52

controllo si ridimensiona automaticamente sulle dimensioni dell'immagine visualizzata. La proprietà Stretch, se True, ridimensiona l'immagine, distorcendola se necessario, in modo che si inserisca nel controllo: in tale caso l'immagine può essere ingrandita o ridotta modificando semplicemente la larghezza e l'altezza. Questo controllo è spesso utilizzato al posto dei bottoni di comando come se fosse un pulsante grafico.

L’oggetto ScrollBar (HScrollBar, VScrollBar) A parte il loro orientamento sono due controlli perfettamente identici. Le proprietà più importanti sono sicuramente Min e Max che rappresentano l'intervallo valido di valori, SmallChange è la variazione di valore che si ottiene facendo clic e sulle frecce della barra di scorrimento, LargeChange è la variazione che si ottiene facendo clic su un lato della casella nella barra di scorrimento. In fase di esecuzione è molto importante la proprietà Value che restituisce la posizione relativa della casella nella barra di scorrimento. Gli eventi più importanti di questo controllo sono: l'evento Change che si attiva quando si fa clic sulle frecce della barra di scorrimento o quando si trascina e si rilascia l'indicatore; l'evento Scroll si attiva quando si trascina l'indicatore. Questi controlli possono ricevere il focus e quindi supportano le proprietà TabIndex e TabStop.

I controlli DriveListBox, DirListBox, FileListBox Il controllo DriveListBox è un controllo di tipo combobox che viene riempito radicalmente con le lettere del drive e le etichette di volume. DirListBox è uno speciale controllo ListBox che visualizza una struttura di directory, il controllo FileListBox è un controllo ListBox speciale che visualizza tutti i file di una determinata directory, filtrandoli facoltativamente sulla base dei nomi o delle estensioni. Di solito questi controlli vengono fatti lavorare cooperando tra di loro, ad esempio cambiando l'elenco delle cartelle quando viene cambiato il drive e cambiando l'elenco dei file quando viene cambiata la cartella. Il controllo fileListbox possiede la proprietà Pattern che indica quali file elencare nell'area di riepilogo; il valore *.* è predefinito e significa tutti i file ma è possibile anche specificare più gruppi di estensioni separati da ;. Selezionando un drive diverso viene attivato l'evento change e la proprietà Drive1.drive viene riempita con la lettera dell'unità selezionata. La proprietà Dir1.Path può essere impostata in modo da elencare le cartelle presenti nell'unità precedentemente selezionata. Anche il controllo dir mostra l'evento change che può servire per impostare la proprietà path del controllo filelist, in modo da visualizzare i file contenuti nella cartella selezionata nel drive è selezionato. I controlli in Dirlist e filelist mostrano le proprietà listcount e listindex oltre all'evento scroll. Il controllo filelist permette di specificare se visualizzare anche i file di tipo Normal, archivi, hidden, readonly e system. Inoltre quest'ultimo controllo permette di intercettare gli eventi PathChange e PatternChange. Questi controlli sono oramai obsoleti e sostituiti dai controlli common dialog.

Il controllo Timer È un controllo invisibile in fase di esecuzione. Il suo compito è di inviare un impulso periodico all'applicazione corrente; queste impulso viene intercettato sul scrivendo del codice nella procedura di evento Ti mer. Esso espone solo due proprietà : Interval che rappresenta il numero di millisecondi tra impulsi successivi; Enabled consente di attirare o disattivare gli eventi.

Page 53: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

53

Ventunesima lezione – Date e orari In Visual Basic esiste il tipo di dato Date per memorizzare informazioni su data e ora. Il linguaggio mette a disposizione numerose funzioni per la gestione delle date. Le funzioni Date e Time permettono sia di leggere la date allora il sistema sia di impostarla

Print Date & “ “ & Time Date= “15/10/2007”

La funzione Now restituisce si era data che l'ora corrente. La funzione Timer restituisce il numero di secondi trascorsi dalla mezzanotte e viene azzerata da mezzanotte. La funzione DateSerial crea un valore Date a partire dai valori anno/mese/giorno passati come argomento.

Function Bisestile(anno as integer) as boolean Bisestile=Dateserial(anno,2,29)<>Dateserial(anno,3,1)

End Function La funzione TimeSerial crea un valore Time a partire dai valori ore/minuti/secondi passati come argomento. DateValue e TimeValue ritornano una data o un’ora calcolata a partire dall'argomento

Print DateValue (now + 7)

Esistono le funzioni Day, Month, Year Hour, Minute e Second che permettono di estrarre informazioni da argomenti data o ora. La funzione WeekDay ritorna un numero compreso tra 1 e 7 che corrisponde al giorno della settimana dell'argomento date passato alla funzione (1=domenica per l’europa). La funzione DatePart permette di estrarre diverse informazioni da una data.

?now 05/10/2007 18.53.55 ? datepart("yyyy",now) ' anno 2007 ? datepart("q",now) ' trimestre 4 ? datepart("m",now) ' mese 10 ? datepart("d",now) ' giorno dell'anno 5 ? datepart("w",now) ' giorno della settimana 6 ? datepart("ww",now) ' settimana 40

La funzione DateAdd(interval,number,date) dove interval è una delle stringhe appena viste (wwww,q,m,d,w,ww), number ha un valore numerico positivo o negativo, permette di aggiungere o sottrarre valori ad una data. La funzione DateDiff permette di valutare la differenza tra due date. La funzione più importante e flessibile per il formato dei valori di data e ora è Format, che offre sette diversi formati (con nome) per la data e l’ora: General Date, Long Date (venerdì 10 settembre 2007), Medium Date (14-lug-2005), Sort Date (14/08/07), Long Time (8:44:22), Medium Time (9:27 AM), Short Time (15:34). Esistono inoltre dei caratteri speciali che consentono di creare stringhe personalizzate del formato data e ora, compresi numeri dei giorni e dei mesi composti da 1 e 2 cifre, i nomi dei mesi e dei giorni della settimana completi o abbreviati, gli indicatori am/pm, i numeri della settimana e di trimestre. Format(now, “mmm ddd yyyy dddd”) ‘ stampa mese abbreviato , giorno abbreviato(numero) anno, descrizione giorno .

Page 54: Prof. Tombolini Gino Appunti di programmazione Visual Basicanicele.it/Doc/VisualBasic.pdf · Lezione 10 Vettori e matrici. Lezione 11 Cicli For ... Next Lezione 12 Cicli Do...Loop

Prof. Tombolini Gino Appunti di programmazione Visual Basic

54

Ventiduesima lezione – L’oggetto Printer Visual Basic fornisce un oggetto Printer che espone diverse proprietà e metodi per controllare accuratamente l'aspetto dei documenti stampati. Esiste inoltre una collezione Printers che consente di raccogliere informazioni su tutte le stampanti installate del sistema. Ogni elemento di questa collezione è un oggetto Printer e tutte le relative proprietà sono di sola lettura, quindi non è possibile modificarne le caratteristiche. Per modificare una caratteristica di una stampante occorre prima assegnarla all'oggetto Printer mediante l'istruzione Set.

Set Printer=Printers(1) Un oggetto Printer espone molte proprietà, le principali sono: DeviceName Il nome della stampante p resente nel Control Panel DriverName Il nome del driver utilizzato dal device Port La porta a cui è collegata la stampane (LPT1: ) ColorMode Determina una stampante è a colori(1) o monocromatica(2) Orientation Determina l'orientamento corrente della pagina PrinterQuality Restituisce la risoluzione corrente (1-draft, 2-Low, 3-Medium, 4-High) PaperSize Le dimensioni della carta PaperBin L'alimentatore della carta Duplex La capacità di stampare entrambe le facciate di un foglio Copies Il numero di copie da stampare Zoom Il fattore di zoom applicato durante la stampa Page In fase di esecuzione ritorna il numero di pagina corrente ScaleLeft ScaleTop

Fanno riferimento all'angolo superiore sinistro dell'area stampabile, il valore predefinito è 0

ScaleWidth ScaleHeight

Restituiscono le coordinate nell'angolo inferiore destro dell'area stampabile

ScaleMode L'unità di misura utilizzata per le utilizzata per le coordinate (in twip)

L'invio dell'output all'oggetto Printer è e si è trovato per mezzo di numerosi metodi grafici: Print, Pset, Line, Circle, PaintPicture. L’oggetto Font possiede numerose proprietà che possono controllare l'aspetto dell'output (Fontxxx, CurrentX, CurrentY, ForeColor..). I metodi più importanti per oggetto Printer sono: Print Invia alla stampante il testo fornito come parametro EndDoc Informa l'oggetto Printer che tutti i dati sono stati inviati e che l'operazione di stampa effettiva può iniziare NewPage Invia la pagina corrente alla stampante e avanza alla pagina successiva, ripristina la posizione di stampa nell'angolo superiore

sinistro della pagina e incrementa il numero di pagina. Il numero di pagina corrente può essere recuperato utilizzando la proprietà Page

KillDoc Termina il lavoro di stampa corrente prima di inviare i dati al device di stampa

For i = 0 to Printers.Count – 1 cboPrinters.Additem Printers(i).Devicename Next i …… Set Printer=Printers(cboPrinters.ListIndex) …. Printer.Print “Ciao” Printer.NewPage Printer.Print “Seconda pagina” Printer.EndDoc