Un controllo listbox può essere "popolato" dinamicamente (come nel programmino che abbiamo mostrato in precedenza per evidenziare la possibilità di usarlo per "output di debugging"), ma, spesso, potrà anche servire, invece, popolarlo "una volta per tutte", con dati non destinati a cambiare.
Purtroppo, non si possono specificare
direttamente i contenuti iniziali nel file .RC;
bisogna, invece, operare comunque
"a runtime", cioe` durante l'esecuzione del nostro
programma (spesso, all'inizializzazione, cioè
rispondendo al messaggio WM_INITDIALOG
),
eseguendo opportune funzionalità di
"riempimento" (normalmente, questo si otterrà
spedendo messaggi opportuni al controllo listbox).
(Un modo decisamente anomalo di popolare una
listbox è quello
messo a disposizione dall'API DlgDirList
,
che riempie un controllo listbox con l'elenco dei
file presenti in un certo folder (con varie opzioni).
Non usatela! Al giorno d'oggi, gli utenti si aspettano,
quando devono scegliere un file fra tanti, di vedere
un'interfaccia utente più sofisticata di una
semplice lista di nomi-file -- e hanno ragione, anche
perchè non è affatto difficile fornire
loro queste migliori interfacce, grazie ai "dialoghi
comuni", di cui parleremo più avanti nel corso
di questo tutorial. Quest'API è presente solo
per compatibilità con un passato antichissimo,
e la nomino solo per avvertirvi di non usarla.)
Il modo più normale di "popolare" un
controllo listbox è quello di inviargli
il messaggio LB_ADDSTRING
,
con lParam
posto all'indirizzo della
stringa (che viene accodata alle eventuali altre
già presenti); si tratta di una "stringa" nel
senso C del termine, cioè un array di
caratteri terminato da uno 0 binario. Se il listbox
è owner-drawn, e privo del bit di stile
LBS_HASSTRING
, esso risponde a questo
messaggio semplicemente memorizzando l'lParam
come dato associato al nuovo elemento.
Al messaggio LB_ADDSTRING
, la listbox
risponde dando come codice di ritorno l'indice (da
0 in sù) della posizione in lista del
nuovo elemento (normalmente, come dicevamo, il
nuovo elemento è posto in coda agli altri
già presenti, ma questo non si applica se
il listbox ha il bit di stile LBS_SORT
).
Questo indice, ad esempio, si può usare come
valore di wParam
nell'inviare alla
listbox un messaggio LB_SETITEMDATA
,
che farà sì che i 32 bit contenuti
nell'lParam
siano associati come
"dati" dell'elemento stesso (similmente, inviare
alla lista un messaggio LB_GETITEMDATA
,
sempre con l'indice di elemento in wParam
,
permetterà di recuperare, come valore di
ritorno, il dato associato a un certo elemento).
(Se si intende aggiungere ad una lista un grande numero
di elementi, una piccola ottimizzazione può
essere quella di spedirle anzitutto un messaggio
LB_INITSTORAGE
, con, in wParam
,
il numero di elementi che si intende inserire, e, in
lParam
, il numero di byte di cui la
lista avrà bisogno per conservare il loro
testo; questa operazione non è necessaria,
ma può accelerare sostanzialmente le cose.)
Se si vuole inserire un elemento ad una posizione
particolare, si può usare il messaggio
LB_INSERTSTRING
al posto di
LB_ADDSTRING
; si dovrà allora
passare l'indice desiderato (-1, per appendere
il nuovo elemento in coda a quelli già
presenti) come valore di wParam
(questo blocca, ma solo temporaneamente, la
funzionalità di ordinamento automatico
di un listbox con stile LBS_SORT
;
vi consiglio di evitare questa situazione, che
può causare alcune anomalie, semplicemente
non usando mai LB_INSERTSTRING
,
bensì soltanto LB_ADDSTRING
,
per popolare listbox con stile LBS_SORT
).
Si può rimuovere dalla lista un elemento
col messaggio LB_DELETESTRING
,
sempre con l'indice dell'elemento d'interesse in
wParam
, e si avrà come valore
di ritorno il numero di elementi restanti. Si
può anche chiedere il numero di elementi
presenti, senza fare modifiche, col messaggio
LB_GETCOUNT
; e svuotare completamente
un listbox col messaggio LB_RESETCONTENT
.
La cancellazione di un elemento, se la lista è
owner-drawn, provoca la spedizione di un messaggio
WM_DELETEITEM
al proprietario (su
Windows 95/98, questo messaggio è spedito
anche per la cancellazione di elementi da liste
non owner-drawn).
La lunghezza del testo associato a un dato elemento
si può richiedere spedendo al listbox il
messaggio LB_GETTEXTLEN
(sempre con
l'indice dell'elemento in wParam
), e
il testo stesso con LB_GETTEXT
(con
l'indirizzo del nostro buffer, che deve avere una
lunghezza sufficiente e verrà riempito col
testo richiesto, passato come lParam
).
Si può trovare un elemento che
inizia con un certo testo con il messaggio
LB_FINDSTRING
(oppure, un elemento
che ha esattamente un certo testo, con
il messaggio LB_FINDSTRINGEXACT
);
si passerà l'indirizzo della stringa da
cercare (terminata come al solito da 0 binario)
in lParam
, e, in wParam
,
-1 per cercare nell'intera lista, o, se no,
l'indice del primo elemento da non
prendere in considerazione nella ricerca (ma
la ricerca riprenderà dall'inizio della
lista se non ha successo entro la sua fine;
il codice LB_ERR, che indica che nulla è
stato trovato, viene restituito come valore di
ritorno solo se l'elemento cercato non è
presente in nessun punto della lista).
Le caratteristiche di dettaglio di una listbox
con stile LBS_USETABSTOPS
dipendono
da come sono settati i suoi "tab stop", cioè,
"arresti di tabulazione". Per default, essi sono
ogni 32 "unità di dialogo", l'unità
di misura, cui già abbiamo accennato, che
corrisponde a circa 1/4 della larghezza media dei
caratteri del font in uso; in altri termini, i
tab stop di default sono ogni 8 caratteri circa,
il che può essere già soddisfacente
in molti casi. Se non lo è, si può
rimediare spedendo alla listbox un messaggio
LB_SETTABSTOPS
: in wParam
metteremo il numero totale di tab-stop che
desideriamo, in lParam
l'indirizzo
di un array di interi corrispondente ai valori
dei tab-stop, in unità di misura "dialog
unit" e in ordine strettamente crescente.
(Ricordiamo anche che abbiamo accennato all'API
MapDialogRect
, che si può
usare per convertire da dialog unit a pixel un
qualsiasi rettangolo entro un dialogo).
Per una listbox multi-colonna (cioè, con
il bit di stile LBS_MULTICOLUMN
),
si può stabilire l'ampiezza delle colonne
(che sono tutte di eguale larghezza) con il
messaggio LB_SETCOLUMNWIDTH
; in
wParam
, si metterà la
desiderata larghezza in pixel delle
colonne.
Vi sono molti altri messaggi importanti che si possono inviare a un controllo listbox, per controllarne la selezione e lo scorrimento, ma li tratteremo al prossimo capitolo.
Capitolo 42: controlli: i LISTBOX
Capitolo 44: messaggi ai LISTBOX (2)
Elenco dei capitoli