Guida introduttiva a Visual Basic.NET

Transcript

Guida introduttiva a Visual Basic.NET
Visual Basic .NET: un nuovo linguaggio di programmazione
Visual Basic .NET è uno dei linguaggi che fa parte della suite di
sviluppo Visual Studio .NET: con essa Microsoft vuole segnare
una svolta nel mondo della programmazione. E pare che le
prerogative ci siano tutte: di questa famiglia di prodotti fa parte
anche C#, il nuovo linguaggio che, secondo Microsoft, riesce a
coniugare la semplicità di Visual Basic con la potenza propria del
C++. La trattazione delle novità architetturali introdotte da
Microsoft con Visual Studio .NET, come il Framework .NET, esula
dagli obiettivi di questo corso, che si propone invece di analizzare
nello specifico Visual Basic .NET: esso introduce talmente tanti
cambiamenti rispetto alle versioni precedenti che da molti, e non a
torto, è considerato un nuovo linguaggio di programmazione
piuttosto che un semplice aggiornamento.
Ora finalmente Visual Basic è un linguaggio di programmazione
orientato agli oggetti: ereditarietà, polimorfismo e overloading non sono più prerogative dei programmatori Java e C++. I
tipi di dato sono stati modificati, per renderli conformi alle definizioni usate negli altri linguaggi; ad esempio, il tipo di dato
Long è stato sostituito da Integer (il vecchio Integer ora è diventato Short). Anche per quanto riguarda la gestione degli errori,
VB si è ispirato a Java e C++, introducendo il costrutto Try… Catch… Finally.
Un'altra importante novità è il supporto nativo per la creazione e la gestione dei thread. La casella degli strumenti di VB,
inoltre, è stata ampliata includendo numerosi nuovi controlli utili, tra cui uno che permette di inserire un'icona nella System
Tray, vicino all'orologio. I controlli per visualizzare le finestre di dialogo comuni e gli elementi dell'interfaccia di Windows,
come la Toolbar, la Statusbar e la Listview, fanno ora parte dei componenti standard, cioè sono utilizzabili senza dover
ricorrere a controlli OCX aggiuntivi. La nuova versione di Visual Basic consente anche di creare applicazioni console, cioè
applicazioni eseguibili dalla riga di comando di MS-DOS.
Come conseguenza di tutte queste innovazioni (e di molte altre che verranno analizzate in seguito), i progetti realizzati con le
versioni precedenti di VB sono incompatibili con VB .NET, cioè non possono essere aperti con quest'ultimo se non
utilizzando una procedura di conversione che, però, nella maggior parte dei casi richiede anche degli interventi manuali. Anche
il formato dei file, infatti, è stato modificato: ora tutti i file che contengono il codice sorgente hanno estensione .vb. Per tale
motivo non è consigliabile cercare di aggiornare i propri programmi a VB .NET; al contrario, è conveniente utilizzare questo
linguaggio per la creazione dei nuovi software.
In questo corso, rivolto a chi ha già una minima conoscenza di Visual Basic, verranno analizzate ed esemplificate le
principali novità di Visual Basic .NET, soprattutto rispetto alle versioni precedenti; non verranno invece trattate le nozioni di
base, come il concetto di tipo di dato, la differenza tra funzioni e procedure, le strutture iterative, ecc. che hanno lo stesso
significato che avevano nelle precedenti versioni di Visual Basic. Per maggiori informazioni su questi argomenti si rimanda
pertanto al corso su Visual Basic.
I cambiamenti nei tipi di dato e nelle dichiarazioni
Uno dei cambiamenti più evidenti in Visual Basic .NET, rispetto alle versioni precedenti, riguarda i tipi di dato. Tale modifica
si è resa necessaria per rendere i tipi di dato di VB .NET formalmente uguali a quelli utilizzati in C# e in C++ (gli altri due
linguaggi "principi" di Visual Studio .NET).
Il tipo di dato Long è stato sostituito da Integer, che quindi ora è usato per la rappresentazione di numeri interi a 32 bit; il
vecchio Integer di VB6 e delle versioni precedenti, usato per i numeri a 16 bit, è diventato Short. In VB .NET il tipo Long
serve per rappresentare i numeri a 64 bit. Comunque, per dichiarare questi tipi di dato, è possibile utilizzare anche i nomi con
cui sono identificati all'interno del framework: invece di Short di può usare Int16, invece di Integer Int32 e al posto di Long
Int64. Riassumendo, ad esempio:
Visual Basic 6
Visual Basic .NET
Dim I As Integer
Dim I As Short
oppure
Dim I As Int16
Dim L As Long
Dim L As Integer
oppure
Dim L As Int32
http://guidepc.altervista.org
Relativamente alle espressioni booleane, bisogna evidenziare una importante novità. Utilizzando l'operatore Or tra due
espressioni logiche: ad esempio A > 0 Or B = 5, esse vengono sempre controllate entrambe, anche se, in realtà, nel caso in cui
A > 0 sia vera, non sarebbe necessario fare il controllo sulla B, dal momento che il risultato di tutta l'espressione sarà
comunque True.
Per sopperire a tale mancanza, è stato introdotto un nuovo operatore, OrElse: utilizzando quest'ultimo, A > 0 OrElse B = 5 , se
la prima condizione è vera la seconda non viene valutata.
Analogamente, per quanto riguarda l'And, l'operatore AndAlso evita il controllo sulla seconda condizione se la prima è falsa,
poiché il risultato finale sarà sempre False.
Le stringhe a lunghezza fis sa non sono più supportate nel linguaggio. Non è quindi più possibile scrivere una dichiarazione
come la seguente:
Dim S As String * 10
La nuova versione del linguaggio introduce delle novità anche per quanto riguarda l'area di validità delle variabili: ora le
variabili sono locali rispetto alla porzione di codice in cui vengono definite. Se, ad esempio, si dichiara una variabile all'interno
di un ciclo For, essa non sarà più utilizzabile una volta usciti dal ciclo stesso. Si verifica quindi la seguente situazione:
Dim I As Short
For I = 0 To 10
Dim N As Integer
....
Next I
MsgBox("Il valore di N è: " & N & ".")
'Errato: la variabile N non è più utilizzabile.
Il tipo Currency è stato eliminato; al suo posto è possibile usare il nuovo tipo Decimal per i calcoli monetari e per calcoli a
virgola fissa in cui la precisione riveste un'importanza particolare.
Il tipo di dati Variant non esiste più: al suo posto è necessario usare il tipo Object, che comunque conserva tutte le
caratteristiche del Variant, quindi può essere utilizzato per memorizzare qualsiasi tipo di dato primitivo, nonché Empty, Null,
Nothing, oppure come puntatore ad un oggetto.
Anche la gestione degli array è cambiata: ora gli array possono essere solo a base 0; non è quindi più possibile specificarne il
limite inferiore. Un effetto collaterale di questa modifica è che l'istruzione Option Base 1 non esiste più.
I tipi definiti dall'utente ora non si creano più con il costrutto Type; al suo posto è stata introdotta la parola chiave Structure.
Ogni elemento all'interno della struttura deve essere dichiarato con Dim, Event, Friend, Private, o Public (ritorneremo su
queste parole chiave più avanti, quando parleremo delle classi in VB .NET). Ad esempio:
Visual Basic 6
Public Type IMPIEGATO
Nome As String
Matricola As String
End Type
Visual Basic .NET
Public Structure IMPIEGATO
Dim Nome As String
Dim Matricola As String
End Structure
Una novità significativa introdotta dalle Structure di VB .NET è la possibilità di definire Sub, Function e Property
all'interno di una struttura. Riprendendo l'esempio sopra riportato, è possibile aggiungere una Sub alla struttura IMPIEGATO
che visualizzi una finestra contente le informazioni contenute nella struttura stessa:
Public Structure IMPIEGATO
Dim Nome As String
Dim Matricola As String
Sub Informazioni()
'Visualizza una MessageBox che contiene le informazioni contenute nella
struttura.
MsgBox("Nome dell'impiegato: " & Nome & vbCrLf & "Matricola: " & Matricola,
MsgBoxStyle.Information)
End Sub
http://guidepc.altervista.org
End Structure
Un utilizzo di questa struttura è il seguente:
Dim I As IMPIEGATO
With I
.Nome = "Marco Minerva"
.Matricola = "232440"
.Informazioni()
'Richiama la Sub definita nella struttura.
End With
Altre novità importanti sono state introdotte da VB .NET relativamente alla dichiarazione di costanti, variabili, procedure e
funzioni. Innanzi tutto, è finalmente possibile inizializzare una variabile nella sua dichiarazione. Ad esempio, sono valide le
dichiarazioni seguenti:
Dim Punti As Short = 10
Dim Nome As String = "Pippo"
Nelle precedenti versioni di Visual Basic, se non diversamente specificato, i parametri di una funzione o di una procedura
venivano passati per riferimento; in pratica, la parola chiave ByRef era predefinita. In VB .NET, invece, per default gli
argomenti sono passati ad una funzione per valore (ByVal ); utilizzando l'editor di Visual Studio .NET, se nella dichiarazione
di una Sub o di una Function non si specifica altrimenti, davanti ai nomi degli argomenti verrà automaticamente aggiunto
ByVal.
Infine, se un parametro di una funzione è dichiarato come Optional, è obbligatorio specificare il valore che tale parametro
assumerà nel caso in cui non venga specificato quando si richiama la funzione stessa. Ad esempio:
Visual Basic 6
Visual Basic .NET
Private Sub DoSomething(ByVal frm
Private Sub DoSomething(frm
As Form, Optional ByVal I As Short =
As Form, Optional I As Integer)
-1)
…
…
End Sub
End Sub
Un'ultima nota riguarda il modo di restituire un valore di una Function. Nelle precedenti versioni di Visual Basic, per
restituire un valore era necessario scrivere <nome funzione> = valore. In VB .NET, oltre a questo metodo, è stato aggiunta la
parola chiave Return, analoga a quanto già esistente in C e in Java. Queste due funzioni sono quindi equivalenti:
Private Function
AreaTriangolo(ByVal Base As Double, ByVal Altezza As Double) As Double
AreaTriangolo = (Base * Altezza) / 2
End Function
Private Function AreaTriangolo(ByVal Base As Double, ByVal Altezza As Double) As Double
End Function
Return (Base * Altezza) / 2
L'unica differenza è che, eseguendo l'istruzione Return, si uscirà automaticamente della funzione. In altre parole, l'istruzione
Return dell'esempio precedente equivale a:
AreaTriangolo = (Base * Altezza) / 2
Exit Function
Utilizzo di classi in VB .NET
Alla base di ogni linguaggio di programmazione orientato agli oggetti c'è il concetto di classe. Chi ha già usato le versioni
precedenti di Visual Basic assocerà immediatamente il concetto di classe a quello di modulo di classe. In effetti, le classi di VB
.NET mantengono tutte le caratteristiche dei moduli di classe, ma ne aggiungono numerose altre (come verrà evidenziato
meglio nelle prossime Lezioni). In prima approssimazione, una classe è una collezione di variabili, metodi e proprietà; è
possibile creare una classe usando il costrutto Class:
http://guidepc.altervista.org
Class Test
Dim Nome As string
'Altre variabili.
Public Sub VisualizzaNome()
'...
End Sub
End Class
Una classe è anche un tipo, quindi può essere assegnata ad una variabile:
Dim Prova As New Test() 'La variabile Prova contiene un'istanza della classe Test. E' da notare l'uso della parola chiave New,
necessaria perché la variabile che stiamo definendo si riferisce ad un oggetto (come in Visual Basic 6, infatti, le istanze degli
oggetti sono create con New). Fatto questo, è possibile utilizzare la classe utilizzando la comune sintassi di Visual Basic. Ad
esempio:
Prova.VisualizzaNome()
L'evento Iniziatialize, generato quando si crea un'istanza della classe, non esiste più: al suo posto è possibile definire un
costruttore della classe, cioè un metodo che viene automaticamente richiamato quando si crea un'istanza della classe stessa;
una delle caratteristiche più importanti del costruttore è che esso consente di specificare le proprietà iniziali della classe (in
questo senso è più versatile dell'evento Initialize). Il costruttore è una particolare Sub il cui nome deve obbligatoriamente
essere New. Riprendendo l'esempio precedente, vediamo come creare un costruttore per la classe Test:
Class Test
Dim Nome As string
'Altre variabili.
Sub New(ByVal strNome As String)
'Imposta le proprietà iniziali.
Nome = strNome
End Sub
Public Sub VisualizzaNome()
'...
End Sub
End Class
Come possiamo vedere, la routine New prende come argomento la variabile strNome e la assegna alla sua variabile interna
Nome. E' possibile definire un oggetto di tipo Test utilizzando il suo costruttore:
Dim Prova As New Test("Marco")
Mentre le Sub e le Function sono rimaste sostanzialmente immutate, la creazione di proprietà di una classe è diversa rispetto
alle versioni precedenti. In VB6 si usavano due metodi, Property Set e Property Let, rispettivamente per assegnare e
recuperare il valore di una proprietà. In VB .NET, invece, è stato tutto riunito in un unico metodo, che include sia il codice per
recuperare sia quello per impostare il valore di una proprietà; ad esempio:
Public Property NomeUtente() As String
Get
Return Nome
End Get
Set(ByVal Value As String)
Nome = Value
End Set
End Property
Come si vede, questa proprietà è composta da due parti: il blocco Get, delimitato da Get… End Get, e il blocco Set (Set…
End Set). A parte queste differenze sintattiche, il comportamento dei due blocchi è quello che ci si aspetta: con Get si
restituisce il valore della proprietà, mentre con Set si specifica un valore per essa. L'utilizzo di una proprietà così creata rimane
lo stesso.
Nella definizione di una routine, oltre a Public o Private, in VB .NET è possibile usare, tra le altre, la nuova parola chiave
Protected ; per maggiori informazioni sulle altre parole chiave si consiglia di consultare la Guida in linea di Visual Basic
.NET. Definendo una routine di una classe come Public, essa sarà visibile da tutti le istanze di quella classe; se, invece, si usa
la parola chiave Private, tale routine non sarà utilizzabile all'esterno della classe. Ad esempio:
http://guidepc.altervista.org
Public Class Test
'...
'...
Public Sub VisualizzaData()
'...
End Sub
Private Function Formatta() As String
'...
End Function
End Class
Dim Prova As New Test()
Prova.VisualizzaData() 'Corretto.
Prova.Formatta() 'Errato: non è possibile accedere alla funzione Formatta, perché è
Private.
Infine, dichiarando una routine della classe Test come Protected, essa sarà visibile a tutte le classi che ereditano da Test (questo
concetto verrà chiarito meglio nelle prossime Lezioni, quando si affronteranno i concetti di ereditarietà, polimorfismo e
overloading); questa routine non potrà però essere utilizzata dalle istanze della classe. In pratica, Protected equivale a Private,
con la differenza che il metodo è visibile anche alle classi che ereditano da quella principale.
Più classi possono essere raggruppate in un unico Namespace. Ad esempio:
Namespace Test
Class Test1
'...
End Class
Class Test2
'...
End Class
End Namespace
Con questo costrutto, per dichiarare un oggetto di tipo Test1 è necessario scrivere, ad esempio:
Dim Prova1 As New Test.Test1()
Analogamente, per oggetti di tipo Test2:
Dim Prova2 As New Test.Test2()
Fatto questo, è possibile accedere ai metodi ed alle proprietà delle classi Test1 e Test2 nel modo consueto.
I namespace sono sempre Public, mentre i componenti all'interno possono essere Public o Friend (impostazioni predefinita).
E' possibile definire un namespace dentro un altro, ad esempio:
Namespace N1
Namespace N2
Class Test1
'...
End Class
Class Test2
'...
End Class
End Namespace
End Namespace
Dim Prova1 As New N1.N2.Test1()
Dim Prova2 As New N1.N2.Test2()
Tutte le classi che compongono la piattaforma .NET sono organizzate in namespace. Ad esempio, la classe Form, da cui
ereditano tutti i Windows form (argomento della Lezione 8) è raggiungibile nel namespace Windows.System.Forms.Form.
A questo punto si hanno tutti gli strumenti necessari per analizzare le caratteristiche di VB .NET che ne fanno un linguaggio di
programmazione orientato agli oggetti: nelle prossime Lezioni parleremo di ereditarietà, polimorfismo ed overloading.
http://guidepc.altervista.org
Ereditarietà
Abbiamo detto più volte che Visual Basic .NET è un linguaggio di programmazione orientato agli oggetti. Avendo bene in
mente il concetto di classe, analizziamo le caratteristiche fondamentali di questo paradigma di programmazione: ereditarietà,
polimorfismo ed overloading. Si definisce ereditarietà la possibilità per una classe (detta classe derivata) di derivare da
un'altra (la classe base), in modo tale che il tipo derivato possa utilizzare le variabili, i metodi, ecc. del tipo base. La parola
chiave utilizzata per creare una relazione di eredità è Inherits; questa istruzione deve obbligatoriamente essere sulla prima riga
di codice dopo la definizione della classe. Si consideri l'esempio seguente:
Public Class Persona
Protected sNome As String
Private iTelefono As Integer
'...
Public Property Nome() As String
Get
Return sNome
End Get
Set(ByVal Value As String)
sNome = Value
End Set
End Property
End Class
Public Class Impiegato
Inherits Persona
Private sMatricola As String
'...
Public Property Matricola() As String
Get
Return sMatricola
End Get
Set(ByVal Value As String)
sMatricola = Value
End Set
End Property
End Class
In questo stralcio di codice la classe Impiegato eredita dalla classe Persona: questo significa che nella classe Impiegato è
possibile utilizzare tutto ciò che in Persona è stato definito come Public, Protected o Friend, sia esso una variabile, una Sub,
una Function o una Property. Ad esempio, all'interno di Impiegato è possibile utilizzare sia la variabile sNome sia la
proprietà Nome, mentre la variabile iTelefono non è visibile.
Provando a dichiarare oggetti di tipo Persona e Impiegato, si ottiene quanto segue:
Dim Imp As New Impiegato()
Imp.Matricola = "389321" 'Corretto: Matricola è una property della classe impiegato.
Imp.Nome = "Marco" 'Corretto: Nome è una property che la classe Impiegato eredita da
Persona.
Dim Pers As New Persona()
Pers.Nome() = "Marco" 'Corretto: Matricola è una property della classe Persona.
Pers.Matricola = "389321" 'Errato: la property Matricola non è visibile alla classe
Persona.
Se ora commentia mo la riga Inherits Persona nella classe Impiegato, otterremo un messaggio di errore relativo all'istruzione
Imp.Nome = "Marco", dal momento che abbiamo eliminato l'ereditarietà.
Polimorfismo
l termina polimorfismo indica la possibilità di definire all'interno di più classi metodi e proprietà con lo stesso nome, in modo
che, ad esempio, una classe derivata possa ridefinire un metodo della classe base con lo stesso nome. Vediamo subito un
esempio di quanto detto:
http://guidepc.altervista.org
Public Class ProdottoBase
Private Const dIVA As Decimal = 0.2
'...
Public Overridable Function IVA(ByVal Prezzo As Decimal) As Decimal
'Calcola l'IVA sul prezzo specificato.
Return (Prezzo * dIVA)
End Function
End Class
Public Class AltroProdotto
Inherits ProdottoBase
Private Const dIVA As Decimal = 0.18
Private Const Tassa As Decimal = 0.1 'Tassa sul prodotto.
'...
Public Overrides Function IVA(ByVal Prezzo As Decimal) As Decimal
'Calcola l'IVA sul prezzo specificato e aggiunge la tassa sul prodotto.
Return (Prezzo * dIVA) + (Prezzo * Tassa)
End Function
End Class
Notiamo che la Function IVA è definita sia nella classe ProdottoBase sia nella classe AltroProdotto, che eredita da
ProdottoBase. Il comportamento della funzione, tuttavia, è diverso, dal momento che in AltroProdotto all'IVA viene aggiunta
una tassa. A seconda che si dichiari un oggetto di tipo ProdottoBase o di tipo AltroProdotto, verrà richiamata la funzione IVA
corrispondente.
Per fare questo abbiamo usato il polimorfismo; la funzione IVA nella classe base è stata dichiarata usando la parola chiave
Overridable: con essa si indica a Visual Basic che è possibile avere un'altra definizione per la stessa funzione in una classe
derivata. In AltroProdotto, infatti, IVA è stata definita specificando Overrides: in tal modo si dice che tale funzione
sovrascrive un metodo con lo stesso nome che è stato definito nella classe base.
C'è anche un altro modo per sfruttare il polimorfismo, ovvero usando la parola chiave Shadows che, letteralmente, nasconde
una definizione della classe base con lo stesso nome. L'esempio sopra riportato, usando Shadows, diventa:
Public Class ProdottoBase
Public Function IVA(ByVal Prezzo As Decimal) As Decimal
'…
End Function
End Class
Public Class AltroProdotto
Inherits ProdottoBase
Public Shadows Function IVA(ByVal Prezzo As Decimal) As Decimal
'…
End Function
End Class
Come si vede, nella classe base la parola chiave Overridable è sparita, mentre in AltroProdotto la Function IVA è preceduta
da Shadows .
E' importante notare che, usando la coppia Overridable e Overrides, il metodo che sovrascrive una routine della classe base
deve avere non solo lo stesso nome, ma anche lo stesso numero di argomenti e dello stesso tipo. Invece, usando Shadows, è
possibile ridefinire un metodo modificandone il tipo, il numero di argomenti, ecc; con Shadows si può addirittura nascondere
una variabile della classe base con un intero metodo nella classe derivata.
Questa rapida panoramica sul polimorfismo non può coprire tutti gli aspetti della tematica, per approfondire i quali si rimanda
alla Guida in linea. I concetti forniti sono comunque più che sufficienti per utilizzare con successo il polimorfismo nei proprio
programmi.
Strettamente collegato con il polimorfismo è l'overloadi ng, altra importante caratteristica dei linguaggi di programmazione
orientati agli oggetti, che sarà discussa nella prossima Lezione.
http://guidepc.altervista.org
Overloading
Overloading L'overloading, letteralmente sovraccaricamento, è la possibilità di definire più versioni di una procedura,
utilizzando lo stesso nome ma un numero e/o un tipo diverso di argomenti: in fase di esecuzione, sulla base degli argomenti
effettivamente passati alla routine, verrà richiamata la procedura corretta; nella Guida in linea di Visual Basic sono specificati
con precisione i passi che il compilatore esegue per risolvere l'overloading, cioè per determinare qual è la routine corretta da
richiamare. Cerchiamo con un esempio di capire come funziona l'overloading:
Public Class Test
'...
Public Sub Prova(ByVal Nome As String)
MsgBox("Il nome specificato è: " & Nome & ".")
End Sub
Public Sub Prova(ByVal Numero As Integer)
MsgBox("Il numero specificato è: " & Numero & ".")
End Sub
End Class
Le due definizioni della Sub Prova differiscono per il tipo dell'argomento: String nel primo caso, Integer nel secondo. Se ora
creiamo un'istanza della classe e proviamo a richiamare la routine Prova, otteniamo:
Dim T As New Test()
T.Prova("Marco") 'Visualizza il messaggio "Il nome specificato è: Marco."
T.Prova(104)
'Visualizza il messaggio "Il numero specificato è: 104."
Per indicare che una routine sfrutta l'overloading, ovvero che sono presenti più definizioni per la stessa, si dovrebbe
specificare la parola chiave Overloads, nel modo seguente:
Public Overloads Sub Prova(ByVal Nome As String)
Public Overloads Sub Prova(ByVal Numero As Integer)
Tuttavia, il parametro Overloads è predefinito, quindi anche omettendolo (come abbiamo fatto nella classe di esempio sopra
riportata), Vis ual Basic sarà in grado di gestire correttamente l'overloading.
Un utilizzo classico dell'overloading è nella definizione di un costruttore per una classe (abbiamo parlato del costruttore
quando abbiamo introdotto il concetto di classe, nella Lezione 3). Supponiamo di avere una classe Giocatore, che, tra le altre
cose, contiene il nome del giocatore: si vorrebbe dare la possibilità di definire il nome del giocatore nel momento in cui si crea
un'istanza della classe; se il nome non viene specificato, dovrebbe essere impostato su "Anonimo". E' possibile realizzare
quanto detto con l'overloading del costruttore:
Public Class Giocatore
Private NomeGiocatore As String
Sub New()
NomeGiocatore = "Anonimo"
End Sub
Sub New(ByVal sNome As String)
NomeGiocatore = sNome
End Sub
'...
End Class
Supponiamo inoltre di avere una Property Nome che restituisce il nome del giocatore. Stando così le cose, creando un'istanza
della classe otterremo, ad esempio:
Dim G As New Giocatore()
'Non si specifica il nome del giocatore: verrà richiamato
il costruttore "New()".
MsgBox(G.Nome) 'Visualizza "Anonimo".
Dim G2 As New Giocatore("Marco")
'Si specifica il nome del giocatore: verrà
richiamato il costruttore
'"New(ByVal sNome As String)".
MsgBox(G2.Nome) 'Visualizza "Marco".
Notiamo che, nel caso di overloading del costruttore, non si deve mai utilizzare la parola chiave Overloads , altrimenti si
http://guidepc.altervista.org
ottiene un messaggio di errore.
Ora che abbiamo analizzato le principali novità di Visual Basic .NET, è finalmente possibile cominciare ad utilizzare nella
pratica questo linguaggio: nella prossima Lezione verrà introdotto brevemente il nuovo ambiente di sviluppo di Visual Studio.
Il nuovo ambiente di sviluppo
Sebbene sia possibile creare applicazioni VB .NET utilizzando un qualsiasi editor di testo e il compilatore da riga di comando
che Microsoft distribuisce gratuitamente sul proprio sito Internet, Visual Studio .NET offre una serie di strumenti che
permettono di incrementare molto la produttività: consente di realizzare applicazioni in modo grafico, semplicemente
trascinando e posizionando sul form gli elementi che si vogliono usare, dispone di tecnologie come il completamento
automatico per velocizzare la scrittura del codice, ecc. Il nuovo ambiente di sviluppo di Microsoft, denominato Microsoft
Development Environment, presenta cambiamenti significativi rispetto alle versioni precedenti di Visual Studio: ora è un
ambiente integrato che racchiude gli editor per tutti i linguaggi di programmazione supportati dalla piattaforma .NET. E'
possibile realizzare applicazioni utilizzando più linguaggi all'interno della stessa soluzione (vedremo più avanti cosa si intende
per "soluzione").
I diversi linguaggi di programmazione condividono anche la stessa organizzazione dei file sorgenti: essa risulterà familiare a
chi ha già usato le precedenti versioni di Visual Studio, mentre potrebbe inizialmente disorientare coloro che hanno
programmato solo con Visual Basic; in realtà è possibile trovare alcuni parallelismi tra l'organizzazione dei file di VB 6 e
quella di Visual Studio .NET.
Come già accennato nella prima lezione, i file sorgente di VB .NET hanno tutti estensione .vb, indipendentemente dal fatto che
siano form, moduli o moduli di classi. I sorgenti di una stessa applicazione sono raggruppati in progetti, proprio come nelle
precedenti versioni. Infine, più progetti possono essere inseriti all'interno della stessa soluzione, concetto che si avvicina
abbastanza al gruppo di progetti di VB 6; la differenza sta nel fatto che nella medesima soluzione è possibile includere
progetti realizzati con diversi linguaggi di programmazione.
Avviando per la prima volta Visual Studio .NET, verranno visualizzate nella parte centrale della finestra una serie di opzioni
utili per personalizzare l'ambiente di sviluppo; esse saranno comunque accessibili anche in futuro all'interno della finestra
Opti ons (Opzioni), raggiungibile con un clic sul menu Tools (Strumenti).
Dopo aver effettuato le personalizzazioni del caso, facendo clic sul pulsante New Project (Nuovo progetto), verrà visualizzata
la finestra di dialogo omonima in cui, sulla sinistra, è visibile una lista ad albero con una voce principale per ogni tipo di
progetto che è possibile realizzare con Visual Studio .NET.
Selezionando Visual Basic projects (Progetti Visual Basic) sulla
destra comparirà l'elenco dei tipi di applicazioni Visual Basic:
Windows Application (Applicazione Windows) corrispondente
all'EXE Standard delle versioni precedenti. In questa stessa finestra
è anche possibile specificare il nome dell'applicazione e la posizione
in cui salvarla.
Accettiamo le impostazioni di default con un clic sul pulsante OK;
verrà creata un'applicazione per Windows composta da un Windows
form: con questo termine si indica l'evoluzione del classico form di
Visual Basic (la Windows form sarà argomento della prossima
Lezione). La struttura dei file che compongono la soluzione
dovrebbe risultare simile a quella raffigurata nella figura seguente:
La finestra mostrata è il Solution Explorer, che funziona in modo analogo alla Gestione progetti delle precedenti versioni di
Visual Basic.
http://guidepc.altervista.org
Facendo doppio clic sul nome della form (Form1.vb) sarà visualizzata la
finestra per l'immissione del codice sorgente; in alternativa al doppio clic è
possibile premere il tasto F7. L'editor del codice di Visual Basic .NET
presenta innovazioni significative rispetto alle versioni precedenti, tutte
rivolte all'aumento della produttività dello sviluppatore. Tra le nuove
funzioni si segnalano in particolare l'indentazione automatica del codice
durante la digitazione e la "chiusura automatica" dei costrutti, per cui, ad
esemp io, se si scrive un condizione If e si preme il tasto Invio, l'editor
aggiungerà la clausola End If e posizionerà il cursore nella posizione
corretta per la scrittura del codice facente parte dell'If stesso.
Altre novità importanti sono relative all'organizzazione del codice sorgente:
ora le varie parti del codice possono essere collassate ed espanse facendo clic
rispettivamente sul simbolo - (meno) e + (più) che viene automaticamente
visualizzato a destra delle dichiarazione di un metodo, di un insieme di righe di commento, ecc. Inoltre, attraverso il nuovo
costrutto #Region... #End Region è possibile organizzare logicamente porzioni di codice che svolgono operazioni correlate.
Ad esempio, all'interno di una classe:
#Region " Matematica "
Private Function Somma(ByVal A As Double, ByVal B As Double) As Double
Return A + B
End Function
Private Function Sottrazione(ByVal A As Double, ByVal B As Double) As Double
Return A - B
End Function
#End Region
Scrivendo questo codice, accanto alla riga #Region " Matematica " comparirà il segno - (meno); se ora proviamo a fare clic
su tale simbolo, tutta la sezione di codice compresa in questa regione verrà collassata nell'unica riga " Matematica ".
Le novità di Visual Studio .NET non si fermano qui: è anche possibile personalizzare l'ambiente di sviluppo tramite macro
scritte con Visual Basic for Applications, utilizzando un editor analogo a quello disponibile in Office. La Lista dei task,
inoltre, oltre a visualizzare gli errori presenti nel programma, consente di definire delle annotazioni all'interno del codice in
modo da evidenziare, ad esempio, i punti da correggere, quelli da rivedere, le modifiche effettuate, ecc. Facendo doppio clic
sull'annotazione visualizzata in questa finestra, verrà automaticamente selezionata la riga di codice corrispondente.
La Windows form – parte prima
Visual Basic .NET introduce un nuovo oggetto, la Windows form, che prende il posto del form delle versioni precedenti; i
cambiamenti riguardano in particolare le funzionalità, le nuove caratteristiche e i nuovi metodi supportati. Le Windows form
sono il componente fondamentale della piattaforma Microsoft .NET, rispondendo a quelli che sono i requisiti del paradigma
della programmazione orientata agli oggetti. Esse consentono di sfruttare in maniera estremamente semplice tutte le
caratteristiche di Windows 2000 e XP.
Per utilizzare le Windows form è necessario creare una Windows Application (Applicazione Windows), come abbiamo visto.
Per aggiungere nuove form al progetto, fare clic con il tasto destro del mouse sul nome del progetto all'interno del Solution
Explorer e scegliere Add (Aggiungi), quindi selezionare €Add Windows form (Aggiungi Windows form).
La Windows form è concettualmente molto diversa dalla form di Visual Basic 6. Innanzi tutto nel codice di una Windows form
possiamo notare la Sub New, che come abbiamo detto definisce il costruttore della classe: una Windows form, infatti, è prima
di tutto una classe, quindi per essa valgono tutte le considerazioni fatte in precedenza. Da notare che tale Sub non è
direttamente visibile nel codice, ma è contenuta all'interno della regione Windows form designer generated code (Codice
generato dal Windows form designer). Sotto la definizione della form, Public Class Form1, compare l'istruzione Inherits
System.Windows.Forms.Form: si tratta della classe base da cui ereditano tutte le Windows form. Essa fa parte della base
class library, la libreria classi base di .NET. Come si può vedere da tale istruzione, la classe Form è contenuta nel namespace
System.Windows.Forms .
Altra novità rispetto alle versioni precedenti di Visual Basic è la routine InitializeComponent, che contiene la definizione e le
proprietà di tutti gli elementi dell'interfaccia della form: mentre prima tali informa zioni erano contenute nell'intestazione del
file .frm e non erano direttamente modificabili da Visual Basic, ora sono chiaramente visibili aprendo il codice della Windows
form all'interno di Visual Studio .NET. La routine New può essere usata per replicare le funzionalità dell'evento
Form_Initialize, scrivendo il proprio codice dopo la chiamata a InitializeComponent.
Facendo doppio clic sulla form, verrà aperto l'editor del codice all'interno della routine Form1_Load, il cui significato è lo
stesso che aveva in VB 6. Dopo la lista degli argomenti dell'evento, di cui parleremo tra breve, si può notare un nuovo
http://guidepc.altervista.org
costrutto: Handles MyBase.Load. Con questa istruzione si indica a Visual Basic che la routine appena dichiarata gestisce
l'evento Load del form; MyBase è una parola chiave che permette di riferire la classe in cui ci si trova attualmente (abbiamo
infatti detto che la Windows form è una classe) . La conseguenza di questa novità è che i nomi degli eventi in VB .NET non
sono più vincolati: è possibile creare Sub con qualsiasi nome, a patto naturalmente che prevedano la corretta lista degli
argomenti, e poi associarli a determinati eventi con il costrutto Handles oggetto.evento. Ad esempio, l'evento Load del form
potrebbe essere gestito da una Sub Avvio così definita:
Private Sub Avvio(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles MyBase.Load
MsgBox("Hello World!")
End Sub
Dopo aver scritto questo codice, eseguiamo il programma, premendo come di consueto il
tasto F5: se non ci sono stati errori di digitazione, verrà visualizzata la seguente finestra:
E' importante notare una cosa: a causa di un bug di Visual Studio .NET, potrebbe succedere
che, premendo il tasto F5, il programma venga compilato ma non eseguito. In questo caso è
sufficiente premere il tasto
, quindi il tasto
per avviare correttamente il programma.
Vediamo ora le differenze negli argomenti inviati ad un evento. Innanzi tutto, in VB .NET tutti gli eventi prevedono degli
argomenti, a differenza di quanto avveniva nelle versioni precedenti di Visual Basic, in cui eventi del tipo Form_Click e lo
stesso Form_Load non avevano alcun argomento. Il primo argomento è sempre di tipo System.Object e permette di
identificare l'oggetto che ha generato l'evento: questa informazione è utile, ad esempio, perché con la parola chiave Handles è
possibile associare più oggetti alla stessa routine. Ad esempio, inseriamo due pulsanti sulla form, quindi premiamo il tasto F7
per visualizzare il codice del form e scriviamo:
Private Sub Clic(ByVal sender As Object, ByVal e As EventArgs) Handles
Button1.Click, Button2.Click
If sender.Equals(Button1) Then
MsgBox("E' stato fatto clic sul pulsante Button1.")
ElseIf sender.Equals(Button2) Then
MsgBox("E' stato fatto clic sul pulsante Button2.")
End If
End Sub
La lista degli argomenti richiesti da un certo evento è disponibile nella Guida in linea di Visual Basic .NET. Dopo la parola
chiave Handles sono stati specificati due eventi, separati da una virgola; in generale, è possibile specificarne un numero
arbitrario, a patto che richiedano gli stessi argomenti.
Poiché la Sub Clic viene generata indifferentemente quando si fa clic su Button1 o su Button2, è necessario usare l'oggetto
sender per sapere quale dei due pulsanti è stato in realtà premuto; per fare questo, si usa il metodo Equals dell'oggetto, che
prende come argomento un altro oggetto e restituisce True se i due oggetti sono uguali.
Il secondo argomento, nel caso dell'evento Load, è di tipo EventArgs, anche se a seconda del tipo di evento può essere
diverso; ad esempio, nel caso degli eventi KeyDown, KeyUp, è di tipo System.Windows.Forms.KeyEventArgs. Esso
contiene informazioni di vario genere, dipendenti dal particolare tipo di evento a cui si riferisce.
Per fare un esempio, proviamo a intercettare l'evento KeyPress della form; Innanzi tutto posizioniamoci sull'evento relativo.
All'interno della finestra del codice, fare clic sulla ComboBox in alto a sinistra e selezionare (base class events): tale categoria
raggruppa tutti gli eventi della classe base; fatto questo, nel ComboBox in alto a destra comparirà la scritta (Declarations):
fare clic su quest'ultima e scorrere l'elenco fino a selezionare l'evento KeyPress. All'interno dell'editor verrà automaticamente
aggiunta la seguente Sub per gestire l'evento:
Private
Sub
Form1_KeyPress(ByVal
sender
As
Object,
ByVal e
System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
As
End Sub
Supponiamo di voler stampare un messaggio diverso a seconda che si digiti una consonante o una vocale. Il codice è:
Private
Sub
Form1_KeyPress(ByVal
sender
As
Object,
ByVal
System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
Select Case e.KeyChar
Case "A", "E", "I", "O", "U", "a", "e", "i", "o", "u"
MsgBox("E' stata digitata una vocale.")
http://guidepc.altervista.org
e
As
Case Else
MsgBox("E' stata digitata una consonante.")
End Select
End Sub
L'oggetto e, di tipo KeyPressEventArgs, contiene informazioni sul carattere premuto; in particolare, la proprietà KeyChar
restituisce il carattere che è stato digitato.
Quanto detto relativamente agli eventi è valido per la form, ma più in generale per tutti i controlli di Visual Basic .NET. Nella
prossima Lezione continueremo l'analisi delle principali novità introdotte dalla Windows form.
La Windows form – parte seconda
Continuiamo la nostra breve analisi delle nuove caratteristiche della Windows form di VB .NET. Una delle cose più importanti
da notare è che la proprietà Caption è stata rinominata in Text. Più in generale, le proprietà Caption di tutti i controlli sono
state sostituite dalla proprietà Text; a parte il nome diverso, comunque, le due proprietà sono assolutamente analoghe.
Abbiamo detto che una Windows form è una classe: è quindi possibile creare oggetti di tipo form e lavorare con essi come con
qualunque altro oggetto. In particolare, quando si vuole aprire una form sopra un altro, è necessario prima dichiarare un
oggetto che abbia come tipo la form da visualizzare. Cerchiamo di spiegare meglio questo concetto con un esempio. Dopo aver
creato una nuova soluzione aggiungiamo un secondo form al progetto corrente, oltre a quello che viene creato di default (e che
ha nome Form1). Per fare questo, fare clic con il tasto destro del mouse sul nome del progetto all'interno del Solution
Explorer e scegliere Add (Aggiungi), quindi selezionare Add Windows form (Aggiungi Windows form). Confermare le
impostazioni della finestra di dialogo Add New Item (Aggiungi nuovo elemento) con un clic sul pulsante Open (Apri). Il
nome del nuovo form è Form2. Ora aggiungiamo un pulsante sul Form1: l'oggetto CommandButton è stato rinominato in
Button; impostiamone la proprietà Text su "Apri secondo form". Facciamo quindi doppio clic sul pulsante per generare la
routine che gestisce l'evento clic e scriviamo il codice seguente:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim frm As New Form2()
'Visualizza il Form2.
frm.ShowDialog()
End Sub
La prima dichiarazione definisce un nuovo oggetto frm di tipo Form2 e, tramite la parola chiave New, ne crea una nuova
istanza. L'istruzione successiva richiama il metodo ShowDialog di frm: esso corrisponde, nelle precedenti versioni di Visual
Basic, al metodo Show con il parametro vbModal , cioè visualizza il Form2 e blocca l'esecuzione di Form1 finché Form2 non
viene chiuso. Invece, se vi vuole visualizzare il Form2 senza fermare Form1, è necessario richiamare il metodo Show di frm.
L'evento QueryUnload è stato rinominato in Closing. Mentre in VB6, per annullare la chiusura della form, era necessario
impostare su True la variabile Cancel che faceva parte degli argomenti di QueryUnload, per ottenere lo stesso effetto in VB
.NET si deve agire sulla proprietà e.Cancel, come potete osservare dall'esempio seguente:
Private Sub Form1_Closing(ByVal sender As Object, ByVal
System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
'Annulla la chiusura del form.
e.Cancel = True
End Sub
e
As
Per chiudere una form è necessario richiamare il metodo Close della form stessa. Ad esempio, per fare in modo che premendo
il pulsante Button1 la finestra venga chiusa, si deve scrivere il codice seguente:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Me.Close()
End Sub
La Windows form introduce numerose nuove proprietà, consentendo di realizzare
facilmente operazioni che prima erano possibili sono utilizzando le API di Windows,
come impostare le dimensioni massima e minima della finestra (per determinare le
quali sono disponibili rispettivamente le proprietà MaximumSize e MinimunSize).
Non essendo possibile analizzarle tutte, ci limiteremo ad illustrare le più importanti e
quelle che hanno subito cambiamenti rispetto alla versione precedenti di Visual Basic.
Innanzi tutto, le proprietà AcceptButton e CancelButton consentono di impostare il
pulsante il cui codice si vuole venga eseguito, rispettivamente, quando si premono i
http://guidepc.altervista.org
tasti Invio oppure Esc. In pratica, queste due proprietà sostituiscono le precedenti Accept e Cancel del controllo
CommandButton. Per impostare tali proprietà, fare clic sulla freccia posta sulla destra di AcceptButton oppure CancelButton
nella finestra delle Proprietà: verrà visualizzata una lista da cui è possibile selezionare il pulsante che si vuole associare.
La proprietà BorderStyle è stata rinominata in FormBorderStyle, ma a parte il cambiamento di nome non ha subito altre
modifiche.
La proprietà Menu consente di impostare un menu per il form. Anche il menu e i comandi di menu, infatti, in VB .NET sono
trattati come oggetti. Questa proprietà viene esposta perché è possibile definire più oggetti di tipo Menu nell'applicazione,
visualizzando di volta in volta quello opportuno, ad esempio in risposta a determinate azioni dell'utente. I menu in VB .NET
saranno trattati nella Lezione 13.
Opacity consente di imp ostare la percentuale di trasparenza della form. La proprietà StartUpPosition è stata rinominata in
StartPosition; la proprietà CenterOwner ora si chiama CenterParent. TransparentKey permette di definire un colore che
apparirà trasparente quando verrà disegnato sulla form.
Ci sono poi altre nuove proprietà supportate dalla form e dai controlli standard. Analizziamo anche in questo caso le più
significative.
La proprietà BackgroundImage consente di impostare un'immagine di sfondo. Se il file selezionato ha dimensioni inferiori a
quelle del form, verrà automaticamente affiancato fino a coprire l'intera finestra.
La proprietà Cursor sostituisce la proprietà MousePointer. Per impostare un cursore è necessario utilizzare la classe Cursors,
come mostrato nell'esempio seguente:
Me.Cursor = Cursors.WaitCursor 'Imposta la clessidra.
Me.Cursor = Cursors.Default 'Ripristina il puntatore predefinito.
Una proprietà completamente nuova è ContextMenu, con cui è possibile associare un menu contestuale alla form, cioè un
menu che viene automaticamente richiamato quando si fa clic sulla form con il tasto destro del mouse. Ritorneremo su questo
argomento quando parleremo della nuova gestione dei menu in VB .NET, nella Lezione 13.
Ora che abbiamo preso familiarità con la Windows form, possiamo analizzare le novità dei controlli standard di VB .NET, che
saranno trattate a partire dalla prossima Lezione.
TextBox
Non possiamo descrivere in questa sede tutti i controlli di Visual Basic .NET; i soli controlli standard, infatti, sono almeno 45,
contro i 20 di Visual Basic 6. Di conseguenza, ci limiteremo ad analizzare i nuovi
oggetti introdotti da VB .NET e, brevemente, quelli che presentano cambiamenti
significati rispetto alle versioni precedenti. Per ogni controllo analizzato, cominceremo
con l'esporre le nuove proprietà e i nuovi metodi di cui dispone; potrebbe sembrare un
approccio noioso, ma dato che la maggior parte delle proprietà e dei metodi hanno
cambiato nome da VB 6 a VB .NET, questo è l'unico modo per evitare di non ritrovare
più quello che serve quando si lavora con il nuovo ambiente di sviluppo.
Uno dei controlli maggiormente potenziati è la TextBox. La prima cosa da far notare è
che è stato finalmente superato il limite dei 64.000 caratteri circa visualizzabili: ora è possibile, teoricamente, inserire fino a 2
GB di informazioni in una singola casella di testo. Una delle proprietà più interessanti, peraltro comune a tutti i controlli, è la
proprietà Anchor, che consente di adattare il controllo alle dimensioni della finestra. Per impostarla, fare clic sulla freccia
visualizzata a destra di tale proprietà: comparirà una piccola finestra in cui selezionare, con un clic del mouse, i bordi della
finestra a cui si vuole ancorare il controllo.
L'impostazione predefinita è Top, Left, cioè il controllo ancorato al bordo sinistro in alto: in pratica l'oggetto non viene
adattato alle dimensioni della finestra, ma resta fisso nella sua posizione. Proviamo ad inserire una TextBox sulla form, in una
posizione qualsiasi, e ad impostare la sua proprietà Anchor su Top, Left, Right. Se ora proviamo a ridimensionare il form,
anche in fase di progettazione, noteremo che la casella di testo di allunga o si riduce in accordo alle dimensioni della finestra.
Analogamente, se posizioniamo la TextBox nella parte bassa del form e impostiamo Anchor su Bottom, Left, essa rimarrà
sempre alla stessa distanza dal bordo inferiore della finestra, qualunque dimensione essa abbia.
Passando alle proprietà specifiche della TextBox, AcceptsReturn e AcceptsTab consentono di stabilire se il controllo deve
accettare, rispettivamente, i caratteri Invio e Tab. Ad esempio, la prima proprietà è utile quando si ha un controllo multilinea e
si vuole fare in modo che, premendo il tasto Invio, venga inserita una nuova linea di testo; se, invece, AcceptsReturn è False
(impostazione predefinita), premendo Invio verrà attivato il pulsante di default della form. AcceptsTab deve essere impostata
su True se si vuole dare la possibilità di inserire caratteri di tabulazione nella TextBox, altrimenti la pressione del tasto Tab
sposterà lo stato attivo sul controllo successivo.
Altra proprietà importante è Lines, che consente di definire le righe di testo della casella, nel caso in cui la proprietà MultiLine
sia impostata su True. Facendo clic sul pulsante con i tre puntini in corrispondenza della proprietà Lines, verrà visualizzato la
finestra di dialogo String Collection Editor, in cui è possibile digitare le righe che si vogliono visualizzare, separate da Invio.
http://guidepc.altervista.org
Per quanto riguarda i metodi, citiamo qui solo i più interessanti, rimandando alla consultazione della Guida in linea per l'elenco
completo. Il metodo AppendText aggiunge il testo specificato alla fine del contenuto nella TextBox. I metodi Copy, Cut e
Paste, rispettivamente, permettono di copiare, tagliare ed incollare il testo: le operazioni con gli Appunti di Windows, che
prima si realizzavano tramite l'oggetto Clipboard, ora sono accessibili come metodi della TextBox. Il metodo Focus, comune a
tutti i controlli, consente di spostare lo stato attivo sull'oggetto su cui viene richiamato. Il metodo Undo, infine, annulla l'ultima
operazione e, di fatto, equivale alla pressione della combinazione di tasti CTRL+Z.
Vediamo ora quali sono i principali eventi del controllo TextBox e come si gestiscono. L'evento Change è stato rinominato in
TextChanged. Ma gli eventi su cui vale la pena spendere qualche parola sono KeyDown, KeyUp e KeyPress: analizziamoli
ricordando che le considerazioni che verranno fatte sono valide per tutti i controlli che possono generare gli eventi KeyDown,
KeyUp e KeyPress.
Per quanto riguarda i primi due, nelle precedenti versioni di Visual Basic essi avevano come parametri KeyCode e Shift, che
permettevano di sapere quale carattere era stato premuto e, controllando il valore di Shift, se in combinazione con ALT, CTRL
o SHIFT; inoltre, scrivendo all'interno dell'evento KeyCode = 0, era possibile annullare la digitazione. Tutte queste
informazioni, in VB .NET, sono contenute nel parametro e, che è di tipo System.Windows.Forms.KeyEventArgs:
Private Sub TextBox1_KeyUp(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyUp
End Sub
In particolare, per quanto riguarda gli eventi KeyUp e KeyDown, l'oggetto e espone le proprietà KeyCode, Alt, Control e Shift,
utili per sapere quale carattere è stato premuto e se in combinazione con i tasti ALT, CTRL o SHIFT. Considerate l'esempio
seguente:
Private Sub TextBox1_KeyUp(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyUp If e.KeyCode = Keys.F And e.Shift = True Then
MsgBox("Premuta la combinazione SHIFT+F.")
End If
End Sub
Keys è un'enumerazione di tutti i caratteri della tastiera e può quindi essere utilizzato per sapere quale carattere è stato
premuto: in questo esempio si controlla se e.KeyCode è uguale a Keys.F, cioè se è stato premuto il carattere F. e.Shift = True,
invece, è usato per sapere se insieme al tasto F è stato premuto anche SHIFT.
Il parametro e dell'evento KeyPress, invece, espone tra le altre le proprietà KeyChar e Handled; la prima contiene la
rappresentazione in formato stringa del carattere premuto, mentre l'altra consente di dire a Visual Basic che l'evento KeyPress
è gestito, cioè che non si vuole visualizzare il carattere premuto nella TextBox perché sono state fatte altre elaborazioni: in
pratica, equivale a porre KeyAscii = 0 nell'evento KeyPress delle precedenti versioni di Visual Basic.
E' arrivato il momento di concretizzare quanto abbiamo detto finora con un esempio pratico. Realizziamo un'ipotetica finestra
per il login di un'applicazione: per essere riconosciuto come valido,
un utente deve digitare nome utente e password corretti (nel nostro
esempio saranno rispettivamente utente e pass); vogliamo però
prevedere anche un funzione di emergenza, in modo tale che sia
possibile entrare anche se ci si dimentica la password. Nel nostro
caso faremo una cosa molto semplice: la procedura di emergenza
consiste nel digitare il nome pippo e premere la combinazione di
tasti SHIFT+E. Iniziamo quindi a realizzare l'esempio, inserendo i
controlli nella form in modo da ottenere una finestra simile a quella
riprodotta a lato. Nella tabella qui sotto sono riportati i nomi dei
controlli utilizzati con i valori delle proprietà da modificare:
Nome controllo (tipo)
Proprietà
Valore
Label1 (Label)
AutoSize
Text
True
Nome utente:
TextBox1 (TextBox)
Text
<Vuoto>
Label2 (TextBox)
Autosize
Text
True
Password:
TextBox2 (TextBox)
PasswordChar
Text
*
><vuoto>
Button1 (Button)
Enable
Text
False
OK
Form1 (Form)
AcceptButton
Button1
http://guidepc.altervista.org
FormBorderStyle
MaximizeBox
MinimizeBox
Text
FivedSingle
False
False
Login
E' il momento di scrivere il codice. Innanzi tutto, vogliamo che il pulsante OK venga attivato solo quando sono stati immessi
sia il nome utente sia la password. Questo comportamento si ottiene con il codice seguente:
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
TextBox1.TextChanged
'La proprietà "TextLength" è usata per recuperare la lunghezza del testo digitato.
If TextBox1.TextLength > 0 And TextBox2.TextLength > 0 Then
Button1.Enabled = True
Else
Button1.Enabled = False
End If
End Sub
Private Sub TextBox2_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged
'La proprietà "TextLength" è usata per recuperare la lunghezza del testo digitato.
If TextBox1.TextLength > 0 And TextBox2.TextLength > 0 Then
Button1.Enabled = True
Else
Button1.Enabled = False
End If
End Sub
La proprietà TextLength restituisce il numero di caratteri contenuti nella casella di testo su cui viene invocata, e corrisponde
alla funzione Len(testo) delle versioni precedenti di Visual Basic. La funzione di controllo del login è molto semplice:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If TextBox1.Text = "utente" AndAlso TextBox2.Text = "pass" Then
Me.Close()
Else
MsgBox("La password digitata non è valida.", MsgBoxStyle.Exclamation)
TextBox1.Focus()
End If
End Sub
Il significato del nuovo operatore AndAlso è stato spiegato nella lezione 2. A questo punto l'esempio è già operativo: avendo
impostato la proprietà AcceptButton della form su Button1, è possibile attivare la routine Button1_Click semplicemente
premendo il pulsante Invio (naturalmente quando il pulsante è attivo). Ma noi abbiamo deciso di prevedere anche una funzione
di emergenza:
Private Sub TextBox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles
TextBox1.KeyDown
If TextBox1.Text = "pippo" AndAlso e.Shift = True AndAlso e.KeyCode = Keys.E Then
MsgBox("E' stata usata la procedura di emergenza.", MsgBoxStyle.Information)
Me.Close()
End If
End Sub
Questa routine semplicemente controlla se, quando il contenuto di TextBox1 è pippo, viene premuta la combinazione
SHIFT+E, nel qual caso visualizza un messaggio per informare l'utente che ha utilizzato la combinazione di emergenza. E'
possibile scaricare il codice completo dell'esempio facendo clic qui.
Nella prossima Lezione parleremo dei controlli PictureBox, Panel e GroupBox: il primo ha subito numerosi cambiamenti
rispetto alle versioni precedenti, mentre il secondo è una novità di Visual Basic. NET; il controllo GroupBox, infine,
sostituisce il vecchio Frame.
I controlli PictureBox, Panel e GroupBox
l controllo Image in Visual Basic .NET non esiste più: ora per visualizzare un'immagine all'interno di una form è possibile
http://guidepc.altervista.org
utilizzare solo il controllo PictureBox. Anch'esso ha subito alcuni cambiamenti significativi.
Innanzi tutto, la proprietà Picture, utilizzata per impostare l'immagine da visualizzare nel controllo, è stata rinominata in
Image; per quanto riguarda i formati, è stato aggiunto il supporto ai file PNG ed alle GIF animate.
La proprietà AutoSize è stata sostituita da SizeMode , che rispetto alla prima offre alcune possibilità in più: Normal è
l'impostazione predefinita; StretchImage adatta le dimensioni dell'immagine perché possa essere interamente visualizzata
all'interno del controllo; AutoSize ridimensiona la PictureBox sulla base della grandezza dell'immagine; CenterImage
visualizza l'immagine centrata nella PictureBox.
Per impostare la proprietà Image non è più disponibile il metodo LoadPicture; essa deve essere impostata su un oggetto di tipo
System.Drawing.Bitmap: allo scopo è possibile utilizzare il metodo FromFile della classe appena citata. Ad esempio,
l'istruzione:
PictureBox1.Image = System.Drawing.Bitmap.FromFile("C:\Immagini\Cascate.bmp")
Visualizza nella PictureBox l'immagine C:\Immagini\ Cascate.bmp. Per eliminare l'immagine, è sufficiente porre la proprietà
Image uguale a Nothing.
Il controllo Panel è molto semplice da utilizzare. Si tratta di un controllo contenitore, cioè consente di definire un'area al cui
interno è possibile inserire altri oggetti, che verranno logicamente considerati insieme, come facenti parte di un unico gruppo:
ad esempio, nascondendo un controllo Panel, verranno automaticamente nascosti anche tutti i controlli in esso contenuti. Nelle
precedenti versioni di Visual Basic, per raggruppare insieme alcuni oggetti era necessario inserirli all'interno di una
PictureBox, che quindi aveva una doppia valenza (visualizzatore di immagini e contenitore). Per inserire oggetti in un controllo
Panel è sufficiente selezionarli e trascinarli all'interno del controllo stesso: non è più indispensabile crearli direttamente nel
contenitore, come accadeva con la PictureBox; analogamente, se si vuole portare un oggetto all'esterno del Panel, basta
selezionarlo e spostarlo al di fuori di esso. Se si elimina un controllo Panel, verranno automaticamente eliminati anche tutti gli
oggetti al suo interno.
Le considerazioni fatte fin qui relativamente al Panel si applicano anche al GroupBox, controllo che
prende il posto del vecchio Frame.
Anch'esso è un controllo contenitore: la differenza rispetto al Panel è che il GroupBox definisce
un'area delimitata e visibile in fase di esecuzione, mentre i bordi del controllo Panel sono invisibili a
runtime.
Realizziamo ora un piccolo esempio per impratichirci con i controlli appena analizzati. Oltre a Panel e
PictureBox, utilizzeremo anche la RadioButton (nuovo nome dell'OptionButton) e la CheckBox.
L'applicazione che andremo a creare è molto semplice: una PictureBox di cui si può impostare la
proprietà SizeMode attraverso una serie di RadioButton; una CheckBox, inoltre, consente di stabilire
se si vuole visualizzare o meno l'immagine. L'interfaccia che vogliamo realizzare è visibile a lato. Le
proprietà da impostare sono le seguenti:
Nome controllo (tipo)
Proprietà
Valore
Panel1 (Label)
RadioButton 1 (RadioButton)
Checked
Tag
Text
True
0
Normal
RadioButton 2 (RadioButton)
Tag
Text
1
StretchImage
RadioButton 3 (RadioButton)
Tag
Text
2
Autosize
RadioButton 4 (RadioButton)
Tag
Text
3
CenterImage
CheckBox 1 (CheckBox)
Checked
Text
True
Visualizza
PictureBox 1 (PictureBox)
SizeMode
Normal
Infine, impostiamo la proprietà Image della PictureBox su un'immagine di dimensioni minori di quelle della casella, cosicché
sia possibile notare gli effetti della modifica della proprietà SizeMode .
Cominciamo dalle cose più facili, cioè il codice associato al controllo CheckBox1. Vogliamo che, attivando o disattivando la
casella di controllo, la PictureBox venga visualizzata oppure nascosta:
Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
CheckBox1.CheckedChanged
'Visualizza o nasconde la PictureBox.
http://guidepc.altervista.org
PictureBox1.Visible = CheckBox1.Checked
End Sub
L'evento CheckedChanged viene generato quando si modifica la selezione di una CheckBox, sia direttamente, con un clic sul
controllo, sia via codice, impostando la proprietà Checked.
Ora dobbiamo scrivere il codice per modificare la proprietà SizeMode della PictureBox a seconda della RadioButton che viene
premuta. Il modo più semplice per farlo consiste nello scrivere quattro routine, una per controllo, ciascuna delle quali imposta
SizeMode su un valore diverso. Vediamo qui, invece, una soluzione più sofisticata ed efficiente, che sfrutta una sola routine e
l'oggetto sender:
Private Sub Selection(ByVal sender As Object, ByVal e As System.EventArgs) Handles RadioButton1.Click,
RadioButton2.Click, RadioButton3.Click, RadioButton4.Click
PictureBox1.SizeMode = CInt(CType(sender, RadioButton).Tag)
End Sub
Cerchiamo di spiegare bene il significato di queste righe di codice. Innanzi tutto, dopo la parola chiave Handles sono stati
specificati quattro eventi, corrispondenti agli eventi Click di ciascuna RadioButton: in tal modo si dice a Visual Basic di
eseguire la routine Selection ogni volta che si preme il pulsante del mouse su una RadioButton. All'interno della routine,
l'oggetto sender è usato per recuperare il particolare controllo che ha generato l'evento; sender è di tipo Object, da cui sono
derivati tutti i tipi di Visual Basic .NET. Noi però sappiamo che in questo caso l'oggetto passato alla funzione è una
RadioButton, quindi usiamo la funzione CType per convertirlo e poter utilizzare i metodi e le proprietà tipiche di una
RadioButton. In generale, la sintassi della funzione CType è la seguente:
CType(espressione, tipo)
Dove espressione rappresenta quello che si vuole convertire (ad esempio un oggetto o una variabile), mentre tipo è il tipo di
dato che vogliamo ottenere con la conversione. Tornando la nostro esempio, dopo aver convertito l'oggetto sender in
RadioButton ne leggiamo la proprietà Tag, la trasformiamo in intero con CInt e la passiamo alla proprietà SizeMode della
PictureBox1.
E' da notare che, se non avessimo utilizzato la funzione CType, il codice avrebbe funzionato ugualmente, poiché VB avrebbe
tentato una conversione implicita dell'oggetto sender. Utilizzando, invece, la funzione CType si forza una conversione
esplicita: dove possibile, è sempre preferibile usare le conversioni esplicite piuttosto che quelle implicite, innanzi tutto perché
rendono più chiaro il codice, poi perché consentono a Visual Basic di determinare univocamente il tipo di dati di un particolare
oggetto.
Il programma di esempio che abbiamo realizzato in questa Lezione può essere scaricato facendo clic qui.
La prossima Lezione sarà dedicata ad una panoramica sui controlli ListBox, CheckedListBox e ComboBox: pur non essendo
una novità, Visual Basic. NET ha introdotto numerosi cambiamenti relativamente al loro utilizzo.
I controlli ListBox, CheckedListBox e ComboBox
controlli ListBox, CheckedListBox e ComboBox erano già presenti in Visual Basic 6, anche se i primi due erano di fatto un
unico oggetto: per visualizzare la caselle di spunta in una ListBox di VB 6 era necessario impostare la sua proprietà Style su 1
- CheckBox. In VB .NET, invece, ListBox e CheckedListBox sono due controlli separati, pur se con molti elementi in comune.
Cominciamo quindi ad analizzare le proprietà che li accomu nano.
La proprietà Items (disponibile anche nella ComboBox) consente di aggiungere o rimuovere elementi alla lista in modo molto
più facile rispetto alle precedenti versioni di Visual Basic: premendo il pulsante con i tre puntini a destra di tale proprietà, verrà
visualizzato l'Item Collection Editor in cui è possibile digitare gli elementi, uno per riga. MultiColumn deve essere
impostato su True se si vuole che gli elementi della ListBox o della CheckedListBox vengano visualizzati in colonne
affiancate; in questo caso, la proprietà ColumnWidth consente di definire la larghezza delle colonne. La proprietà
SelectionMode sostituisce ed estende la proprietà MultiSelect.
Per quanto riguarda le proprietà della ComboBox, la proprietà Style è stata rinominata in DropDownStyle. DropDownWidth
consente di definire la larghezza, in pixel, dell'elenco a discesa. E' possibile anche impostare il numero di elementi da
visualizzare in tale elenco, agendo sulla proprietà MaxDropDownItems .
Passando ai metodi, è interessante notare come questi controlli siano stati notevolmente potenziati, con l'aggiunta di
funzionalità che prima erano disponibili solo utilizzando le API di Windows. Nel seguito faremo riferimento alla ListBox,
ricordando però che le considerazioni che verranno fatte, salvo diversa indicazione, sono valide per tutti e tre i controlli oggetto
di questa Lezione. Per lavorare con gli elementi di una ListBox è necessario utilizzare i metodi della collezione Items del
controllo. Ad esempio, per aggiungere un elemento ad una ListBox di nome ListBox1 è necessario scrivere:
ListBox1.Items.Add("Nuovo elemento")
Per rimuovere una voce sono disponibili i metodi Remove e RemoveAt: il primo consente di rimuovere l'oggetto specificato,
http://guidepc.altervista.org
in qualunque posizione si trovi, mentre il secondo cancella l'elemento nella posizione specificata.
Ad esempio, ListBox1.Items.Remove ("Testing") rimuove l'elemento di nome Testing dalla ListBox, mentre
ListBox1.Items.RemoveAt(5) elimina la sesta voce dell'elenco (ricordiamo che si inizia a contare da 0). E' da notare che se,
nel primo caso, l'elemento Testing non esiste, non viene comunicato alcun messaggio, mentre se, nel secondo caso, la lista ha
meno di sei elementi, si genera un errore. Altro metodo importante della collezione Items è Contains, che restituisce True se
l'elemento specificato come argomento è presente nella lista, False altrimenti.
Per recuperare l'elemento attualmente selezionato nella ListBox si può usare la proprietà SelectedItem; l'indice corrispondente
è conservato in SelectedIndex. Se si vogliono scorrere gli elementi selezionati è possibile usare le collezioni che gli oggetti
ListBox, CheckedListBox e ComboBox mettono a disposizione; il seguente esempio mostra come conoscere gli elementi
attualmente selezionati in una CheckedListBox:
Dim Elemento As String
For Each Elemento In CheckedListBox1.CheckedItems
MsgBox("Elemento selezionato: " & Elemento)
Next
Se, invece di conoscere gli elementi, fossimo stati interessati a recuperare gli indici selezionati, sarebbe stato sufficiente
scorrere la collezione CheckedListBox1.CheckedIndices.
Per quanto riguarda gli eventi, ricordiamo qui soltanto SelectedIndexChanged, comune a tutti e tre
i controlli, che viene generato quando si seleziona un elemento nella lista, ovvero quando si
modifica la proprietà SelectedIndex del controllo. Passiamo alla consueta realizzazione di un
esempio per chiarire i concetti fin qui esposti. Vogliamo creare un'applicazione che consenta di
selezionare alcuni articoli da un elenco per inserirli, ad esempio, in un ordine da stampare o inviare
via posta elettronica. L'interfaccia è molto ricca di controlli, come si può vedere dall'immagine a
lato:
Nome controllo (tipo)
Proprietà
Valore
AutoSize
Text
true
Elementi disponibili:
Button 1 (Button)
Text
Aggiungi>>
Button 2 (Button)
Text
<<Rimuovi
Label 2 (Label)
AutoSize
Text
true
Elementi Selezionati:
CheckedListBox1
(CheckedListBox)
CheckOnClick
True
Label 4 (Label)
AutoSize
Text
True
<vuoto>
Label 5 (Label)
AutoSize
Text
True
Tipo pagamento
ComboBox 1
(ComboBox)
DropDownStyle
Items
DropDownList
Contanti/Carta Credito
Label 6 (Label)
AutoSize
Text
True
<vuoto>
Button 2 (Button3/)
Text
Calcola
Panel1 (Label)
ListBox 1 (ListBox)
La prima cosa da fare è riempire la ListBox1 all'avvio del programma, attraverso il seguente codice:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim I As Short
For I = 1 To 10
ListBox1.Items.Add(I)
Next
ComboBox1.SelectedIndex = 0
End Sub
In questa routine viene anche selezionato il primo elemento della ComboBox, attraverso l'istruzione
ComboBox1.SelectedIndex = 0.
Adesso vogliamo che quando il puntatore del mouse si sposta su un elemento della ListBox1, l'etichetta sottostante, Label3,
http://guidepc.altervista.org
visualizzi il nome dell'elemento stesso. Per fare questo usiamo il metodo IndexFromPoint e l'evento MouseMove:
Private Sub ListBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles
ListBox1.MouseMove
Dim Indice As Short = ListBox1.IndexFromPoint(e.X, e.Y)
If Indice >= 0 Then
Label3.Text = "Elemento corrente: " & ListBox1.Items(Indice)
End If
End Sub
Il
metodo IndexFromPoint restituisce l'indice dell'elemento che si trova nella posizione del mouse
specificata; in questo caso usiamo due proprietà dell'oggetto e, X e Y, per conoscere le coordinate del
cursore. Se l'indice è valido, cioè è un numero maggiore o uguale a 0, visualizziamo il valore
dell'elemento corrispondente leggendo l'oggetto Items di posizione Indice. Per aggiungere o rimuovere elementi da una o
dall'altra lista il codice da usare è il seguente:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If ListBox1.SelectedIndex >= 0 Then
'Se è stato selezionato un elemento, lo aggiunge alla CheckedListBox1.
CheckedListBox1.Items.Add(ListBox1.SelectedItem, True)
'Rimuove l'elemento dalla ListBox1.
ListBox1.Items.RemoveAt(ListBox1.SelectedIndex)
End If
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
If CheckedListBox1.SelectedIndex >= 0 Then
'Se è stato selezionato un elemento, lo rimette nella ListBox1.
ListBox1.Items.Add(CheckedListBox1.SelectedItem)
'Rimuove l'elemento dalla CheckedListBox1.
CheckedListBox1.Items.RemoveAt(CheckedListBox1.SelectedIndex)
End If
End Sub
Come si vede, le due routine sono speculari. L'unica istruzione su cui spendere qualche parola è
CheckedListBox1.Items.Add(ListBox1.SelectedItem, True). Il metodo Items.Add della CheckedListBox è polimorfico: se
viene specificato il secondo parametro e lo si pone uguale a True, la casella di spunta corrispondente all'elemento appena
inserito verrà automaticamente selezionata. Sempre a riguardo dalla CheckedListBox, notiamo che, impostando la proprietà
CheckOnClick su True, la casella di spunta corrispondente all'elemento su cui si fa clic verrà automaticamente selezionata o
deselezionata.
L'ultima cosa che dobbiamo fare è scrivere il codice per fare in modo che, nella Label5, venga visualizzato il tipo di
pagamento selezionato, utilizzando l'evento SelectedIndexChanged di cui abbiamo già parlato:
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
ComboBox1.SelectedIndexChanged
Label5.Text = "Tipo di pagamento selezionato: " & ComboBox1.SelectedItem
End Sub
Il codice da eseguire alla pressione del pulsante Calcola, in quanto non direttamente collegato con l'esempio, è lasciato come
esercizio. L'esempio che abbiamo realizzato può essere scaricato facendo clic qui.
In questa Lezione abbiamo introdotto tre dei controlli più utilizzati. La prossima Lezione sarà incentrata sul menu, uno dei
componenti fondamentali di un'applicazione Windows; come vedremo, la gestione dei menu in VB .NET è radicalmente
diversa rispetto a quella delle versioni precedenti.
Menu e Tooltip in VB .NET
La gestione dei menu in Visual Basic .NET è radicalmente diversa rispetto a quella delle versioni precedenti.
L'amato-odiato Editor di menu ha fatto il suo tempo: ora per inserire un menu in un'applicazione VB .NET si deve utilizzare
l'oggetto MainMenu, disponibile nella casella degli strumenti standard.
Aggiungendo il controllo MainMenu in una form, comparirà un'area nella parte bassa della finestra in cui verrà inserita l'icona
relativa. Si tratta di una novità di VB .NET: i controlli non visibili in fase di esecuzione, ad esempio il Timer, non vengono più
visualizzati nella form, ma in una zona separata, così da evitare appesantimenti inutili.
Dopo aver inserito il MainMenu, sotto la barra del titolo della form apparirà la barra dei menu, come si può vedere
nell'immagine a lato. Ecco un'altro cambiamento rispetto alle versioni precedenti di Visual Basic: per definire i comandi dei
http://guidepc.altervista.org
menu ora basta scriverli all'interno del menu stesso in fase di progettazione. Ad esempio, proviamo a fare clic sulla comando
Type Here (scrivi qui) nella barra dei menu e a scrivere File: questo è sufficiente per creare un menu
di nome File. Appariranno ora nuove voci nella barra dei menu, tutte contrassegnate da Type Here: al
posto di ognuna di esse è possibile inserire un comando di menu. Come nelle versioni precedenti di
Visual Basic, per inserire una barra di separazione nel menu basta creare una nuova voce e impostare
la sua etichetta su - (segno meno); in alternativa, è anche possibile fare clic con il tasto destro del
mouse all'interno del menu e selezionare Insert Separator (Inserisci separatore). Per spostare un
comando da una posizione ad un'altra basta trascinare l'elemento del menu nella posizione
desiderata.
Facendo clic su un comando, nella finestra delle Proprietà compariranno le proprietà della voce
di menu. Checked consente di visualizzare un segno di spunta a sinistra del nome del menu;
RadioCheck, novità di VB .NET, deve essere impostato su True se si vuole che al posto del
segno di spunta venga visualizzato un radio button (può essere usato, ad esempio, per indicare la
scelta corrente in un insieme di opzioni). Shortcut consente di definire una scorciatoia da tastiera per il comando; è possibile
decidere se visualizzare o meno tale combinazione di tasti agendo sulla proprietà ShowShortcut.
Per
scrivere il codice da eseguire quando si seleziona un comando dal menu, fare doppio clic sul comando
stesso: si aprirà l'editor del codice all'interno della routine che gestisce l'evento Click sulla voce di
menu.
Altro
evento importante è Select, che viene generato quando il puntatore del mouse di sposta su una voce del
menu.
L'altro tipo di menu disponibile in VB .NET è il menu contestuale: nelle applicazioni per Windows esso viene visualizzato
quando si fa clic con il tasto destro del mouse su di un controllo. Nelle precedenti versioni di Visual Basic, per mostrare questo
tipo di menu era necessario aggiungerlo alla barra dei menu standard, quindi richiamarlo con il metodo PopupMenu ad
esempio all'interno dell'evento MouseUp, in modo da intercettare la pressione del tasto destro del mouse. In VB .NET il
metodo PopupMenu non esiste più: per associare un menu contestuale ad un controllo è necessario creare un oggetto di tipo
ContextMenu. Anch'esso, al pari del MainMenu, una volta inserito nella form viene visualizzato nella parte bassa della
finestra di progettazione; anche la fase di creazione delle voci di menu e di impostazioni
delle proprietà è la medesima. Se in una form sono presenti sia un MainMenu sia uno o
più ContextMenu, facendo clic sull'uno o sull'altro il corrispondente layout dei menu
verrà visualizzato sotto la barra del titolo, anche se, in fase di esecuzione, la barra dei
menu sarà quella impostata nel MainMenu.
Dopo aver creato un menu contestuale, è necessario associarlo ad uno o più controlli. Per
fare questo si deve selezionare il controllo a cui si vuole collegare il menu e impostare la
sua proprietà ContextMenu sul nome del menu contestuale interessato.
Fatto questo, ogni volta che si farà clic con il tasto destro del mouse sul controllo verrà visualizzato il menu contestuale; non è
più necessario scrivere nemmeno una riga di codice per ottenere questo effetto.
L'evento Popup del ContextMenu viene generato prima della visualizzazione del menu contestuale. Può essere utilizzato, ad
esempio, nel caso di un menu associato a più controlli, per adattare i comandi in base all'oggetto su cui è stato fatto il clic.
Supponiamo di avere un ContextMenu associato ai controlli Button1 e Button2 con un unico comando, MenuItem1.
Consideriamo il codice seguente:
Private Sub ContextMenu1_Popup(ByVal sender As Object, ByVal e As System.EventArgs) Handles ContextMenu1.Popup
If ContextMenu1.SourceControl Is Button1 Then
MenuItem1.Text = "Nascondi pulsante"
ElseIf ContextMenu1.SourceControl Is Button2 Then
MenuItem1.Text = "Esci dal programma"
End If
End Sub
Esso fa in modo che, premendo il pulsante destro del mouse su Button1, il comando del menu contestuale sia "Nascondi
pulsante", mentre, facendo clic sul Button2, diventi " Esci dal programma".
Per fare questo si è usata la proprietà SourceControl dell'oggetto ContextMenu, che specifica il controllo su cui è stato
eseguito il clic destro. Anche gli elementi del ContextMenu dispongono dell'evento Click che viene generato quando l'utente
seleziona un comando di menu con il tasto sinistro del mouse.
Passiamo ora al controllo ToolTip, utilizzato per visualizzare un breve messaggio descrittivo quando si posiziona il mouse su
un oggetto per alcuni istanti. Anch'esso è una novità di Visual Basic .NET: nelle precedenti versioni di VB, infatti, per
assegnare un tooltip era sufficiente impostare la proprietà ToolTipText. In VB .NET, per definire un tooltip è necessario
inserire prima nella form un oggetto di tipo ToolTip; anch'esso, come il MainMenu e il ContextMenu, si posiziona nella parte
bassa della finestra di progettazione. Inserito il ToolTip, tra le proprietà dei controlli della form ne apparirà una nuova, Tooltip
on : il messaggio specificato in questa proprietà verrà utilizzato come tooltip.
La decisione di aggiungere un controllo a parte per visualizzare i tooltip è dovuta al fatto che,
così facendo, è possibile impostarne alcune proprietà, come il ritardo di visualizzazione, che
prima non erano disponibili. In particolare, InitialDelay consente di specificare l'intervallo di
http://guidepc.altervista.org
tempo, in millisecondi, che deve passare da quando il puntatore del mouse si sposta su un controllo alla visualizzazione del
messaggio descrittivo; AutoPopDelay indica per quanti millisecondi deve essere visualizzato il tooltip. La proprietà
AutomaticDelay ha lo stesso scopo di InitialDelay, con la differenza che sulla base del valore in essa specificato, verranno
automaticamente impostate anche le proprietà AutoPopDelay, InitialDelay e ReshowDelay (quest'ultima proprietà specifica
quanti millisecondi devono passare prima di visualizzare il nuovo tooltip quando il puntatore del mouse si sposta da un
controllo ad un altro). Per maggiori informazioni su come vengono impostate tali proprietà sulla base di AutomaticDelay, si
rimanda alla consultazione della Guida in linea.
Dopo aver esaminato i controlli MainMenu, ContextMenu e ToolTip, novità assoluta per i programmatori Visual Basic, nella
prossima Lezione realizzeremo un piccolo programma in cui troveranno posto tutti e tre questi oggetti.
Menu e Tooltip in VB .NET – un esempio pratico
Menu e Tooltip in VB .NET - un esempio pratico Nella precedente Lezione abbiamo introdotto la gestione dei menu e dei
tooltip in VB .NET, evidenziandone gli aspetti chiave e le significative novità rispetto alle precedenti versioni di Visual Basic.
Ora realizzeremo un piccolo programma per mostrare l'utilizzo di questi nuovi oggetti. Vogliamo creare un semplicissimo
editor di testi, una versione super ridotta di Blocco note; per fare questo utilizzeremo menu, menu contestuali e tooltip, oltre a
riprendere alcuni concetti che abbiamo trattato nelle precedenti Lezioni di questo corso.
L'applicazione avrà un MainMenu che conterrà i menu File, Modifica e Formato; il testo verrà visualizzato in una TextBox
di cui ridefiniremo il menu contestuale creando un nostro ContextMenu. Un ToolTip, infine, sarà utilizzato per visualizzare
informazioni sul testo. Dato il numero di oggetti che creeremo, è conveniente assegnare dei nomi significativi ai vari controlli,
piuttosto che utilizzare quelli predefiniti; per fare questo si deve intervenire sulla proprietà (Name) del controllo, che consente
di impostare il nome con cui il controllo verrà identificato all'interno del codice.
Cominciamo col creare la struttura del menu. Per fare questo inseriamo un oggetto di tipo MainMenu nella form e impostiamo
il suo nome su MenuPrincipale.. Per modificare i nomi degli elementi dei menu, dopo averne creato la struttura, è possibile
fare clic con il tasto destro del mouse su una voce e selezionare Edit Names (Modifica nomi): così facendo, a sinistra del
menu, tra parentesi quadre, comparirà il nome del menu (vedi immagine a lato), che è esattamente la proprietà Name di quel
comando. Togliendo il segno di spunto da Edit Names sarà nuovamente possibile modificare le etichette dei menu. Per
semplicità, invece che indicare come di consueto le proprietà dei vari oggetti in una tabella, in questo caso ci limiteremo a
mostrare la struttura del menu; a fianco di ogni voce, sono indicati l'eventuale shortcut e, tra parentesi, il nome:
&File
&Modifica (mnuModifica) &Formato (mnuFormato)
(mnuFile)
&NuovoCTRLN
(mnuFileNuovo)
&AnnullaCTRLZ
(mnuModAnnulla)
Allinea a sinistra
(mnuForSinistra)
&Apri...CTRLO
(mnuFileApri)
- (mnuModSep0)
Allinea al centro
(mnuForCentro)
&Salva...CTRLS
(mnuFileSalva)
&Taglia CTRLX
(mnuModTaglia)
Allinea a destra
(mnuForDestra)
- (mnuFileSep0)
&Copia CTRLC
(mnuModCopia)
- (mnuForSep0)
&Esci (mnuFileEsci)
&Incolla CTRLV
(mnuModIncolla)
&Tutto maiuscolo
(mnuForMaiusc)
Ca&ncella Del
(mnuModCancella)
T&utto minuscolo
(mnuForMinusc)
- (mnuModSep1)
&Seleziona tutto
(mnuModSelTutto)
I comandi Apri e Salva del menu File sono seguiti da tre puntini: con questa convenzione si fa capire all'utente che
selezionando questi comandi si aprirà una nuova finestra di dialogo (nel nostro caso, si
dovranno aprire rispettivamente le finestre di dialogo Apri e Salva con nome ). Le voci di
menu che non hanno i puntini, invece, corrispondono a comandi che vengono eseguiti senza
necessità di ulteriore input.
I comandi del menu Formato che gestiscono l'allineamento del testo sono esclusivi, ovvero
è possibile selezionarne solo uno alla volta. Per tale motivo impostiamo la loro proprietà
RadioCheck su True; inoltre mettiamo a True la proprietà Checked di mnuForSinistra,
perché l'allineamento a sinistra è quello predefinito. Se non riuscite a riprodurre la struttura
dei menu suggerita, potete scaricare la form che la contiene facendo clic qui.
http://guidepc.altervista.org
Passiamo ora al ContextMenu. Innanzi tutto aggiungiamolo alla form e impostiamo il suo nome su MenuContestuale.
Vogliamo che questo menu venga visualizzato quando si preme il tasto destro del mouse sulla TextBox, quindi deve includere
comandi per operare rapidamente sul contenuto della casella di testo. Notiamo che una casella di testo include già un menu
contestuale, quello predefinito di Windows. Nelle precedenti versioni di Visual Basic, per visualizzare in una TextBox un
menu contestuale diverso da quello standard era necessario ricorrere ad un trucco che consisteva nel disattivare e riattivare il
controllo; in VB .NET, invece, impostando la proprietà ContextMenu di una TextBox verrà visualizzato solo il nuovo menu
quando si preme il pulsante destro del mouse (in pratica il menu contestuale predefinito viene disattivato).
Nel nostro esempio, per non complicare troppo il programma, nel ContextMenu ci limiteremo a riprodurre i comandi del menu
Modifica. I nomi dei menu dovranno avere la forma mnuCont, come nel menu Modifica (ad esempio mnuContAnnulla,
mnuContTaglia, ecc. ). La creazione del menu è lasciata come esercizio. Se avete qualche problema nella realizzazione, potete
scaricare l'applicazione con il menu contestuale facendo clic qui.
La tabella seguente mostra i rimanenti oggetti da inserire nella form con le rispettive proprietà:
Nome controllo (tipo)
Proprietà
Valore
AcceptsReturn
True
txtTesto (TextBox)
tltInfoTesto (ToolTip)
Form1 (Form)
AcceptsTab
True
Anchor
Top, Bottom, Left, Right
ContextMenu
MenuContestuale
Location
0; 0
Multiline
True
ScrollBars
Vertical
Text
<vuoto>
AutomaticDelay
1000
MinimunSize
320; 240
StartPosition
CenterScreen
Text
Editor
Possiamo finalmente cominciare a scrivere il codice. La prima cosa da fare è modificare le dimensioni della TextBox in modo
che, all'avvio, occupi l'intero form; sarà poi la proprietà Anchor a garantirci il ridimensionamento del controllo in accordo alle
dimensioni della finestra. Questo risultato si ottiene con il codice seguente:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
txtTesto.Height = Me.Height - 46
txtTesto.Width = Me.Width - 8
End Sub
Cominciamo ora con lo scrivere il codice da eseguire in risposta ai clic sui vari comandi di menu. Benché si possa scrivere una
routine per ogni comando di menu, mostreremo qui come sia possibile usare una sola Sub per ogni menu, quindi una per il
menu File, una per Modifica e una per Formato, oltre a una per il menu contestuale. Il codice del menu File è:
Private Sub mnuFileCommand(ByVal sender As Object, ByVal e As System.EventArgs) Handles mnuFileNuovo.Click,
mnuFileApri.Click, mnuFileSalva.Click, mnuFileEsci.Click
Select Case CType(sender, MenuItem).Text
Case "&Nuovo"
txtTesto.Clear()
Case "&Esci"
Me.Close()
End Select
End Sub
Questa routine intercetta gli eventi clic di tutti i comandi del menu File, quindi converte l'oggetto sender in MenuItem e ne
controlla la proprietà Text per sapere quale elemento è stato effettivamente selezionato. Abbiamo parlato della funzione CType
nella Lezione 11. Non abbiamo incluso il codice relativo ai comandi Apri e Salva, che discuteremo nella prossima Lezione,
quando parleremo delle finestre di dialogo comuni. Per il menu Modifica, seguendo un ragionamento analogo, si ottiene:
Private Sub mnuModificaCommand(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
mnuModAnnulla.Click, mnuModTaglia.Click, mnuModCopia.Click, mnuModIncolla.Click, mnuModCancella.Click,
mnuModSelTutto.Click
Select Case CType(sender, MenuItem).Text
Case "&Annulla"
http://guidepc.altervista.org
txtTesto.Undo()
Case "&Taglia"
txtTesto.Cut()
Case "&Copia"
'...
End Select
End Sub
I rimanenti comandi del menu Modifica, il menu Formato e il menu contestuale, presentando una struttura del tutto analoga
quella già trattata, sono lasciati per esercizio. E' comunque possibile scaricare l'applicazione con tutto il codice dei menu.
L'ultima cosa che dobbiamo fare è aggiungere il codice relativo al tooltip. Poiché il testo da visualizzare viene modificato
durante la digitazione, è necessario utilizzare il metodo SetToolTip dell'oggetto tltInfoTesto; esso prevede due argomenti, il
primo è il nome del controllo per cui si vuole impostare il tooltip, il secondo è il testo del messaggio da mostrare:
Private Sub txtTesto_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtTesto.TextChanged
tltInfoTesto.SetToolTip(txtTesto, "Lunghezza del testo: " & txtTesto.TextLength & " caratteri")
End Sub
Abbiamo utilizzato il metodo TextChanged, in modo che il tooltip venga aggiornato ogni volta che si modifica il contenuto
della casella di testo. In VB .NET è possibile creare tooltip multilinea: è sufficiente inserire il carattere vbCrLf all'interno del
messaggio per andare a capo.
La finestre di dialogo comuni in VB .NET
Le finestre di dialogo comuni sono quelle finestre che, come dice il nome stesso, sono standard in tutte le applicazioni per
Windows. Provate ad esempio ad avviare Blocco note e a selezionare i comandi Apri e Salva con nome del menu File: quelle
che appariranno sono due delle finestre di dialogo comuni offerte da Windows; le altre sono le finestre Stampa, Colore e
Carattere. Visual Basic ha sempre offerto degli stramenti per utilizzare tali finestre nelle proprie applicazioni: fino alle
versione 6 essi erano contenute in un controllo OCX aggiuntivo, che quindi doveva essere distribuito insieme ad ogni
programma che ne faceva uso, mentre in VB .NET le finestre di dialogo comuni fanno parte del corredo di controlli standard e
sono OpenFileDialog, SaveFileDialog, FontDialog, ColorDialog e PrintDialog. In questo corso ci occuperemo delle finestre
di dialogo per la gestione dei file.
I controlli OpenFileDialog e SaveFileDialog sono molto simili; cominceremo quindi ad analizzare le proprietà comuni. La
proprietà più importante è Filter, che consente di stabilire quali tipi di file verranno visualizzati nella finestra di dialogo (in
pratica va a modificare la ComboBox Tipo file nelle finestre Apri e Salva con nome). La sua sintassi è la seguente:
Descrizione tipo file|Tipo file|Descrizione tipo file|Tipo file|…|…
Ad esempio:
File di testo|*.txt|Tutti i file|*.*
La proprietà Filter è formata da coppie in cui il primo elemento è la descrizione del tipo di file, mentre la seconda è il filtro
corrispondente. E' possibile specificare più filtri corrispondenti ad una stessa descrizione; in questo caso devono essere separati
da un punto e virgola, senza spazi:
File immagine|*.bmp;*.jpg;*.gif|Tutti i file|*.*
Il carattere | (pipe) è usato per separare sia le varie coppie, sia la descrizione dal filtro in una stessa coppia. Quando si
specificano più filtri per una finestra di dialogo, la proprietà FilterIndex consente di specificare il filtro predefinito. Le
proprietà CheckFileExists e CheckPathExists, se impostate su True, visualizzano un messaggio di errore se, rispettivamente,
il file o il percorso selezionato nella finestra non esiste; tali proprietà sono utili, ad esempio, quando si vuole aprire un file.
InitialDirectory imposta la cartella che deve essere visualizzata quando si apre la finestra di dialogo.
Il controllo SaveFileDialog ha una proprietà molto importante: OverwritePrompt, che, se impostata su True, visualizza un
messaggio di conferma qualora l'utente specifichi il nome di un file esistente per il salvataggio. Per visualizzare la finestra di
dialogo è necessario richiamare il metodo ShowDialog. Tale metodo è disponibile in tutti i controlli comuni. Esso restituisce
un valore che può essere utilizzato per sapere se l'utente ha effettivamente selezionato un file oppure ha premuto il pulsante
Annulla, quindi ha interrotto l'operazione. Si consideri ad esempio il codice seguente:
If OpenFileDialog1.ShowDialog = DialogResult.OK Then
MsgBox("File selezionato " & OpenFileDialog1.FileName)
Else
MsgBox("L'utente ha annullato la selezione.")
End If
http://guidepc.altervista.org
Se il valore restituito dal metodo ShowDialog è uguale a DialogResult.OK, significa che l'utente ha selezionato un file e
premuto il pulsante OK: in questo caso la proprietà FileName del controllo contiene il nome del file, che viene mostrato in una
MessageBox. Se, invece, l'utente ha premuto Annulla, ShowDialog varrà DialogResult.Cancel.
E' da notare che i controlli OpenFileDialog e SaveFileDialog si limitano a fornire un'interfaccia comune per selezionare il file
da aprire o salvare; le operazioni di apertura e salvataggio vere e proprie dovranno essere poi realizzate dal programmatore.
Ora abbiamo tutte le conoscenze teoriche per riprendere l'esempio precedente ed estenderlo aggiungendo le funzionalità di
gestione dei file. Innanzi tutto inseriamo i due controlli OpenFileDialog e SaveFileDialog nella form: essi si posizioneranno
nella parte bassa della finestra di progettazione, andando ad affiancarsi agli oggetti che rappresentano i menu ed il tooltip.
Impostiamo anche i nomi dei controlli, rispettivamente dlgApri e dlgSalva. Nella seguente tabella sono elencate le proprietà da
modificare:
Nome controllo (tipo)
Proprietà
Valore
dlgApri (OpenFileDialog)
dlgSalva (SaveFileDialog)
Filter
File di testo (*.txt)|*.txt|Tutti i file (*.*)|*.*
FileName
<vuoto>
Filter
File di testo (*.txt)|*.t xt|Tutti i file (*.*)|*.*
Riprendiamo la routine che gestisce i comandi del menu File e aggiungiamo il codice relativo ai comandi Apri e Salva.
Abbiamo detto che per visualizzare la finestra di dialogo è necessario richiamare il metodo ShowDialog, quindi controllare il
valore da esso restituito per sapere se l'utente ha effettivamente selezionato un file. Stando così le cose, basta aggiungere il
codice seguente al Select Case che gestisce i comandi del menu File:
Case "&Apri..."
If dlgApri.ShowDialog = DialogResult.OK Then
ApriFile(dlgApri.FileName)
End If
Case "&Salva..."
If dlgSalva.ShowDialog = DialogResult.OK Then
SalvaFile(dlgSalva.FileName)
End If
Come si può vedere, aggiungere una finestra di dialogo comune alla propria applicazione è estremamente semplice. Se l'utente
seleziona un file per l'apertura (cioè se il metodo ShowDialog di dlgApri restituisce DialogResult.OK), viene richiamata la
routine ApriFile (che dobbiamo ancora scrivere), la quale si occupa di aprire effettivamente il file e visualizzarne il contenuto
nella casella di testo. Analogamente, se si seleziona un file per il salvataggio le operazioni necessarie verranno effettuate da
SalvaFile.
Passiamo alla routine che si occupa di aprire un file. Allo scopo utilizziamo un oggetto del namespace System.IO, più
precisamente lo StreamReader che, come dice il nome stesso, legge un flusso di dati dalla sorgente specificata. La routine
ApriFile risulta dunque:
Private Sub ApriFile(ByVal NomeFile As String)
Dim Testo As String
Dim FileReader As New System.IO.StreamReader(NomeFile)
'Legge l'intero file e lo salva nella variabile "Testo".
Testo = FileReader.ReadToEnd
FileReader.Close()
'Libera le risorse allocate con New.
FileReader = Nothing
txtTesto.Text = Testo
End Sub
L'oggetto StreamReader ha un costruttore polimorfico che, nella sua versione più semplice (quella da noi utilizzata), prende
come argomento il nome del file che si vuole leggere. Dopo aver creato un oggetto di tipo StreamReader, richiamiamo il suo
metodo ReadToEnd, che legge il contenuto del file dalla posizione corrente (in questo caso dall'inizio, poiché non abbiamo
fatto altre operazioni sul file) sino alla fine. Al termine chiudiamo lo StreamReader richiamando il suo metodo Close. L'ultima
operazione svolta dalla routine è quella di visualizzare il testo letto all'interno della TextBox.
Anche per il salvataggio utilizziamo un oggetto del namespace System.IO, questa volta lo StreamWriter. Il codice della
routine SalvaFile è semplicissimo:
Private Sub SalvaFile(ByVal NomeFile As String)
Dim FileWriter As New System.IO.StreamWriter(NomeFile)
'Salva il contenuto di "txtTesto" nel file.
FileWriter.Write(txtTesto.Text)
FileWriter.Close()
'Libera le risorse allocate con New.
http://guidepc.altervista.org
FileWriter = Nothing
End Sub
Se avete capito il funzionamento di StreamReader, il funzionamento di StreamWriter dovrebbe essere altrettanto chiaro.
A questo punto l'applicazione è quasi terminata. Manca però ancora una cosa: la gestione degli errori; infatti, non abbiamo
previsto i casi in cui l'apertura o il salvataggio di un file non vada a buon fine. La gestione degli errori in VB .NET sarà
l'argomento della prossima Lezione.
La gestione degli errori in VB .NET
Visual Basic .NET introduce un nuovo costrutto per la gestione degli errori, che va ad affiancarsi al classico On Error: si
tratta di Try… Catch… Finally, costrutto che risulterà sicuramente familiare a chi ha programmato in C++ o in Java. Esso
consente di gestire gli errori che possono verificarsi in una certa porzione del codice, senza interrompere l'esecuzione del
programma. La sintassi ad utilizzare è la seguente:
Try
'Codice che potrebbe generare un errore.
Catch
'Codice da eseguire in caso di errore.
Finally
'Codice da eseguire sia che si sia verificato un errore nel
'blocco Try sia che non ci siano stati problemi.
End Try
In un costrutto Try è necessario specificare almeno una Catch oppure una Finally; è possibile specificare più clausole Catch,
una per ogni errore che si vuole gestire, mentre è consentito inserire solo una clausola Finally. Per uscire da un blocco Try si
deve usare l'istruzione Exit Try.
Se si verifica un errore nel blocco Try, si dice che il programma ha generato un'eccezione. Nella clausola Catch si può indicare
il tipo di errore (eccezione) che si vuole gestire; ad esempio:
Catch ex As OverflowException
Specifica che si vuole catturare un'eccezione di overflow, che viene generata quando si cerca di assegnare ad una variabile un
valore al di fuori del suo range. Si consideri il codice seguente:
Try
Dim A As Byte = 100
Dim B As Byte = A * A
Catch ex As OverflowException
MsgBox("Si è verificato un errore: " & ex.Message)
End Try
Le due variabili A e B sono di tipo Byte, quindi possono assumere valori tra 0 e 255. La prima istruzione del blocco Try viene
quindi eseguita senza problemi, mentre la seconda, che cerca di assegnare a B il valore A * A, cioè 10000, causa un'eccezione
di overflow, che viene catturata dalla Catch sottostante. Se, invece di OverflowException avessimo specificato un altro tipo di
eccezione, come IndexOutOfRangeException, il blocco Catch non sarebbe stato eseguito e sarebbe apparso il classico
messaggio di errore di run-time di Visual Basic. L'oggetto ex, di tipo OverflowException, consente di recuperare varie
informazioni sull'errore. Nel codice sopra riportato abbiamo usato ex. Message per conoscere la descrizione dell'eccezione.
Se si vuole avere un unico Catch in grado di gestire tutti gli errori, è possibile definire l'oggetto ex di tipo Exception, il tipo
base da cui ereditano tutte le eccezioni. In alternativa è anche consentito omettere il tipo di eccezione che si vuole catturare
(quindi scrivere solo Catch), ma in questo modo non si ha la possibilità di ottenere informazioni sull'errore.
Supponiamo di essere in fase di chiusura di un programma e di avere alcune istruzioni che possono causare degli errori; per
esemplificare al massimo immaginiamo che le istruzioni in questione siano quelle viste in precedenza, ovvero le assegnazioni
dei valori alle variabili A e B. Se non siamo interessati a catturare questi errori, ma vogliamo che l'applicazioni termini in ogni
caso, usando un costrutto Try si deve scrivere:
Try
Dim A As Byte = 100
Dim B As Byte = A * A
Catch
'In realtà non si esegue nessuna operazione in caso di errori.
Finally
Me.Close()
http://guidepc.altervista.org
In questo caso il blocco Catch non esegue alcuna operazione. L'uso della parola chiave Finally ci assicura che le istruzioni
successive verranno sempre eseguite. Provate ad inserire questo codice nella routine che gestisce l'evento Click di un pulsante
e ad eseguire l'applicazione: il programma terminerà correttamente anche se togliete l'istruzione di assegnazione a B.
Possiamo finalmente terminare il nostro editor di testi aggiungendo la gestione degli errori. Alla fine della precedente Lezione
abbiamo accennato al fatto che gli errori possono verificarsi in fase di apertura o salvataggio dei dati. Trattandosi di operazioni
sui file, quindi, le possibili eccezioni sono tipo IOException. Modifichiamo le routine ApriFile e SalvaFile in modo da
prevedere le situazioni problematiche: in caso di errore, vogliamo che venga semplicemente visualizzata una finestra di
messaggio per informare l'utente del problema. Cominciando da ApriFile, dopo le modifiche il codice dovrebbe risultare il
seguente:
Private Sub ApriFile(ByVal NomeFile As String)
Dim Testo As String
Try
Dim FileReader As New System.IO.StreamReader(NomeFile)
'Legge l'intero file e lo salva nella variabile "Testo".
Testo = FileReader.ReadToEnd
FileReader.Close()
'Libera le risorse allocate con New.
FileReader = Nothing
txtTesto.Text = Testo
Catch ex As System.IO.IOException
MsgBox("Si è verificato un errore durante la lettura dal file: " & ex.Message)
End Try
End Sub
Tutto il codice che lavora con i file, essendo "a rischio", è stato inserito all'interno di un costrutto Try, in modo che un
eventuale problema provochi l'esecuzione del blocco Catch. Con questa piccola modifica la routine ApriFile è in grado di
gestire situazioni di errori senza terminare il programma. C'è però un'imperfezione nel nostro codice: se, ad esempio, l'errore si
verifica nel metodo ReadToEnd, l'istruzione FileReader = Nothing, che libera le risorse allocate dall'oggetto FileReader,
non viene eseguita. Per risolvere l'inconveniente, la prima idea che viene in mente è quella di ripetere tale istruzioni anche nel
Catch; tale soluzione è corretta, ma non sfrutta a fondo le potenzialità del costrutto Try. Abbiamo infatti detto che,
specificando un blocco Finally, il relativo codice verrà eseguito sia in caso di problemi, sia nella normale esecuzione del
programma. Usiamo quindi questa possibilità per assicurarci che l'istruzione FileReader = Nothing venga sempre eseguita. Per
raggiungere il nostro scopo basta modificare la routine ApriFile in modo che risulti:
Private Sub ApriFile(ByVal NomeFile As String)
Dim Testo As String
Dim FileReader As System.IO.StreamReader
Try
FileReader = New System.IO.StreamReader(NomeFile)
'Legge l'intero file e lo salva nella variabile "Testo".
Testo = FileReader.ReadToEnd
FileReader.Close()
txtTesto.Text = Testo
Catch ex As System.IO.IOException
MsgBox("Si è verificato un errore durante la lettura dal file: " & ex.Message)
Finally
'Libera le risorse allocate con New.
FileReader = Nothing
End Try
End Sub
Abbiamo dovuto spostare la dichiarazione dell'oggetto FileReader all'esterno del blocco Try, perché altrimenti la sua area di
validità era limitata alle istruzioni del blocco stesso, quindi non poteva essere utilizzata nel blocco Finally.
Le stesse modifiche vanno fatte alla routine SalvaFile, e sono quindi lasciate per esercizio.
Molte sarebbero le funzionalità ancora da implementare, ad esempio fare in modo che appaia un avviso se l'utente non ha
salvato le modifiche di un file, aggiungere la stampa, ecc. Ad ogni modo, le caratteristiche base sono state amp iamente trattate
nel corso dell’ultima parte, dando a tutti gli strumenti necessari per ritoccare il programma secondo la propria fantasia.
Con la prossima Lezione riprenderemo l'analisi dei principali controlli di Visual Basic .NET; in particolare, introdurremo il
richiestissimo controllo NotifyIcon, che consente di visualizzare un'icona nella barra delle applicazioni di Windows, vicino
http://guidepc.altervista.org
all'orologio. Nella stessa Lezione discuteremo anche della realizzazione di un programma privo di interfaccia utente, utile, ad
esempio, se si devono progettare applicazioni che rimangano costantemente in background nel sistema.
Il controllo NotifyIcon e le applicazioni senza interfaccia utente
Una delle funzionalità maggiormente richieste dai programmatori per Windows è quella di inserire un'icona della propria
applicazione nella System Tray, la parte della barra delle applicazioni vicino all'orologio. Fino alla versione 6 di Visual Basic
era necessario ricorrere a controlli OCX di terze parti oppure utilizzare le API di Windows per raggiungere questo scopo. Con
VB .NET finalmente Microsoft ha introdotto un controllo nativo per aggiungere un'icona alla System Tray: il controllo
NotifyIcon, forse uno dei più facili da utilizzare.
Le proprietà messe a disposizione da questo oggetto sono ridotte all'osso, ma d'altra parte sono le uniche di cui si ha bisogno.
ContextMenu permette di associare un menu contestuale all'icona;.
Icon consente di definire l'icona da visualizzare nella System Tray; è possibile utilizzare solo file di tipo ICO.
Text specifica il tooltip da visualizzare quando il puntatore del mouse si sofferma sull'icona per alcuni istanti.
Visible consente di visualizzare o nascondere l'icona. Gli eventi della NotifyIcon sono quelli relativi al mouse, quindi Click,
DblClick, MouseDown, MouseMove e MouseUp.
Per utilizzare questo controllo non serve sapere altro, quindi vediamo subito un esempio pratico che metta in luce le sue
peculiarità.
Vogliamo realizzare una piccola utilità che consenta di avviare in modo veloce i programmi Blocco note e Calcolatrice di
Windows: per fare questo è naturale pensare ad un programma che risiede nella System Tray, poiché in questo modo sarà
sempre visibile.
Questa volta, però, l'applicazione non avrà un'interfaccia utente, ma sarà composta da un unico modulo di Vis ual Basic. Dopo
aver creato la solita Windows Applications, quindi, selezionare con il tasto destro del mouse il file Form1.vb nel Solution
Explorer e fare clic sul comando Delete (Elimina), rispondendo Sì alla domanda successiva. Ora fare clic sul nome del
progetto (è visualizzato in grassetto e, se non diversamente specificato, ha la forma WindowsApplicationX, dove X è un
numero progressivo), selezionate il comando Add (Aggiungi) e quindi Add New Item (Aggiungi nuovo elemento); nella
finestra di dialogo che comparirà selezionare nella lista di destra Module (Modulo) e confermare con un clic sul pulsante
Open (Apri). Si aprirà l'editor del codice all'interno del nuovo modulo:
Module Module1
End Module
E' all'interno di questo modulo che scriveremo tutto il codice della nostra applicazione. La prima cosa da fare è dichiarare
esplicitamente gli oggetti che utilizzeremo, poiché non abbiamo a disposizione un'interfaccia grafica, quindi non possiamo
trascinare i controlli dalla casella degli strumenti. Nelle prime Lezioni abbiamo detto che nell'editor di VB .NET è visibile
l'intero codice dell'applicazione, compreso quello che determina la posizione e le proprietà iniziali degli oggetti, a differenza
delle versioni precedenti, in cui tali informazioni erano "nascoste" nell'intestazione dei file sorgente. Possiamo farci un'idea di
come sono organizzate queste strutture visualizzando la regione Windows Form Designer generated code di una qualsiasi form
realizzata con VB .NET. Dopo le funzioni New e Dispose, rispettivamente il costruttore e il distruttore della form, potremmo
trovare qualcosa del tipo:
Friend WithEvents Button1 As System.Windows.Forms.Button
Button2 As System.Windows.Forms.Button
Friend WithEvents
La parola chiave WithEvents specifica che l'oggetto dichiarato si riferisce all'istanza di una classe che può generare eventi.
Nell'esempio sopra mostrato, Button1 e Button2 sono di tipo Button, quindi possono generare gli eventi del mouse, della
tastiera, ecc. Notiamo che, usando WithEvents, nella ComboBox che visualizza gli oggetti della form (in alto a sinistra nella
finestra del codice) sono presenti sia Button1 sia Button2, quindi siamo in grado di selezionare un evento e scrivere il codice
relativo. Se proviamo a rimuovere la parola chiave WithEvents dalla dichiarazione di Button1, quest'ultimo sparirà dalla
ComboBox sopra citata, quindi non potremo più intercettare i suoi eventi. Se continuiamo a leggere la regione Windows Form
Designer generated code , troviamo la Sub InitializeComponent, in cui vengono impostate tutte le proprietà iniziali degli
oggetti.
Tornando al nostro programma, dobbiamo seguire i principi illustrati finora per creare gli oggetti che ci serviranno, in
particolare una NotifyIcon e un ContextMenu; quest'ultimo, è composto da varie voci (nel nostro esempio saranno 4), ciascuna
delle quali non è altro che un oggetto di tipo MenuItem. Il codice che dobbiamo scrivere all'interno del modulo è dunque il
seguente:
Friend
Friend
Friend
Friend
Friend
Friend
WithEvents
WithEvents
WithEvents
WithEvents
WithEvents
WithEvents
nfiIcona As NotifyIcon
MenuContestuale As ContextMenu
mnuContBloccoNote As MenuItem
mnuContCalcolatrice As MenuItem
mnuContSep0 As MenuItem
mnuContEsci As MenuItem
http://guidepc.altervista.org
La prima riga definisce la NotifyIcon, la seconda il menu contestuale, mentre le rimanenti i comandi del menu. Ora dobbiamo
impostare le proprietà iniziali di questi controlli. Per fare questo scriveremo una Sub dedicata, chiamandola ad esempio Init.
Cominciamo ad impostare le proprietà della NotifyIcon; dobbiamo innanzi tutto creare un'istanza
dell'oggetto usando la parola chiave New, quindi assegnare un'icona e il tooltip:
Private Sub Init()
nfiIcona = New NotifyIcon()
nfiIcona.Icon = New Icon("C:\Programmi\Microsoft Visual Studio .NET\Common7\Graphics\icons\Computer\key04.ico")
nfiIcona.Text = "Avvio applicazioni"
End Sub
Per assegnare l'icona abbiamo creato un nuovo oggetto di tipo Icon, utilizzando una delle icona fornite con Visual Studio
.NET; al suo posto è possibile utilizzare un qualsiasi file in formato ICO.
A questo punto possiamo già provare ad eseguire il programma. Prima però dobbiamo definire il punto di ingresso
dell'applicazione, cioè la routine che verrà eseguita nel momento in cui si lancia il progetto. Per fare questo, fare clic con il
tasto destro del mouse sul nome del progetto all'interno del Solution Explorer, quindi selezionare il comando Properties
(Proprietà); nella finestra Properties Pages (Pagine delle proprietà di ) cercare la ComboBox con etichetta Startup Object
(Oggetto di avvio) e impostarla su Sub Main. Ora non ci resta che scrivere questa Sub Main:
Sub Main()
Init()
nfiIcona.Visible = True
Application.Run()
End Sub
Dopo aver richiamato la routine Init, si visualizza l'icona nella System Tray. L'istruzione Application.Run(), come dice la
Guida in linea, fa in modo che l'applicazione entri in un ciclo in cui resta in attesa di messaggi; in pratica, con essa si indica
che il programma deve rimanere in esecuzione finché non si richiama il metodo Application.Exit().
Avviamo il progetto con il tasto F5: l'icona del programma verrà visualizzata nella barra delle applicazioni, a fianco
dell'orologio; spostando il mouse su di essa per alcuni istanti comparirà il tooltip che abbiamo impostato, ovvero "Avvio
applicazioni". Ora che abbiamo verificato il corretto funzionamento del nostro progetto, interrompiamolo con un clic sul
pulsante (Stop Debugging) e aggiungiamo il menu contestuale. Come prima useremo la Sub Init per impostare le proprietà
dei vari comandi:
MenuContestuale = New ContextMenu()
mnuContBloccoNote = New MenuItem()
mnuContCalcolatrice = New MenuItem()
mnuContSep0 = New MenuItem()
mnuContEsci = New MenuItem()
mnuContBloccoNote.Text = "Avvia &Blocco note"
mnuContCalcolatrice.Text = "Avvia &Calcolatrice"
mnuContSep0.Text = "-"
mnuContEsci.Text = "&Esci"
MenuContestuale.MenuItems.AddRange(New MenuItem() {mnuContBloccoNote, mnuContCalcolatrice, mnuContSep0,
mnuContEsci})
Le prime istruzioni dovrebbero essere ormai chiare. L'ultima inserisce i vari MenuItem all'interno del menu. Ora dobbiamo
associare il menu contestuale appena creato alla NotifyIcon; questo si ottiene facilmente con l'istruzione:
nfiIcona.ContextMenu = MenuContestuale
Eseguendo il programma a questo punto, se si fa clic con il tasto destro del mouse sull'icona nella barra delle applicazioni
comparirà il menu contestuale. L'ultima cosa che ci resta da fare è scrivere il codice da eseguire in risposta ai vari clic sui
comandi del menu. Ricordando le considerazioni fatte, si ottiene:
Public Sub mnuMenuContestuale(ByVal sender As Object, ByVal e As System.EventArgs) Handles mnuContBloccoNote.Click,
mnuContCalcolatrice.Click, mnuContEsci.Click
Select Case CType(sender, MenuItem).Text
Case "Avvia &Blocco note"
Shell("Notepad.exe", AppWinStyle.NormalFocus)
Case "Avvia &Calcolatrice"
Shell("Calc.exe", AppWinStyle.NormalFocus)
Case "&Esci"
nfiIcona.Visible = False
http://guidepc.altervista.org
Application.Exit()
End Select
End Sub
Per avviare un programma esterno si è usata l'istruzione Shell; per la sua sintassi si rimanda alla consultazione della Guida in
linea. Se l'utente seleziona il comando Esci, si nasconde l'icona nel System Tray e si richiama il metodo Application.Exit, che
come detto in precedenza termina l'applicazione. Il progetto completo è disponibile per il download facendo clic qui.
Con questa Lezione termina la nostra analisi dei controlli di Visual Basic .NET. In realtà sarebbero ancora molte le cose da
analizzare, primi tra tutti i controlli standard come la ListView e la ToolBar, ma quanto esposto finora è più che sufficiente
per permettere a chiunque sia interessato di approfondire autonomamente lo studio di questo linguaggio di programmazione.
Nelle rimanenti Lezioni del corso di concentreremo sulla realizzazione di un altro tipo di progetto con VB .NET: la Class
Library.
La Class Library
La Class Library La Class Library, un nuovo tipo di oggetto che
è possibile realizzare con Visual Basic .NET (ma anche con C#),
non è altro che una DLL contenente oggetti, metodi e proprietà
utilizzabili da qualunque programma ne faccia richiesta con
un'opportuna dichiarazione. Si tratta quindi di un componente
condiviso, che permette di usare le stesse funzionalità all'interno
di diverse applicazioni.
Per costruire una Class Library con VB .NET, seguire gli stessi
passi che abbiamo indicato per la Windows Applications, con la
differenza che in questo caso è necessario selezionare Class
Library dall'elenco dei tipi di applicazione. Così facendo si aprirà
l'editor del codice all'interno del file Class1.vb, che si presenta in
questa forma:
Public Class Class1
End Class
In questo blocco dobbiamo scrivere il codice della classe. Se ci limitiamo a fare questo, tuttavia, non potremmo riutilizzare la
Class Library così creata all'interno delle altre applicazioni: per riutilizzare una Class Library, infatti, è necessario che essa sia
contenuta all'interno di un Namespace. Modifichiamo quindi il codice creato automaticamente da Visual Basic .NET in modo
che la classe Class1 venga inserita in un Namespace, ad esempio di nome Test:
Namespace Test
Public Class Class1
End Class
End Namespace
Ora è finalmente possibile scrivere il codice della classe. Realizziamo, ad esempio, un componente che fornisca i metodi
necessari per conoscere l'intervallo di tempo che intercorre tra l'inizio di due azioni successive. Ci servirà un metodo per
avviare il timer, uno per fermarlo e uno per conoscere la differenza tra il tempo di inizio e quello di fine. Il codice completo
della Class Library sarà dunque il seguente:
Namespace Test
Public Class Class1
Private Inizio As Date
Private Fine As Date
Public Sub StartTimer()
Inizio = Now
End Sub
Public Sub StopTimer()
Fine = Now
End Sub
Public Function DiffTime() As Integer
Return Fine.Subtract(Inizio).Seconds
End Function
http://guidepc.altervista.org
End Class
End Namespace
La funzione Now, utilizzata in StartTimer e StopTimer, restituisce la data e l'ora di sistema.
Per calcolare la differenza usiamo il metodo Substract dell'oggetto Fine, che prende come
parametro la data da sottrarre, quindi leggiamo la sua proprietà Seconds per avere il tempo
espresso in secondi.
Notiamo che le variabili sono state dichiarate Private , mentre le Sub e le Function sono
Public: gli oggetti dichiarati Public o Friend sono utilizzabili all'esterno della classe,
mentre gli altri non sono visibili; in pratica, creando un oggetto di tipo Class1 all'interno di
una form, si ottiene:
Dim A As New Test.Class1()
A.StartTimer() 'Corretto, "StartTimer" è Public.
Dim B As Date = A.Inizio 'Errato, "Inizio" non è accessibile perché è Private.
Vogliamo rendere disponibile un'altra
funzionalità, una finestra di informazioni in cui sono contenuti una breve descrizione della Class Library e il nome dell'autore.
Per fare questo, innanzi tutto aggiungiamo una form al progetto; inseriamo poi i seguenti oggetti, impostandone anche le
proprietà:
Nome controllo
Proprietà
Valore
(tipo)
Label1 (Label)
Label 2 (Label)
Button1 (Button)
AutoSize
True
Font ->Bold
True
Text
Classe per il calcolo degli intervalli di
tempo
AutoSize
true
Text
Realizzata da (nome autore)
Text
&Chiudi
AcceptButton
Button1
FormBorderStyle FixedDialog
Form1 (Form)
MaximizeBox
False
MinimizeBox
False
StartPosition
CenterScreen
Text
Informazioni
L'unica riga di codice da scrivere in questa form è relativa all'evento Click del pulsante Button1, per chiudere la finestra:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.Close()
End Sub
Ora dobbiamo estendere la nostra Class Library aggiungendo una Sub per richiamare tale finestra. Definiamo perciò il metodo
AboutBox:
Public Sub AboutBox()
Dim frm As New Form1()
frm.ShowDialog()
frm = Nothing
End Sub
Abbiamo così terminato la creazione della Class Library, che potete prelevare facendo clic qui. Se ora proviamo ad eseguirla
premendo il tasto F5, apparirà una finestra con il seguente messaggio: "A project with an Output Type of Class Library
cannot be started directly" ("Un progetto che ha come output una Class Library non può essere eseguito direttamente). Tale
comportamento è normale: Abbiamo detto che una Class Library è un componente riutilizzabile da tutte le applicazioni che ne
facciano richiesta; di conseguenza, non è un progetto autonomo, pertanto non può essere avviato direttamente. Per evitare che
compaia il messaggio sopra citato, anziché compilare con il tasto F5 è necessario selezionare il comando Build Solution (Crea
Soluzione) dal menu Build (Crea), oppure premere la combinazione di tasto CTRL+SHIIFT+B : in questo modo, infatti, dopo
la compilazione Visual Basic non tenterà di avviare il progetto (cosa che invece avviene premendo il tasto F5).
http://guidepc.altervista.org
Nella prossima Lezione vedremo come è possibile utilizzare una Class Library all'interno di altri progetti.
Utilizzare una Class Library in un progetto
Nella precedente Lezione ci siamo fermati alla fase di compilazione della Class Library.
Ora vedremo cosa si deve fare per usarla in un progetto. Ricordiamo che il risultato della
compilazione di un progetto in VB .NET, sia esso una Windows Application, una Class
Library o qualsiasi altro tipo di progetto, viene posto nella sottocartella bin della cartella del
progetto; nel caso della Class Library appena creata, la compilazione ha creato nella cartella
bin un file di nome ClassLibrary1.dll: è questo il componente che possiamo riutilizzare
nelle nostre applicazioni.
Creiamo quindi una nuova
Windows Application e
aggiungiamo ad essa un riferimento a tale Class Library. Per fare
questo, fare clic con il tasto destro del mouse sul nome del progetto
all'interno del Solution Explorer; dal menu contestuale selezionare
il comando Add Reference (Aggiungi riferimento). Si aprirà la
finestra di dialogo Add Reference, divisa in tre schede: .NET
include tutte le componenti del framework .NET che è possibile
riferire nel progetto; COM raggruppa gli oggetti di tipo COM
installati nel sistema (in pratica contiene i Componenti delle
precedenti versioni di Visual Basic); Projects (Progetti) visualizza
tutti i progetti utilizzabili nel progetto corrente. Inizialmente la lista
corrispondente a quest'ultima scheda è vuota: è qui che dobbiamo
aggiungere il riferimento alla Class Library. Fare clic sul pulsante
Browse (Sfoglia), portarsi nella cartella della Class Library e aprire
la sua sottocartella bin. Ora selezionare il file ClassLibrary1.dll e
confermare con un clic sul pulsante Open (Apri).
Premere nuovamente OK nella finestra di
dialogo Add Reference per aggiungere il nuovo riferimento al progetto. A questo punto il
Solution Explorer dovrebbe essere simile a quello mostrato in figura.
Notiamo che, sotto la voce References (Riferimenti) è stato aggiunto ClassLibrary1. Ora
possiamo finalmente scrivere il codice per utilizzare la nuova classe. Innanzi tutto
dobbiamo far sapere a Visual Basic che la form importa il namespace Test di
ClassLibrary1; tale obiettivo si raggiunge utilizzando la parola chiave Imports:
Imports ClassLibrary1.Test
Questa dichiarazione deve precedere la definizione della form. E' ora possibile istanziare le classi contenute nel namespace
Test:
Dim C As New Class1()
In tal modo attraverso l'oggetto C si ha la possibilità di accedere alle proprietà e ai metodi Public o Friend esposti da Class1.
Se non avessimo usato l'istruzione Imports, per creare un oggetto di tipo Class1 sarebbe stato necessario specificare tutto il
percorso di questa classe, cioè:
Dim C As New ClassLibrary1.Test.Class1()
In pratica la parola chiave Imports permette di abbreviare le dichiarazioni, indicando a Visual Basic all'interno di quali
namespace deve cercare le classi che si utilizzano nel progetto.
In fase di compilazione il file ClassLibrary1.dll verrà automaticamente copiato all'interno della directory bin del progetto che
lo utilizza. Questo particolare è molto importante: per distribuire un'applicazione che utilizza una Class Library esterna, è
sufficiente copiare quest'ultima nella stessa cartella contenente il programma: non è necessario registrare la Class Library nel
sistema utilizzando il programma RegSvr32.
Proviamo adesso ad utilizzare la Class
Library che abbiamo realizzato nella precedente Lezione. Voglia mo realizzare un programma che controlli se un certo numero
è primo: insieme alla risposta vogliamo che venga anche restituito il tempo impiegato per tale controllo. Dopo aver importato
la Class Library come spiegato in precedenza, inseririamo nel form i seguenti oggetti:
Nome controllo (tipo)
Proprietà
Valore
http://guidepc.altervista.org
Label1 (Label)
AutoSize
True
Text
Numero:
TextBox1 (TextBox)
Text
<vuoto>
Button1 (Button)
Text
Controlla
Button2 (Button)
Text
Informazioni su Class1
Form1 (Form)
AcceptButton
Button1
Passiamo alla scrittura del codice, cominciando dalla funzione che, dato un numero, determina se questo è primo oppure no:
Public Function Primo(ByVal N As Integer) As Boolean
Dim I As Integer
Dim L As Integer = Math.Sqrt(N)
For I = 2 To L
If N Mod I = 0 Then Return False
Next
Return True
End Function
L'unica cosa da notare è l'uso della classe Math, che mette a disposizione alcune funzioni matematiche; nel nostro caso,
Math.Sqrt restituisce la radice quadrata del numero. La parte più importante del programma è contenuta all'interno della
routine che gestisce l'evento Click su Button1 :
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If IsNumeric(TextBox1.Text) = True Then
Dim Tempo As New Class1()
Dim Risultato As Boolean
Dim Intervallo As Integer
Tempo.StartTimer() 'Avvia il timer.
Risultato = Primo(CInt(TextBox1.Text))
Tempo.StopTimer() 'Ferma il timer.
Intervallo = Tempo.DiffTime
MsgBox("Il numero " & CInt(TextBox1.Text) & " è primo? " & Risultato & _ "." & vbCrLf & vbCrLf & "Tempo di
esecuzione: " & Intervallo & " secondi.")
Tempo = Nothing
End If
End Sub
Innanzi tutto controlliamo se nella TextBox è stato effettivamente digitato un numero, usando la funzione IsNumeric. In tal
caso creiamo una nuova istanza di Class1, avviamo il timer e controlliamo se il numero è primo; subito dopo fermiamo il
timer, memorizziamo nella variabile Intervallo il tempo impiegato e visualizziamo una finestra di informazioni sull'esito
dell'operazione. Ora non ci resta che aggiungere il codice relativo al Button2:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim Informazioni As New Class1()
In formazioni.AboutBox()
Informazioni = Nothing
End Sub
Dopo la creazione di una istanza di Class1, in questo caso richiamiamo il metodo AboutBox per visualizzare la finestra
contenente le informazioni sulla classe.
Compilare e distribuire un’applicazione
Concludiamo il nostro corso su Visual Basic .NET con alcune
considerazioni sulla compilazione e sulla distribuzione di
un'applicazione. A differenza di quanto avveniva con le versioni
precedenti, con VB .NET il file eseguibile del proprio progetto non
deve essere più creato esplicitamente, selezionando il comando Crea
.exe dal menu File; ora l'eseguibile è creato o aggiornato ad ogni
compilazione e salvato nella sottocartella bin della cartella che
contiene il progetto. Per modificare le proprietà di un progetto, è
necessario fare clic con il tasto destro del mouse sul nome del progetto
stesso all'interno del Solution Explorer e selezionare il comando
http://guidepc.altervista.org
Properties (Proprietà). Si aprirà una finestra di dialogo composta di diversi parti raggiungibili attraverso la vista ad albero
sulla sinistra.
Nella sezione General, la casella di testo Assembly name permette di impostare di impostare il
nome dell'eseguibile (senza estensione, che verrà aggiunta automaticamente);
Output type specifica il tipo di applicazione che si sta creando e viene impostato quando di
seleziona il tipo di progetto nella finestra New Project (Nuovo progetto);
Startup object consente di definire il punto di ingresso dell'applicazione, ovvero il punto da cui
inizierà l'esecuzione del programma quando lo avviamo.
La scheda Build, tra le altre opzioni, permette di impostare l'icona dell'applicazione, agendo sul valore di Application Icon.
Notiamo che in questa finestra non si possono specificare le informazioni sul file, come Titolo, Descrizione, Copyright e
versione. Per fare questo, è necessario aprire con un doppio clic il file AssemblyInfo.vb, sempre presente in ogni progetto di
Visual Basic .NET e visibile nel Solution Explorer. Tra le informazioni contenute in esso, in formato XML, troviamo anche:
<Assembly: AssemblyTitle("")>
<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("")>
<Assembly: AssemblyCopyright("")>
<Assembly: AssemblyTrademark("")>
Per ognuno di questi attributi è possibile specificare un valore, inserendolo tra le virgolette: tale valore comparirà poi nella
scheda Versione delle proprietà dell'eseguibile. Ad esempio, per indicare il titolo del programma e il copyright bisogna
modificare gli attributi AssemblyTile e AssemblyCopyright:
<Assembly: AssemblyTitle("Programa di prova")>
<Assembly: AssemblyCopyright("Realizzato da Marco Minerva")>
Anche per impostare il numero di versione del programma è necessario modificare un altro attributo di AssemblyIn fo.vb:
<Assembly: AssemblyVersion("1.0.*")>
Il primo numero è il Major Version, cioè il numero principale della versione; poi ci sono il Minor Version, il Build Number
e la Revision. Ad esempio, in 5.2.0.8, 5 è il Major Version, 2 il Minor Version, 0 il Build Number e 8 la Revision. Se invece di
un numero si specifica un asterisco (come mostrato sopra per il Build Number), il numero corrispondente verrà incrementato
ad ogni compilazione.
Visual Basic .NET introduce il concetto di configurazioni di rilascio, che dovrebbe essere già noto a chi ha utilizzato Visual
J++; esso determina il modo in cui un'applicazione viene compilata. Di default sono disponibili due opzioni: Debug e Release.
Usando la prima, oltre al programma vero e proprio viene generato un file PDB , nella stessa cartella dell'eseguibile, che
contiene informazioni di debug sul progetto. Sul programma, inoltre, non vengono effettuate ottimizzazioni, dal momento che
esse renderebbero più difficile il debug stesso. Con la configurazione Release, invece, non si genera il file PDB e il programma
è completamente ottimizzato.
Una delle differenze più evidenti è dunque che un progetto compilato in configurazione Release genera un eseguibile più
piccolo di quello creato a partire dallo stesso progetto ma in modalità Debug.
Di conseguenza, è bene usare la configurazione
Debug quando si sviluppa un'applicazione, per poi passare alla configurazione Release quando si genera l'eseguibile da
distribuire. Per passare da una modalità all'altra è possibile utilizzare l'apposita ComboBox nella barra degli strumenti standard.
Per distribuire un'applicazione realizzata con Visual Basic .NET non è più necessario inserire nel Registro di configurazione
tutti i riferimenti agli oggetti ed ai controlli esterni utilizzati: è sufficiente copiare le dipendenze del programma, ad esempio i
file DLL che contengono le Class Library riferite, nella stessa cartella dell'eseguibile principale: sarà poi il runtime a
localizzarle e caricarle correttamente. Da questo punto di vis ta, quindi, l'installazione di un programma è notevolmente
semplificata. Il rovescio della medaglia è che i programmi creati con Visual Basic .NET, allo stesso modo di quelli realizzati
con C#, per funzionare necessitano del runtime del framework .NET: si tratta di un pacchetto di installazione delle dimensioni
di circa 20 MB, fornito assieme a Visual Studio .NET e prelevabile anche sul sito Microsoft.
Questo rende difficoltosa la distribuzione di applicazioni via Internet per chi non dispone di connessioni a banda larga. D'altra
parte, una volta installato tale runtime sarà possibile utilizzare tutti i programmi realizzati con gli strumenti di sviluppi inclusi
in Visual Studio .NET.
Si conclude qui il nostro corso su Visual Basic .NET. Siamo partiti dall'analisi delle novità più significative di questo
ambiente di sviluppo, per poi analizzare alcuni dei più importanti controlli standard messi a disposizione. Infine, ci siamo
dedicati alle peculiarità del linguaggio, come la creazione di una Class Library e il suo utilizzo all'interno di altri progetti. Non
è stato possibile approfondire molto i vari concetti esposti, a causa della mole di innovazioni introdotte, che rischiano persino
http://guidepc.altervista.org
di confondere chi non mai utilizzato altri linguaggi di programmazione. Il bagaglio di conoscenze acquisite costituisce
comunque una solida base da cui è possibile partire per approfondire la conoscenza del nuovo ambiente e di tutte le sue
funzionalità.
http://guidepc.altervista.org