Visual Basic
Visual Basic
Indice
Lezione 1 Introduzione a Visual Basic.
Lezione 2 Le variabili in Visual Basic.
Lezione 3 Le routine in Visual Basic
Lezione 4 Le funzioni in Visual Basic.
Lezione 5 Il primo programma in Visual Basic.
Lezione 6 Convenzioni.
Lezione 7 Interfaccia grafica e controlli standard.
Lezione 8 Operatori Booleani e struttura IF
Lezione 9 Nozioni avanzate sulle variabili.
Lezione 10 Vettori e matrici.
Lezione 11 Cicli For ... Next
Lezione 12 Cicli Do...Loop
Lezione 13 Struttura Select Case
Lezione 14 Stringhe
Lezione 15 Debug e gestione degli errori
Lezione 16 Gestione dei Files
Lezione 17 Gli Oggetti
Lezione 18 Studiare un'applicazione professionale : il Blocco Note di Windows
Lezione 19 I Menù
Lezione 20 Controlli: approfondimenti
Lezione 21 Date e orari
Lezione 22 L’oggetto Printer
1
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): 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:
3
Prof. Tombolini Gino Appunti di programmazione Visual Basic
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.:
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
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)
7
Prof. Tombolini Gino Appunti di programmazione Visual Basic
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
9
Prof. Tombolini Gino Appunti di programmazione Visual Basic
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
12
Prof. Tombolini Gino Appunti di programmazione Visual Basic
13
Prof. Tombolini Gino Appunti di programmazione Visual Basic
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.
App È un oggetto che consente di specificare il titolo dell’applicazione, il percorso ed il nome del file
eseguibile, controlla inoltre se è in esecuzione o meno un’istanza precedente dell’applicazione
Le proprietà principali dell’oggetto App sono:
• App.Path restituisce il percorso dell’applicazione
• App.Title restituisce il titolo dell’applicazione
• App.Helpfile restituisce il nome del file della guida in linea
• App.EXEName restituisce il nome del file eseguibile dell’applicazione
• App.LegalCopyright restituisce informazioni sul copyright
• App.Comments restituisce i commenti sull’applicazione
• App.ProductName restituisce il nome del prodotto
• App.Major e App.Minor restituiscono la versione del programma
• App.PrevIstance consente di verificare se è già in esecuzione un’altra istanza del programma
• App.hInstance fornisce un handle dell’applicazione.
Alcune di queste informazioni sono inserite dal finestra del progetto
Err Contiene informazioni relative agli errori di runtime
Screen Gestisce i form in base alla loro posizione sullo schermo e controlla in fase di esecuzione il puntatore
del mouse all’esterno dei form dell’applicazione
Debug Viene utilizzato da rinviare l’output alla finestra Debug in fase di esecuzione
Printer Consente di comunicare con una stampante di sistema ( inizialmente la stampante predefinita).
L’insieme Printers raccogliere informazioni sulle stampanti disponibili nel sistema
ClipBoard Gestisce il testo e le immagini grafiche negli appunti di Windows. È possibile utilizzare quest’oggetto
per consentire all’utente di copiare, tagliare e incollare testo o immagini grafiche nell’applicazione in
esecuzione.
Clipboard.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
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" Operatori in confronto
ElseIf strName = "Topolino" Then = uguale
frmProva.Show < minore
frmProva.lblName.Caption = "Minnie" <= minore uguale
ElseIf strName = "Pluto" Then > maggiore
frmProva.Show >= maggiore uguale
frmProva.lblName.Caption="Orazio" <> diverso
Else
frmProva.Hide
End If
All'interno di ogni blocco If…Then è possibile inserire qualunque istruzione, anche un'altra If…Then (si parla dei
cosiddetti blocchi annidati); ad esempio si potrebbe fare:
If intX > 10 Then
If intX > 100 Then
intY = intX / 2
Else
intY = intX + 10
End If
ElseIf intX > 5 Then
intY = 0
Else
bValue = True
End If
Le condizioni da valutare possono essere espressioni anche molto complesse, utilizzando gli operatori logici che
abbiamo visto nella lezione precedente. Nel caso di condizioni multiple (diversamente dal linguaggio C) Visual Basic le
valuta sempre tutte, e nel caso di controlli pesanti bisognerebbe tenerne conto, facendo in modo che vengano valutate
solo le espressioni strettamente necessarie.
I valori True e False in realtà non sono altro che numeri, e precisamente la parola chiave true corrisponde al valore -1 e
la parola chiave false corrisponde al valore 0. Più precisamente, un valore numerico viene interpreto da VB come true
se è diverso da 0, anche se il valore predefinito di true è -1, ed è interpretato come false quando è uguale a 0.
In VB esiste anche un particolare costrutto condizionale: IIF(condizione, ris_vero,ris_falso) che valuta la condizione e
ritorna ris_vero se la condizione è vera, ritorna ris_falso se è falsa. Esempio:
un lInizio = IIf(lFine > 1, lFine, 2)
Assegna a LInizio il valore di LFine se la condizione è vera, altrimenti gli assegna 2.
16
Prof. Tombolini Gino Appunti di programmazione Visual Basic
17
Prof. Tombolini Gino Appunti di programmazione Visual Basic
Tipo
Funzione Intervallo
Restituito
CBool Booleano Qualsiasi espressione numerica o stringa valida
CByte Byte Da 0 a 255
CCur Currency Da -922.337.203.685.477,5808 a 922.337.203.685.477,5807
CDate Date Qualsiasi espressione di da valida
CDbl Double Da -1,79769313486232E308 a -4,94065645841247E-324 per valori negivi; da 4,94065645841247E-324 a
1,79769313486232E308 per quelli positivi
CDec Decimal +/-79.228.162.514.264.337.593.543.950.335 per numeri con fattore di divisione zero, ovvero numeri senza decimali. Per i
numeri con 28 decimali l'intervallo è +/-7,9228162514264337593543950335. Il numero minatore possibile diverso da zero
è 0,0000000000000000000000000001
CInt Integer Da -32.768 a 32.767; le frazioni vengono arrotonde
CLng Long Da -2.147.483.648 a 2.147.483.647; le frazioni vengono arrotonde
CSng Single Da -3,402823E38 a -1,401298E-45 per valori negivi; da 1,401298E-45 a 3,402823E38 per valori positivi
CStr String I valori restituiti da CStr dipendono dall'argomento della funzione
CVar Variant Lo stesso intervallo di Double per valori numerici. Lo stesso intervallo di String per valori non numerici
Naturalmente il parametro passato a queste funzioni deve poter assumere un valore che rientra nell'intervallo specifico
del tipo restituito: ad esempio non è possibile scrivere:
CInt(100000.45)
perché il valore 100000 è superiore al massimo consentito per un Integer.
Operatori matematici
Visual Basic supporta tutti e quattro gli operatori matematici: quando combina due valori di diverso tipo applica
automaticamente la coercision (o tipizzazione forzata) cioè converte il cibo più semplice in quello più completo (ad
esempio da Integer a Long).
/ operatore di divisione : converte sempre il risultato in Double, quindi lo converte in base al tipo di risultato.
\ effettua la divisione intera eliminando la parte decimale del quoziente.
^ operatore esponenziale
Mod estrae il resto di una divisione tra valori al numero intero.
Operatori bit-wise (di bit)
Permettono di operare su singoli bit degli operandi:
AND permette di destare uno o più bit di un numero
OR permette di impostare uno o più bit di un numero
NOT inverte i bit di un operando
XOR calcola l’ or esclusivo tra due operandi.
Operatori di arrotondamento
La funzione Int tronca un numero all’intero minore o uguale al suo argomento
Print Int(1.2) stampa 1
Print Int(-1.2) stampa -2
Operatori di conversione
Per convertire una stringa in un numero si può utilizzare la funzione Val( )
Per convertire un numero da decimale a es decimale o ottale esistono le funzioni Hex( ) e Oct( )
Funzione di formattazione
La funzione Format( ) è estremamente complessa e permette di soddisfare gran parte dei requisiti di formattazione
richiesti.
Format(espressione, [Formato], …)
Di solito bastano i primi due parametri, gli altri servono normalmente le date. Stringa riformato può essere fornita sia
tramite nomi (General Number, Standard, Percent, Scienific, Yes/no, True/False,On/Off), sia tramite formati
personalizzati. Esempi di formati personalizzati:
“#,###.00” due cifre decimali e separatori delle migliaia
“#.#%” valori percentuali
“#.###E+” notazione scientifica con un segno per l’esponente
“#.###E-“ notazione scientifica con un segno solo per l’esponente negativo
“##,###.00;( ##,###.00); ;N/A” due cifre decimali per i numeri positivi, negativi tra parentesi, nulla per 0, N/A per i
valori Null.
18
Prof. Tombolini Gino Appunti di programmazione Visual Basic
19
Prof. Tombolini Gino Appunti di programmazione Visual Basic
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
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
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
26
Prof. Tombolini Gino Appunti di programmazione Visual Basic
27
Prof. Tombolini Gino Appunti di programmazione Visual Basic
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
31
Prof. Tombolini Gino Appunti di programmazione Visual Basic
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
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
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
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
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 NAME
Cerca mnuCerca
Trova… mnuTrova
Trova Successivo mnuTrovaAncora
mnuCerca è quello che compare sulla barra dei menù, gli altri sono sottomenù. Per permettere all'utente di indicare la
parola da cercare basterebbe un banale inputbox, ma vale la pena costruire una finestra un po' più sofisticata, con un
textbox (txtTrova) per scrivere la stringa da cercare, un pulsante per avviare la ricerca (cmdTrova), uno per chiudere la
finestra (cmdChiudi), tre optionbutton (optSu, optGiu, optTutto) per scegliere la direzione di ricerca, un checkbox per
abilitare la ricerca case sensitive (chkCaseSens). Il form si può chiamare frmTrova. Il codice di ricerca della stringa sarà
tutto racchiuso nel nuovo form appena creato, cosicché il codice del menù "Cerca" sarà molto semplice: la voce
mnuTrova dovrà soltanto richiamare la finestra frmTrova:
Private Sub mnuTrova_Click()
frmTrova.Show vbModal
End Sub
La costante vbModal indica che il form frmTrova è modale (si dice anche "a scelta obbligatoria") rispetto al form che lo
richiama (frmNotePad), cioè non è possibile tornare al form originale prima di aver compiuto qualche scelta (anche la
sola chiusura) con la finestra in primo piano. La voce mnuTrovaAncora dovrà invece richiamare la routine del pulsante
cmdTrova, che scriveremo in seguito:
Private Sub mnuTrovaAncora_Click()
frmTrova.cmdTrova_Click
End Sub
Per fare ciò però è necessario che la routine cmdTrova_Click sia pubblica e quindi visibile anche da frmNotePad: perciò
occorre sostituire "Private" con "Public" nella dichiarazione dell'evento Click:
Public Sub cmdTrova_Click()
End Sub
Non è questa un'operazione molto raccomandabile, perché va a modificare delle dichiarazioni generate direttamente
dall'IDE di Visual Basic; in realtà non ha molto senso che la routine di un evento sia "pubblica", perché la generazione
dell'evento avviene privatamente rispetto al form che contiene il controllo a cui l'evento si riferisce. Richiamare la
routine non corrisponde propriamente alla generazione dell'evento, anche se in buona sostanza le due cose sono uguali.
In alternativa, è possibile non modificare la dichiarazione dell'evento Click e impostare a True il valore del pulsante
cmdTrova:
Private Sub mnuTrovaAncora_Click()
frmTrova.cmdTrova.Value=True
End Sub
Possiamo ora dedicarci al codice del form frmTrova, cominciando dalla cosa più semplice: la chiusura del form:
Private Sub cmdChiudi_Click()
Me.Hide
End Sub
Il form viene solo nascosto, e non completamente scaricato, perché è sempre possibile continuare la ricerca della stringa
specificata usando il menù mnuTrovaAncora, che deve poter accedere alla proprietà Text di txtTrova: se il form venisse
scaricato, il contenuto di txtTrova andrebbe perso. In alternativa, si può memorizzare il contenuto del textbox in una
variabile pubblica di frmNotePad, il che permetterebbe comodamente di scaricare frmTrova.
All'apertura del form, sarebbe bene che il pulsante cmdTrova sia disabilitato, perché il txtTrova è vuoto: se fosse
abilitato e l'utente lo premesse subito, bisognerebbe cercare una stringa nulla, o visualizzare un messaggio di errore che
avverta di indicare la stringa da cercare; è possibile evitare tutto ciò semplicemente disabilitando per default (ovvero in
fase di progettazione) il pulsante, e abilitarlo quando il txtTrova contiene qualche carattere, sfruttando l'evento Change:
Private Sub txtTrova_Change()
If Len(txtTrova.Text) Then
cmdTrova.Enabled = True
Else
cmdTrova.Enabled = False
End If
End Sub
Prima di scrivere la routine di ricerca, è opportuno specificare l'istruzione Option Compare Binary nella sezione delle
dichiarazioni del form: questo perché è semplice impedire un confronto case sensitive usando le funzioni Lcase o
Ucase, ma è complicato tornare a un confronto case sensitive con l'operatore Like se l'impostazione di default è Option
Compare Text.
Veniamo ora alla routine cmdTrova_Click: volendo scrivere una routine abilitata alla ricerca con caratteri jolly (per
semplicità gli stessi usati dall'operatore like: *, ?, #), è opportuno procedere in questo modo: data l'impossibilità di
cercare direttamente una stringa che contenga caratteri jolly, occorre suddividere il testo cercato in più parti, isolando il
testo "puro" dai caratteri jolly. Ad es., se l'utente vuole cercare "abc*", non bisognerà trovare esattamente "abc*", bensì
"abc": qualunque stringa cominci con "abc" soddisferà i requisiti indicati dall'utente. Più complesso è il caso di una
stringa del tipo "##a*123??": in questo caso bisognerà cercare la lettera "a", oppure i numeri "123", e successivamente
verificare che i caratteri circostanti corrispondano al criterio indicato. È ovvio che specificare soltanto "*" o "?" come
testo da cercare non ha molto senso.
Come prima cosa, occorre eliminare gli asterischi iniziali e finali: cercare "*pippo*" è del tutto equivalente a cercare
"pippo", ma il secondo caso è per noi molto più facile da trattare:
Public Sub cmdTrova_Click()
44
Prof. Tombolini Gino Appunti di programmazione Visual Basic
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
46
Prof. Tombolini Gino Appunti di programmazione Visual Basic
Proprietà comuni
Left Top Width Height Riguardano il contenitore del controllo: per il form è lo schermo mentre per i controlli in
generale è il form stesso. Top e Left determinano la posizione del controllo rispetto al
contenitore; Width e Height ne definiscono le dimensioni. L’unità di misura è il twip ma
possono essere utilizzate altre unità di misura impostando la proprietà ScaleMode del
contenitore.
ForeColor BackColor Influenzano il colore del testo e il colore di sfondo. Il comportamento dipende da altre
proprietà come BackStyle per le etichette e Style per i CommandButton. Per specificare
il colore si possono usare o costanti simboliche (vbRed. ..) o numeriche in formato
esadecimale (&Hffff00) nella logica RGB. È possibile usare anche la funzione RGB(
red,green,blue) specificando i valori (0-255) per i tre colori componenti.
Font Specifica il font di caratteri da usare per visualizzare stringhe di testo. È esso stesso un
oggetto che espone le proprietà Name, Size, Bold, Italic, Underline, Strikethrought.
Caption Text Rappresentano la stringa di caratteri che appare all’interno di un controllo.
Normalmente Caption riguarda controlli che non permettono di modificare tale stringa
al contrario della proprietà Text
Parent Disponibile solo in fase di esecuzione restituisce riferimento al form che ospita il
controllo; è di sola lettura quindi non è possibile spostare un controllo da un form ad un
altro
Container Disponibile solo in fase di esecuzione restituisce riferimento al contenitore che ospita il
controllo; è di lettura/scrittura quindi è possibile spostare un controllo da un contenitore
ad un altro. Occorre usare il comando set: Set Text1.Container=Picture1 sposta Text1
nel contenitore Picture1
Enabled Visible Abilita o disabilita un controllo a gestire eventi (Enabled); rende visibile o invisibile un
controllo
hWind È disponibile solo in fase di esecuzione ed è di sola lettura; restituisce il valore intero 32
bit che Windows usa internamente per identificare un controllo
TabStop TabIndex Identifica l’ordine con cui viene spostato lo stato attivo dei controlli quando l’utente
preme TAB.
MousePointer MouseIcon Influenzano la forma del cursore del mouse quando passa sopra un controllo.
MouseIcon serve a creare un mouse personalizzato quando MousePointer è impostato
99; per caricare l’icona per il mouse si usa l’istruzione Load( ).
Tag Non ha particolare significato; può essere utilizzata come contenitore per un qualunque
dato correlato al controllo definito dal programmatore.
Value Il significato di questa proprietà varia da controllo a controllo ma comunque rappresenta
un valore numerico oppure booleano.
Index È la proprietà chiave della costruzione di array di controlli
Appareance Dà ai controlli un aspetto tridimensionale o piatto
Align Definisce l’allineamento del controllo rispetto al bordo della finestra che lo contiene.
BorderStyle Serve per eliminare il bordo intorno al controllo o per aggiungerlo
ToolTip sono piccole caselle di testo normalmente gialle che appaiono in molte applicazioni
Windows quando posizionare il puntatore del mouse su un controllo
Metodi comuni
Eventi comuni
Click DoubleClick Si verifica quando l’utente fa click con il pulsante sinistro del mouse sul controllo
Change Si verifica se il contenuto del controllo cambia; notare che su CheckBox e OptionButton
la variazione del controllo provoca un evento click
47
Prof. Tombolini Gino Appunti di programmazione Visual Basic
GotFocus LostFocus Si verificano quando il controllo riceve lo stato attivo o lo perde. Spesso è usato per il
controllo di un campo e la notifica di un valore non corretto: per tali casi è meglio usare
l’evento Validate e la proprietà CausesValidation
KeyDown KeyPress Si è video quando l’utente preme un tasto mentre un controllo riceve l’input. Prima si
KeyUp verifica KeyDown, quindi KeyPress e infine KeyUp. Con KeyPress è possibile
controllare e anche scatare il valore del tasto premuto impostandolo a 0 nella relativa
routine di risposta. KeyDown KeyUp ricevono due parametri KeyCod e Shift: il primo è
il codice fisico (in sola lettura) del tasto premuto, il secondo indica lo stato dei tasti Ctrl,
Maiusc e Alt. Se la proprietà KeyPreview del Form contenitore del controllo è True,
questi eventi vengono prima inviati al form poi al controllo.
MouseDown MouseUp Verificano rispettivamente quando viene fatto un clic con il pulsante del mouse, quando
MouseMove 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
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
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
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.
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.
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
53
Prof. Tombolini Gino Appunti di programmazione Visual Basic
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