- 12 Aprile 2007
- 3.227
- 0
- Miglior risposta
- 0
[FONT=Arial, Helvetica, sans-serif]
[/FONT]
[FONT=Arial, Helvetica, sans-serif]Prima di iniziare[/FONT]
[FONT=Arial, Helvetica, sans-serif]Occorre all'inizio cercare nel menu di Visual Basic Strumenti\Opzioni le voci Salva con conferma e Dichiarazioni di variabili obbligatoria, di conseguenza settarle di modo che l'istruzione Option Explicit appaia in tutti gli script e ad ogni esecuzione del vostro programma vi verrà chiesto se desiderate salvare il vostro lavoro (e voi lo farete per sicurezza). Poi tenete a portata di mano il Visualizzatore testo API presente nella cartella di VB. [/FONT]
[FONT=Arial, Helvetica, sans-serif]Visione d'insieme[/FONT]
[FONT=Arial, Helvetica, sans-serif]Avviate il Visualizzatore testo API e dal menu File\Carica file di testo... caricate il file Win32api.txt, di seguito eseguite dal menu File\Converti testo in database... seguendo le istruzioni e caricate quest'ultimo.
In esso vi sono tre ListBox (Tipo API, Elementi disponibili e Elementi selezionati) e tre Pulsanti (Aggiungi, Rimuovi e Copia). Se cliccate su una delle voci in Elementi disponibili il pulsante Aggiungi si attiva e dopo averlo premuto apparirà nelle voci di Elementi selezionati: potrete rimuoverla (Rimuovi) dopo averla selezionata oppure copiarla (Copia) negli appunti, da dove sarà possibile inserirla nel vostro progetto VB con Incolla.
Questo piccolo programmino fornito nel pacchetto serve a facilitare la digitazione delle dichiarazioni API desiderate, poiché, essendo alcune piuttosto lunghette, ci si può sbagliare con facilità.[/FONT] [FONT=Arial, Helvetica, sans-serif]Che cosa sono le API[/FONT]
[FONT=Arial, Helvetica, sans-serif]Esse sono delle funzioni che possono a volte non avere un valore di ritorno; le stesse assomigliano in un certo qual modo alle chiamate DOS/BIOS che qualche volta avrete visto nei programmi assembly o inline in quelli C++ o TPascal: di fatto esse sono le funzioni di sistema che di solito vengono usate in Visual C++, Borland C++, Watcom C++, Visual Age for C++, etc. È il Sistema Operativo che dialoga con noi offrendoci tutto ciò che esso ci mostra: le finestre, i movimenti, i suoni la grafica, il controllo del mouse, etc.[/FONT]
[FONT=Arial, Helvetica, sans-serif]Adesso s’inizia[/FONT]
[FONT=Arial, Helvetica, sans-serif]Chiarito questo, se avrete lasciato la voce Dichiarazioni nella ListBox Tipo API, dopo aver cercato la voce GetWindowsDirectory e averla aggiunta in quella in basso, potrete notare che essa è composta da più parti: (è una funzione API che ci restituisce la directory effettiva in cui è situato Windows)
- Questa è la funzione richiesta [/FONT]
[FONT=Courier New, Courier, mono]Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long[/FONT]
[FONT=Arial, Helvetica, sans-serif]- Qui di seguito la spiegazione [/FONT]
[FONT=Courier New, Courier, mono]Declare Function[/FONT] [FONT=Arial, Helvetica, sans-serif]la dichiarazione vera e propria[/FONT] [FONT=Courier New, Courier, mono]GetWindowsDirectory Lib "kernel32"[/FONT] [FONT=Arial, Helvetica, sans-serif]il nome della funzione e la libreria d’origine [/FONT] [FONT=Courier New, Courier, mono]Alias "GetWindowsDirectoryA"[/FONT] [FONT=Arial, Helvetica, sans-serif]l'alias, cioè il nome sostitutivo, dato che a volte può essere identico a una istruzione VB[/FONT] [FONT=Arial, Helvetica, sans-serif]Noterete che essa termina con una ‘A’ Essa sta ad indicare ANSI , cioè set dei caratteri ad un solo byte, usato per il Win32 da Windows95. Mentre se andrete a spulciare il file Win32api.txt sotto Windows NT ne troverete un altro un altro col suffisso ‘W’ che sta ad indicare WIDE, esteso, cioè appartiene al set dei caratteri Unicode di questo SO. Di questo se ne preoccupa sia il compilatore, che il programma di installazione VB, ma voi dovete sapere che il VB utilizza quello di Windows NT ed è costretto ad operare la conversione sotto W95.[/FONT]
[FONT=Courier New, Courier, mono](ByVal lpBuffer As String, ByVal nSize As Long)[/FONT] [FONT=Arial, Helvetica, sans-serif]gli argomenti[/FONT] [FONT=Arial, Helvetica, sans-serif]La prima è una stringa terminante con zero che serve da buffer (in realtà un vettore), mentre la seconda è la grandezza della stringa stessa, di cui il SDK ci informa che non deve superare 144. Ora poiché in C/C++ i vettori (vengono usati per formare stringhe, quest’ultime non esistono in C/C++) hanno gli indici che iniziano con zero (0), noi la dovremo inizializzare a 145, perciò dovremo con un accorgimento adattare la nostra stringa a al vettore del C/C++ e di seguito prelevare il testo sottraendolo dagli zeri successivi. Ambedue sono argomenti che devono essere passati per valore (byVal), cioè la nostra stringa conterrà il valore cercato.
[/FONT]
[FONT=Courier New, Courier, mono]As Long[/FONT] [FONT=Arial, Helvetica, sans-serif]il valore di ritorno[/FONT] [FONT=Arial, Helvetica, sans-serif]di cui il SDK ci informa che è la grandezza, in bytes, della stringa (meglio vettore) contenuta in lpbuffer, mentre l’eventuale errore dovrà essere prelevato tramite la funzione GetLastError(…)
La dichiarazione andrà messa in un modulo standard e dovrà essere richiamata dalla sub desiderata. Ciò che noterete più avanti è l’uso di una particolare tecnica per dimensionare una stringa di modo tale che venga usata come buffer compatibile col tipo vettore C/C++: prima la si dichiara moltiplicandola per la grandezza desiderata, poi la si riempie di zero con la funzione interna Vb string(…, …), così come si potrà notare di seguito:[/FONT]
[FONT=Courier New, Courier, mono]Dim Risult&[/FONT] [FONT=Courier New, Courier, mono]‘questo è il valore di ritorno della funzione[/FONT] [FONT=Courier New, Courier, mono]Dim WinDir As String * 145[/FONT] [FONT=Courier New, Courier, mono]‘dimensionamento della stringa[/FONT] [FONT=Courier New, Courier, mono]WinDir = String(256, 0)[/FONT] [FONT=Courier New, Courier, mono]‘ la stringa viene riempita di zero[/FONT] [FONT=Courier New, Courier, mono]Risult& = GetWindowsDirectory (WinDir, 145)[/FONT] [FONT=Courier New, Courier, mono]‘viene chiamata[/FONT] [FONT=Courier New, Courier, mono]Print "valore di ritorno = " & Risult&[/FONT] [FONT=Courier New, Courier, mono]‘stampa il valore di ritorno[/FONT] [FONT=Courier New, Courier, mono]Print "Directory Windows = " & [/FONT][FONT=Courier New, Courier, mono]StrNulToStr[/FONT][FONT=Courier New, Courier, mono](WinDir, Risult&)[/FONT] [FONT=Courier New, Courier, mono]‘stampa directory[/FONT] [FONT=Arial, Helvetica, sans-serif]Nella seconda istruzione di stampa (print …) avrete notato due cose strane: un richiamo a una funzione di cui non si è parlato prima e il fatto che il valore di ritorno desiderato da noi, che avrebbe dovuto farci conoscere il percorso in cui è situato Windows, non sta dove ce lo saremmo aspettato, cioè nella variabile[/FONT][FONT=Arial, Helvetica, sans-serif] Risult&[/FONT][FONT=Arial, Helvetica, sans-serif]!
Poco fa abbiamo detto che il C/C++ non avendo le stringhe utilizza dei vettori di bytes per simularle e ciò in qualche modo al VB potrebbe anche star bene, in quanto comunque ha utilizzato una stringa per avere il valore, ma ciò che il VB non potrà mai fare è trattare delle stringhe in cui, oltre ai caratteri, vi sono degli zero: di fatto per lui sono un po’ indigesti. Perciò bisogna implementare una funzione che tolga gli zero e restituisca una stringa pura VB sapendo che già Risult& è la lunghezza di essa, cioè in tal modo:
[/FONT]
[FONT=Courier New, Courier, mono]' funzione che trasforma un stringa terminante con zero
' in una senza[/FONT][FONT=Courier New, Courier, mono]
Public Function StrNulToStr(ByVal Str_Nul$, ByVal Size As Long) As String
Dim k, SizeKont As Long
SizeKont = Size
If Size = 0 Then SizeKont = 256[/FONT][FONT=Courier New, Courier, mono] ' valore di default se non si passa[/FONT][FONT=Courier New, Courier, mono]
[/FONT][FONT=Courier New, Courier, mono] ' alcun argomento per la lunghezza desiderata[/FONT][FONT=Courier New, Courier, mono]
For k = 1 To SizeKont
If Asc(Mid(Str_Nul$, k, 1)) = 0 Then Exit For[/FONT][FONT=Courier New, Courier, mono] ' per sicurezza quando vi è zero è meglio uscire[/FONT][FONT=Courier New, Courier, mono]
StrNulToStr = StrNulToStr + Mid(Str_Nul$, k, 1)
Next
End Function[/FONT]
[FONT=Arial, Helvetica, sans-serif]Per ciò che riguarda il secondo dubbio bisogna chiarire che voi probabilmente siete abituati a pensare che le funzioni abbiano sempre la sintassi classica y=f(x), in questo caso è sufficiente inserire il valore desiderato in x per avere un risultato a lui dipendente in y, ma con le API di Windows non funziona così: il valore y può essere il risultato dell’esito della funzione (è andata bene o male?) o qualcos’altro (in questo caso la grandezza del vettore), le funzioni dovrete sempre pensarle come le chiamate Dos/Bios in Assembly, laddove si parla di servizi del Sistema Operativo. In realtà si tratta di un passaggio di parametri per riferimento, ciò che in VB equivale al ByRef, mentre con ByVal si vuole indicare che noi desideriamo passare l’argomento per valore, tutto come il VB normale: in fondo si tratta solo di funzioni!
Inoltre se vi siete trovati di fronte funzioni il cui nome terminano con …ex, nel caso in cui il SDK ve lo chieda espressamente, usate queste. Queste sono funzioni che rappresentano un aggiornamento delle corrispondenti senza il suffisso …ex in Win32, a volte con funzionalità in più.[/FONT]
[FONT=Arial, Helvetica, sans-serif]Come chiamare le funzioni[/FONT]
[FONT=Arial, Helvetica, sans-serif]Nel microesempio precedente abbiamo chiamato la funzione secondo la consuetudine, d’altra parte se proprio il valore di ritorno non ci fosse utile, avremmo potuto chiamarlo anche con Call, infatti la routine di conversione da stringa con zero a stringa pura da me proposta prevede già un controllo sulla fine del vettore, così potremo modificare il programma in questo modo con i medesimi risultati:[/FONT]
[FONT=Courier New, Courier, mono]Dim Risult&
…
Call GetWindowsDirectory (WinDir, 145)
Print "Directory Windows = " & StrNulToStr(WinDir, 0)[/FONT]
[FONT=Arial, Helvetica, sans-serif]È più semplice, vero? Tenete presente a questo punto che molte volte il SDK vi chiederà proprio di tener in conto che il risultato del vostra richiesta è prelevabile da una altra funzione: infatti capita spesso che i possibili errori vengano prelevati tramite la funzione GetLastError(void).
[/FONT]
[FONT=Arial, Helvetica, sans-serif]I tipi[/FONT]
[FONT=Arial, Helvetica, sans-serif]Sicuramente il maggior dubbio vostro è dato dal termine lpbuffer: che sarà mai ‘sta roba? Questo è un buffer che ha come suffisso lp, cioè un puntatore a una struttura o voce di dati. Insomma questa è la notazione Ungherese. Nella tabella seguente vi sono i tipi e il prefisso corrispondente per Win32:[/FONT][FONT=Arial, Helvetica, sans-serif]
[/FONT] [FONT=Arial, Helvetica, sans-serif]tipo[/FONT] [FONT=Arial, Helvetica, sans-serif]prefisso[/FONT] [FONT=Arial, Helvetica, sans-serif]commento[/FONT] [FONT=Arial, Helvetica, sans-serif]bit[/FONT]
[FONT=Arial, Helvetica, sans-serif]tipo[/FONT] [FONT=Arial, Helvetica, sans-serif]prefisso[/FONT] [FONT=Arial, Helvetica, sans-serif]commento[/FONT] [FONT=Arial, Helvetica, sans-serif]bit[/FONT] [FONT=Arial, Helvetica, sans-serif]bool[/FONT] [FONT=Arial, Helvetica, sans-serif]b[/FONT] [FONT=Arial, Helvetica, sans-serif]boolean(= 0/1)[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]byte[/FONT] [FONT=Arial, Helvetica, sans-serif]ch[/FONT] [FONT=Arial, Helvetica, sans-serif]int unsigned[/FONT] [FONT=Arial, Helvetica, sans-serif]8[/FONT] [FONT=Arial, Helvetica, sans-serif]char[/FONT] [FONT=Arial, Helvetica, sans-serif]ch[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]8[/FONT] [FONT=Arial, Helvetica, sans-serif]tchar[/FONT] [FONT=Arial, Helvetica, sans-serif]ch[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]8/16[/FONT] [FONT=Arial, Helvetica, sans-serif]farproc[/FONT] [FONT=Arial, Helvetica, sans-serif]lpfn[/FONT] [FONT=Arial, Helvetica, sans-serif]puntatore far[/FONT] [FONT=Arial, Helvetica, sans-serif]32 [/FONT] [FONT=Arial, Helvetica, sans-serif]handle[/FONT] [FONT=Arial, Helvetica, sans-serif]h[/FONT] [FONT=Arial, Helvetica, sans-serif]handle windows[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]int[/FONT] [FONT=Arial, Helvetica, sans-serif]n[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]short[/FONT] [FONT=Arial, Helvetica, sans-serif]n[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]16[/FONT] [FONT=Arial, Helvetica, sans-serif]long[/FONT] [FONT=Arial, Helvetica, sans-serif]l[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lp[/FONT] [FONT=Arial, Helvetica, sans-serif]lp [/FONT] [FONT=Arial, Helvetica, sans-serif]pointer long[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lpint[/FONT] [FONT=Arial, Helvetica, sans-serif]pli[/FONT] [FONT=Arial, Helvetica, sans-serif]pointer[/FONT][FONT=Arial, Helvetica, sans-serif] long[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lpstr[/FONT] [FONT=Arial, Helvetica, sans-serif]lpsz[/FONT] [FONT=Arial, Helvetica, sans-serif]pointer long(nul str)[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lpcstr[/FONT] [FONT=Arial, Helvetica, sans-serif]lpsz[/FONT] [FONT=Arial, Helvetica, sans-serif]pointer long (nul str)[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lptstr[/FONT] [FONT=Arial, Helvetica, sans-serif]lpsz[/FONT] [FONT=Arial, Helvetica, sans-serif]pointer long (nul str)[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]np[/FONT] [FONT=Arial, Helvetica, sans-serif]n[/FONT] [FONT=Arial, Helvetica, sans-serif]non utilizzabile[/FONT] [FONT=Arial, Helvetica, sans-serif]-[/FONT] [FONT=Arial, Helvetica, sans-serif]npstr[/FONT] [FONT=Arial, Helvetica, sans-serif]np[/FONT] [FONT=Arial, Helvetica, sans-serif]non utilizzabile[/FONT] [FONT=Arial, Helvetica, sans-serif]-[/FONT] [FONT=Arial, Helvetica, sans-serif]uint[/FONT] [FONT=Arial, Helvetica, sans-serif]n[/FONT] [FONT=Arial, Helvetica, sans-serif]int unsigned[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]word[/FONT] [FONT=Arial, Helvetica, sans-serif]w[/FONT] [FONT=Arial, Helvetica, sans-serif]int unsigned[/FONT] [FONT=Arial, Helvetica, sans-serif]16[/FONT] [FONT=Arial, Helvetica, sans-serif]dword[/FONT] [FONT=Arial, Helvetica, sans-serif]dw[/FONT] [FONT=Arial, Helvetica, sans-serif]int unsigned[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]flags[/FONT] [FONT=Arial, Helvetica, sans-serif]f[/FONT] [FONT=Arial, Helvetica, sans-serif]bit flag[/FONT] [FONT=Arial, Helvetica, sans-serif]16/32[/FONT] [FONT=Arial, Helvetica, sans-serif]lpunknow[/FONT] [FONT=Arial, Helvetica, sans-serif]-[/FONT] [FONT=Arial, Helvetica, sans-serif]puntatore[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT]
[FONT=Arial, Helvetica, sans-serif]Spiegare adesso in questo breve articolo tutto su questi tipi sarebbe un pò troppo, ma è già sufficiente sapere che sono così e che bisogna dare un’occhiata al C/C++ per comprendere meglio quanto detto. Risulta interessante legare questo concetto con quello definito nel modo VB, più esattamente quello della dichiarazione degli argomenti, in ciò risulta altamente utile il C/C++, poiché se ad esempio il tipo richiesto dalle API dovesse essere una UNSIGNED WORD (da 0 a 65535) a 16 bit fate bene attenzione che non ne esiste alcuno che corrisponda esattamente al VB. Perciò bisognerà applicare il tipo più vicino INTEGER (da -32768 a 32767) a 16 bit, di seguito una routine che svolga il compito di conversione che preveda la sottrazione di 32768 in qualsiasi caso, con una operazione And sui bit: ma questo non è un caso isolato! Il motivo sta nel fatto che se vi è stato chiesto proprio quel valore in bit, voi dovrete fornigliene uno identico a parità di bit, altrimenti vi trovereste con un valore non desiderato.[/FONT][FONT=Arial, Helvetica, sans-serif]
Per chi programma col C questo è uno dei problemi all’ordine del giorno, dato che è diverso confrontarsi con un computer ALFA o PC, il primo è a 64 bit su cui possono girare SO da 64 bit in giù, il secondo può essere a 32 o 16 bit con lo stesso effetto: che cosa succederebbe se il vostro programma volesse accedere all’hardware bypassando il SO e voi vorreste farlo eseguire a tutt’e due? Tenete presente che ambedue possono supportare Windows NT. Perciò è vostro compito sempre dare un’occhiata ai valori dei tipi in VB espressi in bit sul vostro manuale.
Un discorso a parte invece meritano i tipi [/FONT][FONT=Arial, Helvetica, sans-serif]as Any[/FONT][FONT=Arial, Helvetica, sans-serif], verso i quali si sarebbe tentati di utilizzare i tipi Variant, dato che traducendo letteralmente dall’inglese per noi potrebbe significare tipo qualsiasi, fidandosi in tal modo dell’estrema leggerezza con cui il C tratta i dati e del fatto che, talvolta essendoci andata bene, ciò ci ha fatto credere che sia proprio il VB a occuparsi di tutto! [/FONT][FONT=Arial, Helvetica, sans-serif]
In parte l’affermazione è vera, poiché il VB di fatto ha un buon controllo su questi tipi di chiamate, adattandosi ai nostri desideri: ma non è sempre così. Prendete ad esempio questa funzione: Declare Function LoadCursor Lib "user32" Alias "LoadCursorA" (ByVal hInstance As Long, ByVal lpCursorName As Any) As Long, essa accetta sia una string che una long, con due servizi totalmente differenti: diamine, se qui vi sbagliate ci lascerete veramente le penne!
[/FONT]
[FONT=Arial, Helvetica, sans-serif]Dunque che cosa sono gli argomenti?[/FONT]
[FONT=Arial, Helvetica, sans-serif]Gli argomenti servono per l’immissione, il prelievo o l’impostazione di dati, non necessariamente in questa sequenza e neppure tutte insieme: dipende solo dal servizio e dal tipo di progettazione pensato dalla Microsoft. Questo lo si comprenderà meglio con l’esempio successivo, per ora bisogna tenere presente che solo uno sparuto gruppo di funzioni di fatto restituisce qualcosa immediatamente, la maggior parte svolge un oscuro ed umile compito che ha senso solo nel gruppo di appartenenza: grafica, contesti di dispositivo, menu, file, processi, etc.[/FONT]
[FONT=Arial, Helvetica, sans-serif]Impariamo ad usare le strutture e le costanti[/FONT]
[FONT=Arial, Helvetica, sans-serif]Come sopra, tramite il Visualizzatore testo API, inseriamo nel nostro modulo standard la funzione GetSystemInfo(…). Subito si potrà notare contrariamente a quella precedente che l’unico argomento presente è scritto tutto in maiuscolo: questa è una convezione utilizzata per avvertirvi che state utilizzando una struttura, cioè una struct in C/C++, una type in Delphi o VB. Adesso dovrete solo richiamarle ambedue col Visualizzatore testo API, la prima nella ComboBox Tipo API tramite la voce Dichiarazioni, la seconda tramite quella dei tipi, di seguito inserirle nel vostro modulo standard. Questa struttura prevede anche alcune costanti che si riferiscono al tipo di processore presente, esse sono dei codici identificativi che le API ci danno che bisogna confrontare per conoscere il tipo della CPU; contrariamente a quanto detto in precedenza per gli altri casi, sebbene la procedura di inserimento nel nostro modulo standard avvenga sempre col Visualizzatore Testo API, selezionando nella ComboBox Tipo API la voce Costanti, adesso noi conosciamo la loro esistenza e il loro uso solo leggendo quanto il SDK ci dice rispetto alla struttura. Per il resto bisogna assegnare una variabile public del tipo della nostra struttura (non potete usare direttamente essa nei vostri programmi), di seguito chiamare con la stessa la funzione e stampare i risultati, confrontando le costanti col campo riferito al processore. Eccole qui:[/FONT][FONT=Arial, Helvetica, sans-serif]
[/FONT] [FONT=Courier New, Courier, mono]Type SYSTEM_INFO[/FONT] [FONT=Courier New, Courier, mono] dwOemID As Long[/FONT] [FONT=Courier New, Courier, mono]‘restituisce il processore usato: 0 in Win95[/FONT] [FONT=Courier New, Courier, mono] dwPageSize As Long[/FONT] [FONT=Courier New, Courier, mono]‘ restituisce la grandezza della paginazione usata[/FONT] [FONT=Courier New, Courier, mono] lpMinimumApplicationAddress As Long[/FONT] [FONT=Courier New, Courier, mono]‘Indirizzo più basso per un'applicazione[/FONT] [FONT=Courier New, Courier, mono] lpMaximumApplicationAddress As Long[/FONT] [FONT=Courier New, Courier, mono]‘Indirizzo più alto per un'applicazione[/FONT] [FONT=Courier New, Courier, mono] dwActiveProcessorMask As Long [/FONT] [FONT=Courier New, Courier, mono]‘numero di processori configurati nel sistema[/FONT] [FONT=Courier New, Courier, mono] dwNumberOrfProcessors As Long [/FONT] [FONT=Courier New, Courier, mono]‘numero di processori nel sistema[/FONT] [FONT=Courier New, Courier, mono] dwProcessorType As Long [/FONT] [FONT=Courier New, Courier, mono]‘Tipo di Processore, obsoleta, ma adesso utile[/FONT] [FONT=Courier New, Courier, mono] dwAllocationGranularity As Long[/FONT] [FONT=Courier New, Courier, mono]'composizione memoria virtuale: 64k default[/FONT] [FONT=Courier New, Courier, mono] dwReserved As Long [/FONT] [FONT=Courier New, Courier, mono]‘riservato[/FONT] [FONT=Courier New, Courier, mono]End Type[/FONT]
[FONT=Courier New, Courier, mono]Declare Sub GetSystemInfo Lib "kernel32" Alias "GetSystemInfo" (lpSystemInfo As SYSTEM_INFO)[/FONT] [FONT=Arial, Helvetica, sans-serif]Il terzo esempio incluso nell'allegato vi mostra l’uso di tale funzione, di essa non dovete far altro che richiamarla per ottenere le informazioni desiderate.[/FONT]
[FONT=Arial, Helvetica, sans-serif]Una dichiarazione con più argomenti[/FONT]
[FONT=Arial, Helvetica, sans-serif]Con la funzione GetVolumeInformation(…), che restituisce le caratteristiche della memoria di massa richiesta, si vedrà praticamente l’uso di argomenti compositi, evitando adesso di ripeterci su cose già dette su. Accanto ad ogni argomento v’è la spiegazione, che dovrebbe essere già sufficiente per comprensione immediata di essa.[/FONT]
[FONT=Courier New, Courier, mono]Declare Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA"[/FONT] [FONT=Courier New, Courier, mono] ByVal lpRootPathName As String[/FONT] [FONT=Courier New, Courier, mono]‘inserire: unità espressa in lettere "A:" , "B:", "C", "D:" ….."[/FONT] [FONT=Courier New, Courier, mono] ByVal lpVolumeNameBuffer As String[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: l’etichetta dell’unità (stringa terminante con zero)[/FONT] [FONT=Courier New, Courier, mono] ByVal nVolumeNameSize As Long[/FONT] [FONT=Courier New, Courier, mono]‘inserire: 255 grandezza del vettore in lpVolumeNameBuffer[/FONT] [FONT=Courier New, Courier, mono] lpVolumeSerialNumber As Long[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: numero di serie dell’unità[/FONT] [FONT=Courier New, Courier, mono] lpMaximumComponentLength As Long[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: grandezza massima di un nome di file predefinita dal SO[/FONT] [FONT=Courier New, Courier, mono] lpFileSystemFlags As Long[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: tipo di File System: compresso, unicode,…[/FONT]
[FONT=Courier New, Courier, mono]‘da reperire tramite costanti[/FONT] [FONT=Courier New, Courier, mono] ByVal lpFileSystemNameBuffer As String[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: nome del FileSystem[/FONT] [FONT=Courier New, Courier, mono] ByVal nFileSystemNameSize As Long)[/FONT] [FONT=Courier New, Courier, mono]‘inserire: 255 grandezza del vettore in lpFileSystemNameBuffer[/FONT] [FONT=Courier New, Courier, mono]As Long [/FONT] [FONT=Courier New, Courier, mono]‘ riuscita dell’operazione: 1 = OK, 0 = fallita[/FONT]
[FONT=Arial, Helvetica, sans-serif]Come al solito in allegato c’è l’esempio quarto al riguardo[/FONT]
[FONT=Arial, Helvetica, sans-serif]Conclusioni[/FONT]
[FONT=Arial, Helvetica, sans-serif]Probabilmente si potrà pensare di unire tutte le chiamate API in un unico modulo per utilizzarle facilmente nei propri programmi. Questa non è un’idea malsana che tuttavia non tiene conto del fatto che esse per poter funzionare adeguatamente hanno comunque bisogno delle Dichiarazioni dei Tipi e delle Costanti, cosa che in una memoria Heap (cioè quella parte della memoria riservata ad ogni applicazione ai dati, determinata dal SO tramite le informazioni contenute nell’Header [intestazione] del file) predefinita del VB non riuscirebbero a collocarsi e il programma nemmeno partirebbe.[/FONT][FONT=Arial, Helvetica, sans-serif]
Se avete pensato a costruirci su una DLL da VB, tenete conto del fatto che essa non è affatto identica a quelle che voi avete chiamato tramite l’istruzione DECLARE, poiché il VB le crea con un sistema pressappoco simile agli Overlay (OVR) usati in alcuni linguaggi su piattaforma DOS, con l’evidente conseguenza di condividere la stessa memoria Heap usata dal vostro programma. Allora perché utilizzare le API da VB?
Di fatto il VB offre numerose estensioni al proprio linguaggio, le quali coprono buona parte delle normali richieste dei programmatori. Le stesse vi vengono offerte direttamente senza bisogno di dover accedere a tool quali le MFC o gli Object Windows, che il più delle volte sono facili da implementare, ma complicati da gestire, poiché per esse, se si desidera apportare modifiche personali, bisogna sempre risalire alle classi parent per conoscerne bene la struttura e poi implementare le nostre istanze o funzioni membro ereditando le classi stesse: il VB fortunatamente ci mette al riparo da tutto ciò, rendendoci tutto più semplice.
Le API possono velocizzare molto in alcuni casi il alcune operazioni del nostro programma o darci delle informazioni che non possono essere reperite senza esse stesse. Prendete il caso successivo e ve ne renderete conto.
Dovevo caricare un database di 5000 elementi circa in una ComboBox. Per evitare che il tempo necessario per compiere tale operazione facesse credere all’utente un possibile errore del programma, bisognava implementare una barra di avanzamento grafica e attivare la funzione DoEvents() in modo da liberare il SO dall’eccessiva presenza del programma in esecuzione. A questo punto l’unica cosa da fare era velocizzare questa procedura tramite funzioni API che caricassero gli elementi del database velocemente nella ComboBox e costruire velocemente la barra di avanzamento, tramite le funzioni grafiche, evitando l’uso (in questo caso lento) del controllo line.
Probabilmente penserete a questo punto che vale la pena di utilizzare un altro linguaggio: questo potrebbe essere vero rispetto all’uso specifico che se ne deve fare e alle capacità offerte dal linguaggio stesso. Ma se le vostre conoscenze di programmazione non volete che diventino il fine della vostra vita, bisogna scegliere un linguaggio semplice.
D’altra parte, se il tutto il resto del vostro programma l’avete creato in cinque minuti col VB, che senso ha pensare ad un altro linguaggio per crearvi inutili problemi?
Resta comunque il fatto che con le API bisogna avere pazienza e legger bene il SDK prima di implementarle.
[/FONT]
[FONT=Arial, Helvetica, sans-serif]Approfondimenti[/FONT]
[FONT=Arial, Helvetica, sans-serif]Come approfondimento è consigliato sia una buona lettura dell'MSDN, ci si trova di tutto dentro persino il libro di Bruce McKinney - HardCore Visual Basic - MSPress, e senza ombra di dubbio l'acquisto del libro di Dan Appleman, Visual Basic X.0 win 32 API - Guida del programmatore, Mondadori Informatica.
Buon Lavoro.[/FONT][FONT=Arial, Helvetica, sans-serif]
[/FONT]
[/FONT]
[FONT=Arial, Helvetica, sans-serif]Francesco Mannarino http://www.it-lang-vb.net
[/FONT]
[FONT=Arial, Helvetica, sans-serif]Prima di iniziare[/FONT]
[FONT=Arial, Helvetica, sans-serif]Occorre all'inizio cercare nel menu di Visual Basic Strumenti\Opzioni le voci Salva con conferma e Dichiarazioni di variabili obbligatoria, di conseguenza settarle di modo che l'istruzione Option Explicit appaia in tutti gli script e ad ogni esecuzione del vostro programma vi verrà chiesto se desiderate salvare il vostro lavoro (e voi lo farete per sicurezza). Poi tenete a portata di mano il Visualizzatore testo API presente nella cartella di VB. [/FONT]
[FONT=Arial, Helvetica, sans-serif]Visione d'insieme[/FONT]
[FONT=Arial, Helvetica, sans-serif]Avviate il Visualizzatore testo API e dal menu File\Carica file di testo... caricate il file Win32api.txt, di seguito eseguite dal menu File\Converti testo in database... seguendo le istruzioni e caricate quest'ultimo.
In esso vi sono tre ListBox (Tipo API, Elementi disponibili e Elementi selezionati) e tre Pulsanti (Aggiungi, Rimuovi e Copia). Se cliccate su una delle voci in Elementi disponibili il pulsante Aggiungi si attiva e dopo averlo premuto apparirà nelle voci di Elementi selezionati: potrete rimuoverla (Rimuovi) dopo averla selezionata oppure copiarla (Copia) negli appunti, da dove sarà possibile inserirla nel vostro progetto VB con Incolla.
Questo piccolo programmino fornito nel pacchetto serve a facilitare la digitazione delle dichiarazioni API desiderate, poiché, essendo alcune piuttosto lunghette, ci si può sbagliare con facilità.[/FONT] [FONT=Arial, Helvetica, sans-serif]Che cosa sono le API[/FONT]
[FONT=Arial, Helvetica, sans-serif]Esse sono delle funzioni che possono a volte non avere un valore di ritorno; le stesse assomigliano in un certo qual modo alle chiamate DOS/BIOS che qualche volta avrete visto nei programmi assembly o inline in quelli C++ o TPascal: di fatto esse sono le funzioni di sistema che di solito vengono usate in Visual C++, Borland C++, Watcom C++, Visual Age for C++, etc. È il Sistema Operativo che dialoga con noi offrendoci tutto ciò che esso ci mostra: le finestre, i movimenti, i suoni la grafica, il controllo del mouse, etc.[/FONT]
[FONT=Arial, Helvetica, sans-serif]Adesso s’inizia[/FONT]
[FONT=Arial, Helvetica, sans-serif]Chiarito questo, se avrete lasciato la voce Dichiarazioni nella ListBox Tipo API, dopo aver cercato la voce GetWindowsDirectory e averla aggiunta in quella in basso, potrete notare che essa è composta da più parti: (è una funzione API che ci restituisce la directory effettiva in cui è situato Windows)
- Questa è la funzione richiesta [/FONT]
[FONT=Courier New, Courier, mono]Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long[/FONT]
[FONT=Arial, Helvetica, sans-serif]- Qui di seguito la spiegazione [/FONT]
[FONT=Courier New, Courier, mono]Declare Function[/FONT] [FONT=Arial, Helvetica, sans-serif]la dichiarazione vera e propria[/FONT] [FONT=Courier New, Courier, mono]GetWindowsDirectory Lib "kernel32"[/FONT] [FONT=Arial, Helvetica, sans-serif]il nome della funzione e la libreria d’origine [/FONT] [FONT=Courier New, Courier, mono]Alias "GetWindowsDirectoryA"[/FONT] [FONT=Arial, Helvetica, sans-serif]l'alias, cioè il nome sostitutivo, dato che a volte può essere identico a una istruzione VB[/FONT] [FONT=Arial, Helvetica, sans-serif]Noterete che essa termina con una ‘A’ Essa sta ad indicare ANSI , cioè set dei caratteri ad un solo byte, usato per il Win32 da Windows95. Mentre se andrete a spulciare il file Win32api.txt sotto Windows NT ne troverete un altro un altro col suffisso ‘W’ che sta ad indicare WIDE, esteso, cioè appartiene al set dei caratteri Unicode di questo SO. Di questo se ne preoccupa sia il compilatore, che il programma di installazione VB, ma voi dovete sapere che il VB utilizza quello di Windows NT ed è costretto ad operare la conversione sotto W95.[/FONT]
[FONT=Courier New, Courier, mono](ByVal lpBuffer As String, ByVal nSize As Long)[/FONT] [FONT=Arial, Helvetica, sans-serif]gli argomenti[/FONT] [FONT=Arial, Helvetica, sans-serif]La prima è una stringa terminante con zero che serve da buffer (in realtà un vettore), mentre la seconda è la grandezza della stringa stessa, di cui il SDK ci informa che non deve superare 144. Ora poiché in C/C++ i vettori (vengono usati per formare stringhe, quest’ultime non esistono in C/C++) hanno gli indici che iniziano con zero (0), noi la dovremo inizializzare a 145, perciò dovremo con un accorgimento adattare la nostra stringa a al vettore del C/C++ e di seguito prelevare il testo sottraendolo dagli zeri successivi. Ambedue sono argomenti che devono essere passati per valore (byVal), cioè la nostra stringa conterrà il valore cercato.
[/FONT]
[FONT=Courier New, Courier, mono]As Long[/FONT] [FONT=Arial, Helvetica, sans-serif]il valore di ritorno[/FONT] [FONT=Arial, Helvetica, sans-serif]di cui il SDK ci informa che è la grandezza, in bytes, della stringa (meglio vettore) contenuta in lpbuffer, mentre l’eventuale errore dovrà essere prelevato tramite la funzione GetLastError(…)
La dichiarazione andrà messa in un modulo standard e dovrà essere richiamata dalla sub desiderata. Ciò che noterete più avanti è l’uso di una particolare tecnica per dimensionare una stringa di modo tale che venga usata come buffer compatibile col tipo vettore C/C++: prima la si dichiara moltiplicandola per la grandezza desiderata, poi la si riempie di zero con la funzione interna Vb string(…, …), così come si potrà notare di seguito:[/FONT]
[FONT=Courier New, Courier, mono]Dim Risult&[/FONT] [FONT=Courier New, Courier, mono]‘questo è il valore di ritorno della funzione[/FONT] [FONT=Courier New, Courier, mono]Dim WinDir As String * 145[/FONT] [FONT=Courier New, Courier, mono]‘dimensionamento della stringa[/FONT] [FONT=Courier New, Courier, mono]WinDir = String(256, 0)[/FONT] [FONT=Courier New, Courier, mono]‘ la stringa viene riempita di zero[/FONT] [FONT=Courier New, Courier, mono]Risult& = GetWindowsDirectory (WinDir, 145)[/FONT] [FONT=Courier New, Courier, mono]‘viene chiamata[/FONT] [FONT=Courier New, Courier, mono]Print "valore di ritorno = " & Risult&[/FONT] [FONT=Courier New, Courier, mono]‘stampa il valore di ritorno[/FONT] [FONT=Courier New, Courier, mono]Print "Directory Windows = " & [/FONT][FONT=Courier New, Courier, mono]StrNulToStr[/FONT][FONT=Courier New, Courier, mono](WinDir, Risult&)[/FONT] [FONT=Courier New, Courier, mono]‘stampa directory[/FONT] [FONT=Arial, Helvetica, sans-serif]Nella seconda istruzione di stampa (print …) avrete notato due cose strane: un richiamo a una funzione di cui non si è parlato prima e il fatto che il valore di ritorno desiderato da noi, che avrebbe dovuto farci conoscere il percorso in cui è situato Windows, non sta dove ce lo saremmo aspettato, cioè nella variabile[/FONT][FONT=Arial, Helvetica, sans-serif] Risult&[/FONT][FONT=Arial, Helvetica, sans-serif]!
Poco fa abbiamo detto che il C/C++ non avendo le stringhe utilizza dei vettori di bytes per simularle e ciò in qualche modo al VB potrebbe anche star bene, in quanto comunque ha utilizzato una stringa per avere il valore, ma ciò che il VB non potrà mai fare è trattare delle stringhe in cui, oltre ai caratteri, vi sono degli zero: di fatto per lui sono un po’ indigesti. Perciò bisogna implementare una funzione che tolga gli zero e restituisca una stringa pura VB sapendo che già Risult& è la lunghezza di essa, cioè in tal modo:
[/FONT]
[FONT=Courier New, Courier, mono]' funzione che trasforma un stringa terminante con zero
' in una senza[/FONT][FONT=Courier New, Courier, mono]
Public Function StrNulToStr(ByVal Str_Nul$, ByVal Size As Long) As String
Dim k, SizeKont As Long
SizeKont = Size
If Size = 0 Then SizeKont = 256[/FONT][FONT=Courier New, Courier, mono] ' valore di default se non si passa[/FONT][FONT=Courier New, Courier, mono]
[/FONT][FONT=Courier New, Courier, mono] ' alcun argomento per la lunghezza desiderata[/FONT][FONT=Courier New, Courier, mono]
For k = 1 To SizeKont
If Asc(Mid(Str_Nul$, k, 1)) = 0 Then Exit For[/FONT][FONT=Courier New, Courier, mono] ' per sicurezza quando vi è zero è meglio uscire[/FONT][FONT=Courier New, Courier, mono]
StrNulToStr = StrNulToStr + Mid(Str_Nul$, k, 1)
Next
End Function[/FONT]
[FONT=Arial, Helvetica, sans-serif]Per ciò che riguarda il secondo dubbio bisogna chiarire che voi probabilmente siete abituati a pensare che le funzioni abbiano sempre la sintassi classica y=f(x), in questo caso è sufficiente inserire il valore desiderato in x per avere un risultato a lui dipendente in y, ma con le API di Windows non funziona così: il valore y può essere il risultato dell’esito della funzione (è andata bene o male?) o qualcos’altro (in questo caso la grandezza del vettore), le funzioni dovrete sempre pensarle come le chiamate Dos/Bios in Assembly, laddove si parla di servizi del Sistema Operativo. In realtà si tratta di un passaggio di parametri per riferimento, ciò che in VB equivale al ByRef, mentre con ByVal si vuole indicare che noi desideriamo passare l’argomento per valore, tutto come il VB normale: in fondo si tratta solo di funzioni!
Inoltre se vi siete trovati di fronte funzioni il cui nome terminano con …ex, nel caso in cui il SDK ve lo chieda espressamente, usate queste. Queste sono funzioni che rappresentano un aggiornamento delle corrispondenti senza il suffisso …ex in Win32, a volte con funzionalità in più.[/FONT]
[FONT=Arial, Helvetica, sans-serif]Come chiamare le funzioni[/FONT]
[FONT=Arial, Helvetica, sans-serif]Nel microesempio precedente abbiamo chiamato la funzione secondo la consuetudine, d’altra parte se proprio il valore di ritorno non ci fosse utile, avremmo potuto chiamarlo anche con Call, infatti la routine di conversione da stringa con zero a stringa pura da me proposta prevede già un controllo sulla fine del vettore, così potremo modificare il programma in questo modo con i medesimi risultati:[/FONT]
[FONT=Courier New, Courier, mono]Dim Risult&
…
Call GetWindowsDirectory (WinDir, 145)
Print "Directory Windows = " & StrNulToStr(WinDir, 0)[/FONT]
[FONT=Arial, Helvetica, sans-serif]È più semplice, vero? Tenete presente a questo punto che molte volte il SDK vi chiederà proprio di tener in conto che il risultato del vostra richiesta è prelevabile da una altra funzione: infatti capita spesso che i possibili errori vengano prelevati tramite la funzione GetLastError(void).
[/FONT]
[FONT=Arial, Helvetica, sans-serif]I tipi[/FONT]
[FONT=Arial, Helvetica, sans-serif]Sicuramente il maggior dubbio vostro è dato dal termine lpbuffer: che sarà mai ‘sta roba? Questo è un buffer che ha come suffisso lp, cioè un puntatore a una struttura o voce di dati. Insomma questa è la notazione Ungherese. Nella tabella seguente vi sono i tipi e il prefisso corrispondente per Win32:[/FONT][FONT=Arial, Helvetica, sans-serif]
[/FONT] [FONT=Arial, Helvetica, sans-serif]tipo[/FONT] [FONT=Arial, Helvetica, sans-serif]prefisso[/FONT] [FONT=Arial, Helvetica, sans-serif]commento[/FONT] [FONT=Arial, Helvetica, sans-serif]bit[/FONT]
[FONT=Arial, Helvetica, sans-serif]tipo[/FONT] [FONT=Arial, Helvetica, sans-serif]prefisso[/FONT] [FONT=Arial, Helvetica, sans-serif]commento[/FONT] [FONT=Arial, Helvetica, sans-serif]bit[/FONT] [FONT=Arial, Helvetica, sans-serif]bool[/FONT] [FONT=Arial, Helvetica, sans-serif]b[/FONT] [FONT=Arial, Helvetica, sans-serif]boolean(= 0/1)[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]byte[/FONT] [FONT=Arial, Helvetica, sans-serif]ch[/FONT] [FONT=Arial, Helvetica, sans-serif]int unsigned[/FONT] [FONT=Arial, Helvetica, sans-serif]8[/FONT] [FONT=Arial, Helvetica, sans-serif]char[/FONT] [FONT=Arial, Helvetica, sans-serif]ch[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]8[/FONT] [FONT=Arial, Helvetica, sans-serif]tchar[/FONT] [FONT=Arial, Helvetica, sans-serif]ch[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]8/16[/FONT] [FONT=Arial, Helvetica, sans-serif]farproc[/FONT] [FONT=Arial, Helvetica, sans-serif]lpfn[/FONT] [FONT=Arial, Helvetica, sans-serif]puntatore far[/FONT] [FONT=Arial, Helvetica, sans-serif]32 [/FONT] [FONT=Arial, Helvetica, sans-serif]handle[/FONT] [FONT=Arial, Helvetica, sans-serif]h[/FONT] [FONT=Arial, Helvetica, sans-serif]handle windows[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]int[/FONT] [FONT=Arial, Helvetica, sans-serif]n[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]short[/FONT] [FONT=Arial, Helvetica, sans-serif]n[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]16[/FONT] [FONT=Arial, Helvetica, sans-serif]long[/FONT] [FONT=Arial, Helvetica, sans-serif]l[/FONT] [FONT=Arial, Helvetica, sans-serif]int signed[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lp[/FONT] [FONT=Arial, Helvetica, sans-serif]lp [/FONT] [FONT=Arial, Helvetica, sans-serif]pointer long[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lpint[/FONT] [FONT=Arial, Helvetica, sans-serif]pli[/FONT] [FONT=Arial, Helvetica, sans-serif]pointer[/FONT][FONT=Arial, Helvetica, sans-serif] long[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lpstr[/FONT] [FONT=Arial, Helvetica, sans-serif]lpsz[/FONT] [FONT=Arial, Helvetica, sans-serif]pointer long(nul str)[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lpcstr[/FONT] [FONT=Arial, Helvetica, sans-serif]lpsz[/FONT] [FONT=Arial, Helvetica, sans-serif]pointer long (nul str)[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]lptstr[/FONT] [FONT=Arial, Helvetica, sans-serif]lpsz[/FONT] [FONT=Arial, Helvetica, sans-serif]pointer long (nul str)[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]np[/FONT] [FONT=Arial, Helvetica, sans-serif]n[/FONT] [FONT=Arial, Helvetica, sans-serif]non utilizzabile[/FONT] [FONT=Arial, Helvetica, sans-serif]-[/FONT] [FONT=Arial, Helvetica, sans-serif]npstr[/FONT] [FONT=Arial, Helvetica, sans-serif]np[/FONT] [FONT=Arial, Helvetica, sans-serif]non utilizzabile[/FONT] [FONT=Arial, Helvetica, sans-serif]-[/FONT] [FONT=Arial, Helvetica, sans-serif]uint[/FONT] [FONT=Arial, Helvetica, sans-serif]n[/FONT] [FONT=Arial, Helvetica, sans-serif]int unsigned[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]word[/FONT] [FONT=Arial, Helvetica, sans-serif]w[/FONT] [FONT=Arial, Helvetica, sans-serif]int unsigned[/FONT] [FONT=Arial, Helvetica, sans-serif]16[/FONT] [FONT=Arial, Helvetica, sans-serif]dword[/FONT] [FONT=Arial, Helvetica, sans-serif]dw[/FONT] [FONT=Arial, Helvetica, sans-serif]int unsigned[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT] [FONT=Arial, Helvetica, sans-serif]flags[/FONT] [FONT=Arial, Helvetica, sans-serif]f[/FONT] [FONT=Arial, Helvetica, sans-serif]bit flag[/FONT] [FONT=Arial, Helvetica, sans-serif]16/32[/FONT] [FONT=Arial, Helvetica, sans-serif]lpunknow[/FONT] [FONT=Arial, Helvetica, sans-serif]-[/FONT] [FONT=Arial, Helvetica, sans-serif]puntatore[/FONT] [FONT=Arial, Helvetica, sans-serif]32[/FONT]
[FONT=Arial, Helvetica, sans-serif]Spiegare adesso in questo breve articolo tutto su questi tipi sarebbe un pò troppo, ma è già sufficiente sapere che sono così e che bisogna dare un’occhiata al C/C++ per comprendere meglio quanto detto. Risulta interessante legare questo concetto con quello definito nel modo VB, più esattamente quello della dichiarazione degli argomenti, in ciò risulta altamente utile il C/C++, poiché se ad esempio il tipo richiesto dalle API dovesse essere una UNSIGNED WORD (da 0 a 65535) a 16 bit fate bene attenzione che non ne esiste alcuno che corrisponda esattamente al VB. Perciò bisognerà applicare il tipo più vicino INTEGER (da -32768 a 32767) a 16 bit, di seguito una routine che svolga il compito di conversione che preveda la sottrazione di 32768 in qualsiasi caso, con una operazione And sui bit: ma questo non è un caso isolato! Il motivo sta nel fatto che se vi è stato chiesto proprio quel valore in bit, voi dovrete fornigliene uno identico a parità di bit, altrimenti vi trovereste con un valore non desiderato.[/FONT][FONT=Arial, Helvetica, sans-serif]
Per chi programma col C questo è uno dei problemi all’ordine del giorno, dato che è diverso confrontarsi con un computer ALFA o PC, il primo è a 64 bit su cui possono girare SO da 64 bit in giù, il secondo può essere a 32 o 16 bit con lo stesso effetto: che cosa succederebbe se il vostro programma volesse accedere all’hardware bypassando il SO e voi vorreste farlo eseguire a tutt’e due? Tenete presente che ambedue possono supportare Windows NT. Perciò è vostro compito sempre dare un’occhiata ai valori dei tipi in VB espressi in bit sul vostro manuale.
Un discorso a parte invece meritano i tipi [/FONT][FONT=Arial, Helvetica, sans-serif]as Any[/FONT][FONT=Arial, Helvetica, sans-serif], verso i quali si sarebbe tentati di utilizzare i tipi Variant, dato che traducendo letteralmente dall’inglese per noi potrebbe significare tipo qualsiasi, fidandosi in tal modo dell’estrema leggerezza con cui il C tratta i dati e del fatto che, talvolta essendoci andata bene, ciò ci ha fatto credere che sia proprio il VB a occuparsi di tutto! [/FONT][FONT=Arial, Helvetica, sans-serif]
In parte l’affermazione è vera, poiché il VB di fatto ha un buon controllo su questi tipi di chiamate, adattandosi ai nostri desideri: ma non è sempre così. Prendete ad esempio questa funzione: Declare Function LoadCursor Lib "user32" Alias "LoadCursorA" (ByVal hInstance As Long, ByVal lpCursorName As Any) As Long, essa accetta sia una string che una long, con due servizi totalmente differenti: diamine, se qui vi sbagliate ci lascerete veramente le penne!
[/FONT]
[FONT=Arial, Helvetica, sans-serif]Dunque che cosa sono gli argomenti?[/FONT]
[FONT=Arial, Helvetica, sans-serif]Gli argomenti servono per l’immissione, il prelievo o l’impostazione di dati, non necessariamente in questa sequenza e neppure tutte insieme: dipende solo dal servizio e dal tipo di progettazione pensato dalla Microsoft. Questo lo si comprenderà meglio con l’esempio successivo, per ora bisogna tenere presente che solo uno sparuto gruppo di funzioni di fatto restituisce qualcosa immediatamente, la maggior parte svolge un oscuro ed umile compito che ha senso solo nel gruppo di appartenenza: grafica, contesti di dispositivo, menu, file, processi, etc.[/FONT]
[FONT=Arial, Helvetica, sans-serif]Impariamo ad usare le strutture e le costanti[/FONT]
[FONT=Arial, Helvetica, sans-serif]Come sopra, tramite il Visualizzatore testo API, inseriamo nel nostro modulo standard la funzione GetSystemInfo(…). Subito si potrà notare contrariamente a quella precedente che l’unico argomento presente è scritto tutto in maiuscolo: questa è una convezione utilizzata per avvertirvi che state utilizzando una struttura, cioè una struct in C/C++, una type in Delphi o VB. Adesso dovrete solo richiamarle ambedue col Visualizzatore testo API, la prima nella ComboBox Tipo API tramite la voce Dichiarazioni, la seconda tramite quella dei tipi, di seguito inserirle nel vostro modulo standard. Questa struttura prevede anche alcune costanti che si riferiscono al tipo di processore presente, esse sono dei codici identificativi che le API ci danno che bisogna confrontare per conoscere il tipo della CPU; contrariamente a quanto detto in precedenza per gli altri casi, sebbene la procedura di inserimento nel nostro modulo standard avvenga sempre col Visualizzatore Testo API, selezionando nella ComboBox Tipo API la voce Costanti, adesso noi conosciamo la loro esistenza e il loro uso solo leggendo quanto il SDK ci dice rispetto alla struttura. Per il resto bisogna assegnare una variabile public del tipo della nostra struttura (non potete usare direttamente essa nei vostri programmi), di seguito chiamare con la stessa la funzione e stampare i risultati, confrontando le costanti col campo riferito al processore. Eccole qui:[/FONT][FONT=Arial, Helvetica, sans-serif]
[/FONT] [FONT=Courier New, Courier, mono]Type SYSTEM_INFO[/FONT] [FONT=Courier New, Courier, mono] dwOemID As Long[/FONT] [FONT=Courier New, Courier, mono]‘restituisce il processore usato: 0 in Win95[/FONT] [FONT=Courier New, Courier, mono] dwPageSize As Long[/FONT] [FONT=Courier New, Courier, mono]‘ restituisce la grandezza della paginazione usata[/FONT] [FONT=Courier New, Courier, mono] lpMinimumApplicationAddress As Long[/FONT] [FONT=Courier New, Courier, mono]‘Indirizzo più basso per un'applicazione[/FONT] [FONT=Courier New, Courier, mono] lpMaximumApplicationAddress As Long[/FONT] [FONT=Courier New, Courier, mono]‘Indirizzo più alto per un'applicazione[/FONT] [FONT=Courier New, Courier, mono] dwActiveProcessorMask As Long [/FONT] [FONT=Courier New, Courier, mono]‘numero di processori configurati nel sistema[/FONT] [FONT=Courier New, Courier, mono] dwNumberOrfProcessors As Long [/FONT] [FONT=Courier New, Courier, mono]‘numero di processori nel sistema[/FONT] [FONT=Courier New, Courier, mono] dwProcessorType As Long [/FONT] [FONT=Courier New, Courier, mono]‘Tipo di Processore, obsoleta, ma adesso utile[/FONT] [FONT=Courier New, Courier, mono] dwAllocationGranularity As Long[/FONT] [FONT=Courier New, Courier, mono]'composizione memoria virtuale: 64k default[/FONT] [FONT=Courier New, Courier, mono] dwReserved As Long [/FONT] [FONT=Courier New, Courier, mono]‘riservato[/FONT] [FONT=Courier New, Courier, mono]End Type[/FONT]
[FONT=Courier New, Courier, mono]Declare Sub GetSystemInfo Lib "kernel32" Alias "GetSystemInfo" (lpSystemInfo As SYSTEM_INFO)[/FONT] [FONT=Arial, Helvetica, sans-serif]Il terzo esempio incluso nell'allegato vi mostra l’uso di tale funzione, di essa non dovete far altro che richiamarla per ottenere le informazioni desiderate.[/FONT]
[FONT=Arial, Helvetica, sans-serif]Una dichiarazione con più argomenti[/FONT]
[FONT=Arial, Helvetica, sans-serif]Con la funzione GetVolumeInformation(…), che restituisce le caratteristiche della memoria di massa richiesta, si vedrà praticamente l’uso di argomenti compositi, evitando adesso di ripeterci su cose già dette su. Accanto ad ogni argomento v’è la spiegazione, che dovrebbe essere già sufficiente per comprensione immediata di essa.[/FONT]
[FONT=Courier New, Courier, mono]Declare Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA"[/FONT] [FONT=Courier New, Courier, mono] ByVal lpRootPathName As String[/FONT] [FONT=Courier New, Courier, mono]‘inserire: unità espressa in lettere "A:" , "B:", "C", "D:" ….."[/FONT] [FONT=Courier New, Courier, mono] ByVal lpVolumeNameBuffer As String[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: l’etichetta dell’unità (stringa terminante con zero)[/FONT] [FONT=Courier New, Courier, mono] ByVal nVolumeNameSize As Long[/FONT] [FONT=Courier New, Courier, mono]‘inserire: 255 grandezza del vettore in lpVolumeNameBuffer[/FONT] [FONT=Courier New, Courier, mono] lpVolumeSerialNumber As Long[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: numero di serie dell’unità[/FONT] [FONT=Courier New, Courier, mono] lpMaximumComponentLength As Long[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: grandezza massima di un nome di file predefinita dal SO[/FONT] [FONT=Courier New, Courier, mono] lpFileSystemFlags As Long[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: tipo di File System: compresso, unicode,…[/FONT]
[FONT=Courier New, Courier, mono]‘da reperire tramite costanti[/FONT] [FONT=Courier New, Courier, mono] ByVal lpFileSystemNameBuffer As String[/FONT] [FONT=Courier New, Courier, mono]‘prelevare: nome del FileSystem[/FONT] [FONT=Courier New, Courier, mono] ByVal nFileSystemNameSize As Long)[/FONT] [FONT=Courier New, Courier, mono]‘inserire: 255 grandezza del vettore in lpFileSystemNameBuffer[/FONT] [FONT=Courier New, Courier, mono]As Long [/FONT] [FONT=Courier New, Courier, mono]‘ riuscita dell’operazione: 1 = OK, 0 = fallita[/FONT]
[FONT=Arial, Helvetica, sans-serif]Come al solito in allegato c’è l’esempio quarto al riguardo[/FONT]
[FONT=Arial, Helvetica, sans-serif]Conclusioni[/FONT]
[FONT=Arial, Helvetica, sans-serif]Probabilmente si potrà pensare di unire tutte le chiamate API in un unico modulo per utilizzarle facilmente nei propri programmi. Questa non è un’idea malsana che tuttavia non tiene conto del fatto che esse per poter funzionare adeguatamente hanno comunque bisogno delle Dichiarazioni dei Tipi e delle Costanti, cosa che in una memoria Heap (cioè quella parte della memoria riservata ad ogni applicazione ai dati, determinata dal SO tramite le informazioni contenute nell’Header [intestazione] del file) predefinita del VB non riuscirebbero a collocarsi e il programma nemmeno partirebbe.[/FONT][FONT=Arial, Helvetica, sans-serif]
Se avete pensato a costruirci su una DLL da VB, tenete conto del fatto che essa non è affatto identica a quelle che voi avete chiamato tramite l’istruzione DECLARE, poiché il VB le crea con un sistema pressappoco simile agli Overlay (OVR) usati in alcuni linguaggi su piattaforma DOS, con l’evidente conseguenza di condividere la stessa memoria Heap usata dal vostro programma. Allora perché utilizzare le API da VB?
Di fatto il VB offre numerose estensioni al proprio linguaggio, le quali coprono buona parte delle normali richieste dei programmatori. Le stesse vi vengono offerte direttamente senza bisogno di dover accedere a tool quali le MFC o gli Object Windows, che il più delle volte sono facili da implementare, ma complicati da gestire, poiché per esse, se si desidera apportare modifiche personali, bisogna sempre risalire alle classi parent per conoscerne bene la struttura e poi implementare le nostre istanze o funzioni membro ereditando le classi stesse: il VB fortunatamente ci mette al riparo da tutto ciò, rendendoci tutto più semplice.
Le API possono velocizzare molto in alcuni casi il alcune operazioni del nostro programma o darci delle informazioni che non possono essere reperite senza esse stesse. Prendete il caso successivo e ve ne renderete conto.
Dovevo caricare un database di 5000 elementi circa in una ComboBox. Per evitare che il tempo necessario per compiere tale operazione facesse credere all’utente un possibile errore del programma, bisognava implementare una barra di avanzamento grafica e attivare la funzione DoEvents() in modo da liberare il SO dall’eccessiva presenza del programma in esecuzione. A questo punto l’unica cosa da fare era velocizzare questa procedura tramite funzioni API che caricassero gli elementi del database velocemente nella ComboBox e costruire velocemente la barra di avanzamento, tramite le funzioni grafiche, evitando l’uso (in questo caso lento) del controllo line.
Probabilmente penserete a questo punto che vale la pena di utilizzare un altro linguaggio: questo potrebbe essere vero rispetto all’uso specifico che se ne deve fare e alle capacità offerte dal linguaggio stesso. Ma se le vostre conoscenze di programmazione non volete che diventino il fine della vostra vita, bisogna scegliere un linguaggio semplice.
D’altra parte, se il tutto il resto del vostro programma l’avete creato in cinque minuti col VB, che senso ha pensare ad un altro linguaggio per crearvi inutili problemi?
Resta comunque il fatto che con le API bisogna avere pazienza e legger bene il SDK prima di implementarle.
[/FONT]
[FONT=Arial, Helvetica, sans-serif]Approfondimenti[/FONT]
[FONT=Arial, Helvetica, sans-serif]Come approfondimento è consigliato sia una buona lettura dell'MSDN, ci si trova di tutto dentro persino il libro di Bruce McKinney - HardCore Visual Basic - MSPress, e senza ombra di dubbio l'acquisto del libro di Dan Appleman, Visual Basic X.0 win 32 API - Guida del programmatore, Mondadori Informatica.
Buon Lavoro.[/FONT][FONT=Arial, Helvetica, sans-serif]
[/FONT]