Breve Corso di Visual Basic

Transcript

Breve Corso di Visual Basic
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
Introduzione al Visual Basic
Indice
Lezione 1
Lezione 2
Lezione 3
Lezione 4
Lezione 5
Lezione 6
Lezione 7
Lezione 8
Lezione 9
Lezione 10
Lezione 11
Lezione 12
Lezione 13
Lezione 14
Lezione 15
Lezione 16
Lezione 17
Lezione 18
Lezione 19
Lezione 20
Lezione 21
Lezione 22
Introduzione a Visual Basic.
Le variabili in Visual Basic.
Le routine in Visual Basic
Le funzioni in Visual Basic.
Il primo programma in Visual Basic.
Convenzioni.
Interfaccia grafica e controlli standard.
Operatori Booleani e struttura IF
Nozioni avanzate sulle variabili.
Vettori e matrici.
Cicli For ... Next
Cicli Do...Loop
Struttura Select Case
Stringhe
Debug e gestione degli errori
Gestione dei Files
Gli Oggetti
Studiare un'applicazione professionale : il Blocco Note di Windows
I Menù
Controlli: approfondimenti
Date e orari
L’oggetto Printer
1
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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:
Fig.1: Apertura di un nuovo
Fig.2: Casella degli strumenti utilizzabili in Visual Basic.
progetto "EXE Standard"
Quelli visibili all'apertura dell'applicazione sono i controlli
scegliendo di creare un nuovo progetto "exe standard"
standard (o di default). Per visualizzare o gestire
l'aggiunta/rimozione di altri controlli cliccare col
(Fig.1) al centro compare una finestra con un "form": i form rappresentano le
pulsante destro del mouse sulla finestra "Generale".
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
Fig.3: La finestra delle Proprietà
di un controllo particolare (ad es., la proprietà Interval è disponibile
visualizza
le
proprietà
dell'oggetto seleziono sul form.
solo per il controllo Timer). Solitamente le proprietà possono essere
A
seconda
dell'oggetto
seleziono,
le
proprietà
lette e anche impostate, ovvero è possibile sia leggere il valore della
visualizzate nella tabella saranno
differenti. Per modificare una
proprietà fare clic sulla casella
proprietà, sia assegnare ad essa un nuovo valore: in tal caso si dice che
corrispondente
alla
seconda
colonna. A questo punto può
la proprietà è di lettura e scrittura; tuttavia esistono anche proprietà di
essere richiesto di immettere
manualmente di come numeri,
sola lettura (alle quali non è possibile assegnare un nuovo valore) e di
lettere
o
simboli,
oppure
scegliere tra più possibilità de o
sola scrittura.
ancora potrà comparire una
finestra
di
dialogo
collega
all'argomento.
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.
2
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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: Casella destra e sinistra
(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
Byte
Integer
Long
Spazio occupato in
memoria
1 byte
2 byte
4 byte
Intervallo di valori
0/255
-32768/+32767
-2147483648 / +2147483647
Numeri dotati di decimali virgola mobile e singola
Single
4 byte
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.
3
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
4
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
Prova
End Sub
e proviamo ad avviare il progetto, vedremo che nella finestra immediata viene scritto:
11
e non, come qualcuno si potrebbe aspettare:
12
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:
12
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.
5
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
6
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
7
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
8
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
9
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
10
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
11
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
12
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
Consente di selezionare, spostare o ridimensionare form o controlli.
(pointer)
Casella di testo
Crea un box dove l’utente può inserire o modificare una stringa di caratteri. Serve sia
(Text Box)
per l’input che per l’output. Può contenere più righe ed è possibile scorrerla.
Pulsante di comando
Bottone di comando per iniziare o terminare un’elaborazione. Si attiva facendo click
(Command Button)
su di esso o premendo la barra spaziatrice dopo averlo selezionato.
Etichetta
Visualizza un messaggio o un’intestazione che l’utente non può modificare. È’ utile
(Label)
per visualizzare informazioni per l’utente, titoli o descrizioni del contenuto delle
caselle di testo.
Casella di controllo
Quadratino con eventuale crocetta per gestire le scelte dell’utente del tipo si/no o
(Check Box)
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
Permette di attivare un’opzione scelta tra un gruppo di opzioni. E’ possibile
(Optino Button)
selezionare un solo pulsante del gruppo; quando si seleziona un’opzione (pallino
presente), viene disattivata quella precedentemente attiva.
Casella di riepilogo
Consente di creare un elenco che l’utente po’ scorrere e/o selezionare una o più voci.
(List Box)
Casella Combinata
Consente all’utente di operare una scelta scrivendola nel box di testo o selezionando
(Combo Box)
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 Permette all’utente di selezionare il disco (A:,C: ..) durante l’esecuzione
delle unità disco
dell’applicazione.
(Drive List Box)
Casella di riepilogo Permette all’utente di selezionare directory o sottodirectory del disco durante
delle directory
l’esecuzione dell’applicazione.
(Directory List Box)
Casella di riepilogo dei Permette all’utente di selezionare i file durante l’esecuzione dell’applicazione.
file
Consente di visualizzare tutti i file di una determinata directory, effettuando anche dei
(File List Box)
filtri sul tipo.
Cornice
Crea una cornice adatta a contenere dei controlli, raggruppandoli in modo sia grafico
(Frame)
che funzionale. E’ spesso usata per racchiudere più gruppi di option button.
Barra di scorrimento Crea una barra di scorrimento pr muoversi all’interno dei form o liste di grandi
orizzontale
dimensioni. E’ anche usata per l’impostazione di valori.
(Horizontal scroll bar)
Barra di scorrimento Crea una barra di scorrimento pr muoversi all’interno dei form o liste di grandi
verticale
dimensioni. E’ anche usata per indicare la posizione in un range di valori Viene
(Vertical scroll bar)
aggiunta automaticamente quando il numero di righe conteneti dati supera la
13
Prof. Tombolini Gino
Casella Immagine
(Picture box)
Immagine
(Image)
Linea
(line)
Forma
(Shape)
Contenitore OLE
(OLE)
Timer
(timer)
Dati
(Data)
Finestre di dialogo
comuni
(Common Dialog Box)
Appunti di programmazione Visual Basic
dimensione del controllo.
Crea il contenitore per grafici e immagini nei formati BMP, ICO, WMF, JPG, GIF.
Permette di inserire anche immagini animate.
Visualizza immagini nei formati BMP, ICO, WMF, JPG, GIF. Può essere utilizzata
come pulsante di comando.
Disegna linee orizzontali, verticali o oblique. E’ utilizzato per suddividere
graficamente i contenuti di un form complesso in sottosezioni.
Mette nel form figure ipo rettangoli, cerchi ellissi.
Consente al programmatore di creare applicazioni che possono visualizzare e
modificare dati provenienti da altre applicazioni (disegni, fogli elettronici, grafici).
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.
Consente di visualizzare, modificare, aggiornare dati di un database esistente.
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
Impostano le dimensioni di un oggetto
Width (larghezza)
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.
14
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
App
eseguibile, controlla inoltre se è in esecuzione o meno un’istanza precedente dell’applicazione
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
Contiene informazioni relative agli errori di runtime
Err
Gestisce i form in base alla loro posizione sullo schermo e controlla in fase di esecuzione il puntatore
Screen
del mouse all’esterno dei form dell’applicazione
Viene utilizzato da rinviare l’output alla finestra Debug in fase di esecuzione
Debug
Consente di comunicare con una stampante di sistema ( inizialmente la stampante predefinita).
Printer
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
ClipBoard
per consentire all’utente di copiare, tagliare e incollare testo o immagini grafiche nell’applicazione in
esecuzione.
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
15
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
Ottava lezione – Operatori Booleani e struttura IF.
Ricordiamo brevemente i principali operatori logici
And (congiunzione), Or (disgiunzione), Not (negazione), Xor (exclusive Or)
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
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
EQV
IMP
espressioni sono equivalenti se sono uguali (entrambe false o
True Eqv True = True
True Imp True = True
entrambe vere); l'Imp corrisponde più o meno alla
True Eqv False = False
True Imp False = False
costruzione "se… allora" con l'uso di una condizione
False Eqv True = False
False Imp True = True
sufficiente ma non necessaria, ad esempio "se x>y, allora
False Eqv False = True
False Imp False = True
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
=
<
<=
>
>=
<>
Operatori in confronto
uguale
minore
minore uguale
maggiore
maggiore uguale
diverso
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.
16
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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 = "Pluto"
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:
17
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
CDec
Decimal
CInt
Integer
Da -1,79769313486232E308 a -4,94065645841247E-324 per valori negivi; da 4,94065645841247E-324 a
1,79769313486232E308 per quelli positivi
+/-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
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.
18
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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:
19
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
20
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
21
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
22
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
23
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
24
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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:
25
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
26
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
27
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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)
Instr([inizio,]stringa1,
[,confronto])
stringa2
InstrRev(stringa1,
stringa2[,
inizio[, confronto]])
Left(stringa,lunghezza)
Len(stringa)
Mid(stringa, inizio[,lunghezza])
Right(stringa,lunghezza)
UCase(stringa)
LTrim(stringa),
Trim(stringa)
StrComp()
RTrim(stringa)
Str
String(numcar,”car”)
Space(numcar)
Replace(source, find, replace,[
start], [count], [metodo])
Split( .. )
Join( …)
Filter ( … )
Format ( … )
Restituisce la stringa specificata come parametro con tutti i caratteri maiuscoli convertiti in minuscolo. Lascia
inalterati tutti gli altri caratteri.
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
Restituisce la posizione di un'occorrenza di una stringa inclusa in un'altra a partire dalla fine della stringa.
Restituisce una stringa composta da un numero di caratteri uguale alla lunghezza ed estratti dalla stringa
specificata come parametro, a partire da sinistra
Restituisce un intero che indica il numero di caratteri presenti in una stringa
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
Restituisce una stringa composta da un numero di caratteri uguale alla lunghezza ed estratti dalla stringa
specificata come parametro, a partire da destra
Restituisce la stringa specificata come parametro con tutti i caratteri minuscoli convertiti in maiuscolo. Lascia
inalterati tutti gli altri caratteri.
Consentono, rispettivamente, di ottenere una copia di una stringa senza spazi iniziali, spazi finali o senza spazi
iniziali e finali.
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
è una funzione molto importante che permette di convertire un valore numerico in una stringa di carattere
Permette di creare una stringa di caratteri “car” ripetuti per la lunghezza specificata da numcar
Restituisce una stringa costituita dal numero specificato di spazi.
Trova e sostituisce rapidamente sottostringhe
Trova ed isola tutti gli elementi delimitati in una stringa. Ritorna normalmente uno array
È il complementare di Split; accetta un array di stringhe ed un carattere delimitatore e ricrea la stringa originale
Analizza rapidamente un array, cercando una sottostringa e restituisce un altro array contenente solo gli
elementi che includono la sottostringa ricercata
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" restituisce False)
Vediamo qualche altro esempio:
ESPRESSIONE RISULTATO
"abc" Like "*abc"
True
"abc*" Like "*abc"
False
(l'asterisco a sinistra di Like è un carattere 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]:
28
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
"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.
29
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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 steptasto 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);
30
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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", vbOkOnly
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 trovare 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
31
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
32
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
33
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
34
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
35
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
36
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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 String)
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
37
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
38
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
39
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
40
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
41
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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 le 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 modifiche
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:
42
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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 file|*.*"
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.
43
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
Cerca
Trova…
Trova Successivo
NAME
mnuCerca
mnuTrova
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()
44
Prof. Tombolini Gino
Dim
Dim
Dim
Dim
Do
Appunti di programmazione Visual Basic
sTestoPuro(1) As String
lCount As Long
lInizio As Long
lFine As Long
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!
45
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
Dim ncontr As Integer
Private Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
controlli menù.
If Button = vbRightButton Then
Con il controllo menu si possono anche gestire in
PopupMenu menu_cmd1
End If
menù di scelta rapida (quelli visualizzati quando si fa
End Sub
Private Sub Command2_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
click destro su un controllo). Per visualizzare in Form
If Button = vbRightButton Then
un menù di scelta rapida bisogna utilizzare il metodo
PopupMenu menu_cmd2
End
If
PopupMenu. Il menù da utilizzare va creato con
End Sub
l’Editor di menù disattivando la proprietà Visible per
Private Sub fine_Click()
il controllo (il controllo non è visibile). Nelle routine
End
End Sub
di evento MouseUp e MouseDown va verificato se è
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = vbRightButton Then
stato usato il pulsante destro del mouse (il valore di
PopupMenu menu
Button, il primo argomento, deve essere uguale a
End If
End Sub
vbRightButton), ed in tal caso di chiamare il metodo
Private Sub help_Click()
PopupMenu.
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
46
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
Left Top Width Height
ForeColor BackColor
Font
Caption Text
Parent
Container
Enabled Visible
hWind
TabStop TabIndex
MousePointer MouseIcon
Tag
Value
Index
Appareance
Align
BorderStyle
ToolTip
Proprietà comuni
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.
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.
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.
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
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
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
Abilita o disabilita un controllo a gestire eventi (Enabled); rende visibile o invisibile un
controllo
È disponibile solo in fase di esecuzione ed è di sola lettura; restituisce il valore intero 32
bit che Windows usa internamente per identificare un controllo
Identifica l’ordine con cui viene spostato lo stato attivo dei controlli quando l’utente
preme TAB.
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( ).
Non ha particolare significato; può essere utilizzata come contenitore per un qualunque
dato correlato al controllo definito dal programmatore.
Il significato di questa proprietà varia da controllo a controllo ma comunque rappresenta
un valore numerico oppure booleano.
È la proprietà chiave della costruzione di array di controlli
Dà ai controlli un aspetto tridimensionale o piatto
Definisce l’allineamento del controllo rispetto al bordo della finestra che lo contiene.
Serve per eliminare il bordo intorno al controllo o per aggiungerlo
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
Refresh
SetFocus
ZOrder
Permette di cambiare la posizione di un controllo e le dimensioni
Formato Move Left, Top, Width, Height
Provoca il ridisegno del controllo
Sposta lo stato attivo o focus sul controllo
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
Change
Si verifica quando l’utente fa click con il pulsante sinistro del mouse sul controllo
Si verifica se il contenuto del controllo cambia; notare che su CheckBox e OptionButton
la variazione del controllo provoca un evento click
47
Prof. Tombolini Gino
GotFocus LostFocus
KeyDown KeyPress
KeyUp
MouseDown MouseUp
MouseMove
Appunti di programmazione Visual Basic
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
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.
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
Caption
ControlBox
MinButton MaxButton
WindowState
StartupPosition
Moveable
SkowInTaskbar
AutoRedraw
Imposta per il controllo la possibilità di ridimensionamento
Il testo che appare sulla barra del titolo
Importa la presenza del menù di sistema
In vostra presenza dei relativi pulsanti di riduzione a icona e ingrandimento
Imposta se visualizzare il Form a tutto schermo, ridotto a icona o normale
Utile che si vuol far apparire il form nel centro dello schermo
rendere la finestra non spostabile
Il form viene mostrato nella barra delle applicazioni se impostata a Truer
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
48
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
49
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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:
50
Prof. Tombolini Gino
AddItem
RemoveItem
Clear
Appunti di programmazione Visual Basic
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
Elimina una voce dall'elenco. Il formato è:
List1.RemoveItem <posizione>
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
Il cui effetto è già conosciuto
MouseDown
MouseUp
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
51
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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.
52
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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 .
53
Prof. Tombolini Gino
Appunti di programmazione Visual Basic
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
DriverName
Port
ColorMode
Orientation
PrinterQuality
PaperSize
PaperBin
Duplex
Copies
Zoom
Page
ScaleLeft
ScaleTop
ScaleWidth
ScaleHeight
ScaleMode
Il nome della stampante p resente nel Control Panel
Il nome del driver utilizzato dal device
La porta a cui è collegata la stampane (LPT1: )
Determina una stampante è a colori(1) o monocromatica(2)
Determina l'orientamento corrente della pagina
Restituisce la risoluzione corrente (1-draft, 2-Low, 3-Medium, 4-High)
Le dimensioni della carta
L'alimentatore della carta
La capacità di stampare entrambe le facciate di un foglio
Il numero di copie da stampare
Il fattore di zoom applicato durante la stampa
In fase di esecuzione ritorna il numero di pagina corrente
Fanno riferimento all'angolo superiore sinistro dell'area stampabile, il valore predefinito è 0
Restituiscono le coordinate nell'angolo inferiore destro dell'area stampabile
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
EndDoc
NewPage
KillDoc
Invia alla stampante il testo fornito come parametro
Informa l'oggetto Printer che tutti i dati sono stati inviati e che l'operazione di stampa effettiva può iniziare
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
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
54