Come promesso alla fine del capitolo precedente, proseguiamo a mostrare subito un possibile approccio alla ri-creazione di una finestra, anche se, alla fine, dovremo ancora chiarire un paio di cosette...:
Alcuni dei dettagli ancora
da chiarire sono piccoli; ad esempio, il
messaggio WM_SETFONT
prende l'HFONT
come wParam
,
mentre l'lParam
, come l'abbiamo costruito, dice alla
finestra-bersaglio di "ridipingersi" subito per riflettere
il "nuovo" font settato; la malloc, che non richiederebbe
un cast per l'uso in C (ove void* può essere assegnato
a qualsiasi puntatore) lo richiede invece in C++,
quindi lo poniamo, per totale compatibilità -- minuzie.
Le cosette più interessanti sono invece quelle di
geometria. Anzitutto, è importante notare che
r.right-r.left
è la giusta espressione
per dare la
larghezza della finestra -- non c'è, come si
potrebbe pensare, un errore "off by one"; e questo,
perchè Windows, assai comodamente, ci ha dato
come right
uno in più -- cioè, non la coordinata
dell'ultimo punto a destra, che è ancora dentro la
finestra, ma del primo che ne è fuori!
È questo un esempio
di un idioma fondamentale del C, presentato da A. Koenig
in "C Traps and Pitfalls": rappresentare un "range",
non, come ingenuamente si potrebbe pensare, con
"il primo, e l'ultimo" (questo impedisce di rappresentare
comodamente un range vuoto, e inoltre causa spesso
problemi di off-by-1),
bensì con "il primo, e il primo successivo
all'ultimo" (i lettori che usano C++ sanno bene,
d'altra parte,
come questo stesso concetto sia usato estesamente nella
libreria standard C++, ad esempio
con i vari membri end()
dei contenitori standard).
Ho anche infilato nel trattamento della geometria un'API che non avevo ancora nominato... la
HWND
HWND_DESKTOP
per esprimere "coordinate di
schermo". La GetWindowRect
ci dà, appunto,
sempre le coordinate di schermo, mentre, per
creare una finestra-figlia, ci servono invece quelle
relative alla finestra-genitrice; così "mappando",
risolviamo il problema, approfittando anche del
comodo fatto che un RECT
è identico ad un array
di due POINT
(quello in alto a sinistra, poi quello
"subito dopo" quello in basso a destra), anche se
occorre un cast per convincere di ciò il nostro
compilatore. Questo, e le sue ovvie varianti, è
un idioma frequentissimo quando ci si occupa di
geometria di finestre, e punti e regioni entro le
finestre.
Avendo, dunque, a disposizione la nostra nuova funzione ricreaWindow, sarà facile modificare il nostro programmino sperimentale: basta ricreare l'edit a ogni modifica al suo stile, oppure, volendo, avere un altro bottone separato -- un pushbutton, che causi la ri-creazione, ovvero una checkbox che la renda facoltativa ("ri-crea a ogni modifica"). Questo tipo di scelte di progetto, così come la relativa implementazione, è ormai sicuramente in grado di farle e sperimentarle il lettore, e noi possiamo tornare, nel prossimo capitolo, ad esaminare altri aspetti dei controlli di edit.
Capitolo 24: creazione di finestre
Capitolo 26: interazioni con gli EDIT
Elenco dei capitoli