Le API di Windows: differenze tra VB 6 e VB .Net (2a parte)
a cura di Alessandro Del Sole (requisiti: conoscenza intermedia di VB6)

Premessa
In questo articolo vorrei integrare quanto descritto nel precedente circa le varie differenze nell'utilizzo delle API tra VB 6 e il nuovo .Net, facendo un più approfondito il discorso sui tipi di dato in VB .Net.

Poiché l'Application Programming Interface non si compone solo di funzioni, ma anche di tipi (oltre che di costanti), questa volta descriverò come avvengono le dichiarazioni dei tipi (cosa rivoluzionata in .Net e che tornerà utile anche nel caso non utilizziae i tipi API) e l'utilizzo dell'attributo DllImport.

I tipi di dato in Visual Basic .Net
In VB .Net uno dei cambiamenti inerenti il linguaggio riguarda i tipi di dato. E' stato soppresso il tipo di dato Any in modo che lo sviluppatore debba utilizzare dati precisi, inoltre alcuni tipi di dato sono stati modificati come riassunto nella seguente tabella:

Visual Basic 6 Visual Basic .Net
Integer Short
Long Integer
Currency Decimal
  Char
  Long
Questa (molto) sintetica tabella evidenzia alcune differenze tra i tipi di dato in Vb 6 e Vb .Net, quindi attenzione a quando effettuate il cosiddetto porting del codice da una all'altra versione.
Una funzione API dichiarata in VB 6 utilizzerà parametri quasi sempre di tipo Long di conseguenza in VB .Net il tipo di dato corretto da utilizzare sarà Integer.
In particolare per i tipi numerici il cambiamento è avvenuto anche in considerazione delle CPU di nuova generazione, in grado di elaborare numeri decisamente più grandi.

Le dichiarazioni dei tipi: i vecchi UDT e le nuove strutture
Come ben sapete, numerose funzioni API utilizzano, come parametro, un tipo di dato particolare, il tipo struttura, composto da più membri a loro volta di tipo diverso. In Visual Basic 6 un tipo di dato di questo genere viene definito UDT (User Defined Type), e viene creato utilizzando il costrutto Type...End Type. Riporto a titolo esemplificativo la dichiarazione del tipo RGBQUAD utilizzato da alcune delle API grafiche:

  Type RGBQUAD
    rgbBlue As Byte
    rgbGreen As Byte
    rgbRed As Byte
    rgbReserved As Byte
  End Type

Il tipo RGBQUAD, utilizzato per la definizione dei colori utilizzando le componenti RGB (rosso, verde e blu), espone 4 membri di tipo Byte. Visual Basic .Net consente la creazione di tipi user-defined attraverso il costrutto Structure...End Structure.
In apparenza sembra solo un cambiamento di parole chiave, in realtà la nuova versione del linguaggio impone cambiamenti notevoli nella sintassi e (ovviamente...) potenzia la creazione di propri tipi di dato.
Prima di passare ad un esempio pratico, va sottolineato che ogni membro della struttura, ad esempio nel caso precedente rgbBlue, deve essere dichiarato con Dim, Private o Public, in modo da definirne le possibilità di accesso da parte dell'utente.
In più è stata data la possibilità allo sviluppatore di aggiungere all'interno di una struttura una o più funzioni!
Ma vediamo come in Visual Basic .Net viene trasformato il codice precedente:

  Structure RGBQUAD
    Dim rgbBlue As Byte
    Dim rgbGreen As Byte
    Dim rgbRed As Byte
    Dim rgbReserved As Byte
  End Type


Non vorrei dilungarmi sulla definizione di array all'interno di tipi, in primo luogo perché è un concetto non semplice, in secondo luogo perché anch'io sto continuando a documentarmi, comunque Vb .Net non consente di definire delle matrici ben precise all'interno di una struttura, ma dovrà essere fatto successivamente. Sottolineo, inoltre, che tutte le matrici hanno base zero pertanto il vecchio codice VB 6

  Dim x(0 To 10)

non sarà più corretto. Ad esempio il codice seguente genera errore:

  Structure RGBQUAD
    Dim rgbBlue(2) As Byte
    ...

Una soluzione al problema è quella di definire la matrice una volta creata un'istanza della struttura, più o meno in questo modo:

  Structure Prova
    Dim Elemento() As Byte
  End Structure

  Private Sub Genera()
    Dim P as Prova
    P.Elemento = New Byte() {2} 'Il numero è tra parentesi graffe
  End Sub

Poiché lo scopo dell'articolo non è quello di illustrare la creazione di matrici, vi rimando per questo ad altri approfondimenti, l'importante è avere capito come avviene la creazione di un tipo di dato definito dall'utente, cosa molto frequente se si utilizzano le dichiarazioni API "vecchio stile", per intenderci nella modalità VB 6 anche in VB .Net, se si vuole rendere meno traumatico il passaggio ai nuovi NameSpaces e alle classi del .Net Framework.

L'attributo
Visual Basic .Net fornisce un modo migliore per dichiarare delle funzioni contenute in delle librerie DLL esterne, l'attributo .
Tale attributo permette di dichiarare la funzione esterna senza dover implementare alcun tipo di codice, in quanto si sottintende che l'implementazione sia presente nella Dll stessa.
Per poterlo utilizzare è necessario includere la seguente riga di codice nelle dichiarazioni del modulo (ad esempio in AssemblyInfo.vb):

  Imports System.Runtime.InteropServices

Ad esempio supponiamo di voler dichiarare la funzione Api GetPixel per leggere il colore di un pixel alle coordinate specificate.

  ' Dichiarazione in VB 6


  Declare Function GetPixel Lib "gdi32" Alias "GetPixel" _
    (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long

  ' Dichiarazione in VB .Net con l'istruzione Declare

  Declare Function GetPixel Lib "gdi32" Alias "GetPixel" _
    (ByVal hdc As Integer, ByVal x As Integer, ByVal y As Integer) As Integer

  ' Dichiarazione in VB .Net con 

   Function GetPixel(ByVal hdc As Integer, _
                            ByVal x As Integer, ByVal y As Integer) As Integer
                         'Niente da digitare
                       End Function

L'utilizzo della funzione rimarrà invariato.

Disclaimer :o)
Alla fine di questo articolo vorrei scusarmi per eventuali imprecisioni od imperfezioni, ma come per molti di voi anche per me il mondo di Visual Basic .Net è una continua scoperta, di conseguenza è possibile che io sbagli qualcosa anche se cerco di limitare i danni!

Per eventuali quesiti, critiche o suggerimenti, vi ricordo comunque che potete contattarmi al mio indirizzo e-mail.