Se le varie "funzioni di comodo" (e relative macro) ci risparmiano un po' di lavoro, e facilitano l'uso dei tipi, per spedire messaggi, non si potrebbe considerare l'uso di qualcosa di analogo anche per il compito di ricevere i messaggi stessi...?
La risposta è "sì", e lo stesso header file windowsx.h, già visto per le macro di spedizione, ne fornisce una versione: i "message crackers".
Ad esempio, la macro HANDLE_WM_COMMAND
,
definita in windowsx.h, accetta quattro parametri --
i tre classici hwnd
, wParam
, lParam
di un messaggio
di command, e, come quarto, il nome di una funzione
che deve essere simile, nomi a parte, a:
HANDLE_WM_COMMAND
"spezza" il messaggio,
nel senso dei vari cast, LOWORD
, HIWORD
, ecc,
ecc, e chiama l'apposita funzione (suo quarto
argomento).
Questo ci permette di riscrivere la TreControlli vista al capitolo precedente nella seguente forma:
Questa forma non permette di tornare un codice
d'errore (cioè di messaggio non gestito), ma, quando
applicabile, è sicuramente più comoda e chiara,
permettendo di ragionare al livello semantico un
poco più alto di id e codici invece di doverseli
ricavare ogni volta a colpi di cast, HIWORD
, ecc.
"Liberandoci" dai dettagli dell'esatta codifica dei
campi semanticamente significativi (idCliccato
,
ecc) nei campi-dati "di trasporto" (wParam
, ecc),
i message cracker migliorano inoltre la nostra
portabilità: originalmente pensati per facilitare
la migrazione/coesistenza fra versioni Windows
a 16 e 32 bit, potranno, un domani, tornar magari
comodi anche nella migrazione 32->64.
windowsx.h comprende anche una macro che facilita la scrittura dell'intera dialog procedure, con l'approccio "semi-ingenuo" accennato nel capitolo 9 (mappa messaggio->gestore che è codificata rigidamente nel codice eseguibile, ma gestione di ciascun messaggio in una sua funzione apposita):
L'idea è che si può scrivere direttamente, proprio come "corpo" della dialog procedure:
wParam
ed lParam
, al cracker
più opportuno. Questa soluzione non è particolarmente
convincente, per quanto abbiamo già detto sull'approccio
"semi-ingenuo", anche se è, ovviamente, molto superiore
all'approccio "totalmente ingenuo" (gestire ogni messaggio
nel corpo della dialog procedure!), e forse accettabile per
casi particolarmente semplici, come questo che abbiamo
testè esemplificato.
Se mai, potrebbe essere meglio definirci noi stessi una macro analoga, che metta la corrispondenza messaggio->funzione in una struttura dati, e un'altra che, "frugando" la struttura dati alla ricerca dello specifico messaggio, usi, quando lo trova, il cracker adatto; la dialog procedure userebbe quest'ultima, mentre la struttura verrebbe costruita, ad esempio nel WinMain, come parte dell'inizializzazione del sistema.
windowsx.h contiene parecchie altre macro "di comodo",
che si possono usare o meno a seconda dei gusti. Ad
esempio, chi non ami il nome poco pronunciabile della
importante API GetDlgCtrlID
, può usare al suo posto il
nome GetWindowID
, definito in windowsx.h; normalmente,
"rinominare" in questo modo importanti funzioni di sistema
per pure considerazioni "estetiche" sarebbe una prassi di
valore molto dubbio, e certamente da sconsigliare, ma,
in questo caso, essendo il #define
a sua volta in un file di
sistema, si può ammettere di considerare questo come
quasi un "sinonimo" ufficiale.
Più interessante, comunque, la macro di windowsx.h:
WM_QUALCOSA
. I meccanismi che
questa macro utilizza internamente, esaminabili,
chiaramente, dalla lettura di windowsx.h, suggeriamo,
per il momento, di considerarli "pura magia nera" (e
non si andrà troppo lontani dalla realtà...!-); li
esamineremo, tuttavia, più avanti nel corso di questo
tutorial.
Capitolo 12: ID e HWND
Capitolo 14: un esempio (1)
Elenco dei capitoli