Il "programma principale" e la dialog procedure del nostro esempietto di grafico di una funzione non presentano, naturalmente, molte novità; dopo i soliti define e include di sistema, le solite...:
Attenzione, però, agli utenti dell'ottimo e gratuito
MinGw32: il cracker per WM_DRAWITEM
non è
stato riportato, chissa perchè!, negli header file
per questo compilatore; in effetti, essi includono solo
una piccola parte di windowsx.h. Gli utenti di questo
compilatore, che vogliano usare i message cracker,
dovranno dunque procurarsi anche il Platform SDK
dal sito Microsoft (download gratuito e comunque
consigliabile, poichè comprende vari strumenti e
documentazioni interessanti!), e fare un poco di
taglia-e-cuci da windowsx.h per ricavarne i cracker
di proprio interesse.
L'inizializzazione del dialogo deve essere condotta con molta cura, poichè la procedura di validazione che già abbiamo visto dipende in modo cruciale dal fatto che non vi siano mai due controlli di edit che, allo stesso tempo, siano in stato "non valido" rispetto alla propria rispettiva sintassi. Ecco, ad esempio, un possibile approccio:
Qui, tutto si appoggia sulla struttura stru
, cui già
abbiamo accennato, e su di una funzione nuova_stru
in grado di "generare" in qualche modo un oggetto di
questo tipo e tornarci un puntatore ad esso. In
realtà, nell'implementarla, possiamo, almeno per il
momento, "barare", poichè sappiamo che non ci
sarà mai più di una stru
alla volta ``in giro'' --
quindi, almeno come prototipo, si può scrivere
qualcosa del tipo...:
Abbiamo quasi tutti i frammenti... manca solo, a parte
la "organizzazione e ricucitura" del codice, che lasciamo
all'iniziativa del lettore, la gestione del clic sulla checkbox
(automatica) IDC_AUTOY
, che abbiamo più volte
menzionato. Supponiamo, naturalmente, di delegare
anche questa ad una funzione apposita, sempre per
tenere il nostro codice diviso e modularizzato in modo
ragionevole ed appropriato. Cosa farà questa funzione...?
Anzitutto, dovrà controllare se il check su IDC_AUTOY
è
stato messo, o tolto. Nel primo caso, l'utente chiede
di calcolare automaticamente il minimo e il massimo per Y;
bisognerà dunque rendere read-only i relativi controlli di
edit, e causare un ridisegno del grafico -- la funzione di
preparazione, chiamata per il ridisegno, porterà un bit
di stato "calcolo automatico di minx/maxx"; in questo caso,
una tantum,
potrà essere appropriato ottenere subito il ri-calcolo con
una chiamata di UpdateWindow
, per potere aggiornare il
valore dei campi in questione -- alternativamente, il compito
di questo aggiornamento potrà essere delegato (sotto
verifica del bit di stato in questione) a punti più appropriati
del codice, come il gestore di WM_DRAWITEM
, visto che
questi campi andranno normalmente riscritti, se soggetti
ad aggiornamento automatico, sostanzialmente tutte e
sole le volte che viene ridisegnato il grafico (cambiamento
di questo bit di stato, della funzione, del minimo o massimo
di X, e relativo clic dell'utente sul bottone di "Disegna").
Il caso in cui la "spuntatura" ("check") è stata tolta
ad IDC_AUTOY
è ancora più semplice:
basterà, in questo caso, rimuovere lo stato di read-only dagli
edit di min-y e max-y -- non occorre cambiare il testo che
contengono, e neppure fare nessun ri-disegno.
L'impostazione di un edit control a read-only, e il reset di
esso a read-write, si ottengono spedendogli il messaggio
EM_SETREADONLY
, con lParam
a
0
e wParam
al valore
BOOL
che si vuole dare all'attributo di read-only; in
alternativa, la solita macro di windowsx.h, qui:
Lo stato di "checked" di un bottone (checkbox o radio),
ricordiamo, si può
richiedere in vari modi, fra cui il più semplice
è forse l'API IsDlgButtonChecked
(che ha come suoi
parametri l'handle del dialogo e l'ID del bottone, e torna
come risultato lo stato del check su quel bottone).
Ecco, dunque, tutti gli elementi occorrenti -- il lettore è certamente in grado di metterli insieme a formare il programma desiderato (e questo esercizio di "ricucitura" può essere un ottimo modo di verificare la propria effettiva comprensione dei vari punti da noi spiegati, che rischiano altrimenti di restare troppo "teorici" per il lettore; di conseguenza, raccomandiamo calorosamente di svolgere davvero l'esercizio stesso).
Resta, naturalmente, un problema sostanziale con il
programma di "grafico di una funzione" che così si
otterrà: la povertà
del nostro "linguaggino" per la definizione delle funzioni
il cui grafico siamo in grado di disegnare! I dettagli di
questo linguaggio sono incapsulati dall'interfaccia IndiEs
,
e la sua sintassi e semantica potrebbero certo essere
arricchite senza eccessiva fatica (esercizio per il lettore
interessato: migliorare l'analizzatore lessicale perchè
possa riconoscere generici "identificatori"; e aggiungere
fra le funzioni unarie implementate dal programma
quelle indicate dagli identificatori SIN
,
COS
, TAN
, ASIN
,
ACOS
, ATAN
).
Ma è mai possibile, piuttosto, che non ci sia modo di
riutilizzare, al posto di una versione di IndiEs
tutta scritta da noi, un qualche
linguaggio interpretativo già esistente...?!
Certamente! Disponendo, ad esempio, dei sorgenti di un interprete, e in rete se ne trovano tanti, non è certo impossibile "cablare" quell'interprete nel nostro stesso programma; con una progettazione accurata delle interfacce, può essere possibile anche un riutilizzo "binario", ad esempio di un interprete che sia fornito come DLL (posso, ad esempio, raccomandare nel modo più incondizionato il linguaggio Python, davvero splendido, per questo tipo di usi -- e anche per quasi qualsiasi altro uso, in realtà!-).
Tuttavia, c'è anche un approccio specifico di Windows al riutilizzo di componenti di ogni tipo, che si applica, fra i mille esempi, anche, in particolare, ai linguaggi interpretati (o "di scripting", come usa spesso dire); ed è un approccio che merita sicuramente di essere preso in considerazione.
Il seguito, dunque, alla prossima puntata...!
Capitolo 33: i parametri del grafico
Capitolo 35: il COM, visto da C (1)
Elenco dei capitoli