I controlli "Listbox", che abbiamo usato nel più semplice dei modi negli ultimi due capitoli, servono, più in generale, a mostrare all'utente elenchi (liste) di stringhe di testo (o, liste di arbitraria grafica, usando il concetto avanzato di "owner-drawn"), eventualmente dando all'utente la possibilità di selezionare uno o più degli elementi elencati.
Il controllo può occupare uno spazio su schermo inferiore a quello necessario per mostrare simultaneamente tutti gli elementi dell'elenco; in questo caso, si potranno avere delle "scroll bar", di cui l'utente potrà servirsi per scorrere avanti e indietro nell'elenco, cioè per visualizzare zone diverse.
Non bisogna confondere i (relativamente semplici) controlli "listbox", con i sofisticati controlli comuni "listview", che svolgono ruoli analoghi ma in modi più complessi. Comunque, anche un "semplice" listbox, così come gli altri controlli "elementari" che abbiamo esaminato sinora, di compiti può svolgerne parecchi, come vedremo, oltre a quello fondamentale di mostrare un semplice elenco di stringhe (con scrolling), è già compito per cui abbiamo utilizzato un list-control nei due capitoli precedenti.
Anche per i controlli Listbox, come per gli altri tipi
già visti ai capitoli precedenti, i bit di stile
svolgono un ruolo fondamentale. LBS_NOSEL
serve per eliminare la possibilità che l'utente
effettui una selezione sulla lista; con questo bit di
stile, il Listbox è un controllo di "puro output".
Al contrario, i bit di stile (mutualmente esclusivi)
LBS_MULTIPLESEL
e LBS_EXTENDEDSEL
permettono entrambi di abilitare sulla lista la
selezione multipla, con due diverse modalità di
interazione dal punto di vista dell'utente: la prima
prevede semplicemente che ogni clic su di un elemento
lo trasformi da non-selezionato a selezionato, o
viceversa; la seconda, più sofisticata, prevede
l'uso di tasti speciali come SHIFT e CONTROL per i
cambiamenti della selezione -- è una modalità di
interazione probabilmente familiare agli utenti
esperti di Windows.
Il bit LBS_NOTIFY
fa sì che il controllo
spedisca alla finestra che lo contiene un messaggio di
notifica ad ogni clic o doppio clic dell'utente su di
un elemento della lista (per la precisione, bisognerà
porre NOT LBS_NOTIFY
, esplicitamente, fra i
bit di stile, se non si vogliono avere queste
notifiche). Il bit
LBS_WANTKEYBOARDINPUT
permette un controllo
ancora maggiore da parte del programma, poichè fa
sì che il listbox spedisca alla finestra che lo
contiene uno speciale messaggio WM_VKEYTOITEM
ogni volta che l'utente preme un tasto mentre il focus
è sul listbox stesso.
Normalmente, un listbox elenca i propri elementi uno
dopo l'altro, in una singola colonna; si può invece
ottenere una molteplicità di colonne usando il bit
di stile LBS_MULTICOLUMN
.
Normalmente, la scroll-bar verticale appare automaticamente
(se la finestra del list-box comprende il bit di stile
WS_VSCROLL
, naturalmente!), se e quando
la lista contiene più elementi di quanti possa
mostrarne simultaneamente sullo schermo, e sparisce
se il numero di elementi è inferiore a questo; per
avere invece una scroll-bar verticale sempre visibile (che
sarà non abilitata, se non vi è possibile scorrimento),
occorre aggiungere al controllo il bit di stile
LBS_DISABLENOSCROLL
. Se interessa che
l'utente possa effettuare uno scroll orizzontale,
si userà il bit di stile WS_HSCROLL
(e vedremo inoltre più avanti quale altra precauzione
sarà necessaria in questo caso).
Il bit LBS_USETABSTOPS
fa sì che il controllo
espanda i caratteri di tabulazione (control-I, cioè
caratteri di valore numerico 9) presenti nelle stringhe
che contiene.
LBS_NOREDRAW
evita che il controllo si
ridisegni automaticamente ad ogni cambiamento (questo
bit può essere messo o tolto in qualsiasi momento,
spedendo al controllo opportuni messaggi di
WM_SETREDRAW
, con wParam
rispettivamente FALSE
o TRUE
).
LBS_NOINTEGRALHEIGHT
evita che la
dimensione del controllo venga arrotondata ad un
multiplo intero dello spazio necessario per mostrare
ciascun elemento; di default, questo arrotondamento
avviene automaticamente, mentre, con questo bit, la
dimensione del controllo è invece esattamente
quella specificata dal programma.
Un controllo listbox mantiene una copia delle stringhe
relative agli elementi che contiene, a meno che il
listbox non sia "owner-drawn", nel qual caso ciò
normalmente non succede; ma si può specificare
il bit di stile LBS_HASSTRINGS
per far
sì che le stringhe vengano memorizzate anche
da un controllo listbox owner-drawn.
Il concetto di "owner-drawn" per un controllo listbox
è più raffinato che per i controlli che abbiamo
visto sinora, poichè il listbox ha molteplici
elementi ("item") e il disegno deve avvenire in modo
separato per ciascuno di essi.
Ad ogni WM_DRAWITEM
, lParam
sarà un puntatore ad una
struttura dati DRAWITEMSTRUCT
, che fra i
vari campi ne ha uno, itemID
, che
identifica l'esatto elemento di cui si richiede il
disegno, e un altro, itemData
,
che può portare
informazioni arbitrarie che il programma ha scelto
di associare al dato elemento (si tratta spesso di un
puntatore a una struttura di dati, o di un indice
in una tabella mantenuta dal programma).
Il controllo listbox può essere reso owner-drawn
da due diversi bit di stile (mutualmente esclusivi,
naturalmente): LBS_OWNERDRAWFIXED
,
se tutti gli elementi hanno la stessa altezza (il
programma dovrà allora rispondere a un singolo
messaggio WM_MEASUREITEM
, speditogli
alla creazione della lista, e i dati di dimensione
che fornirà in quell'occasione varranno per
ogni elemento);
LBS_OWNERDRAWVARIABLE
, se ogni elemento
può avere altezza diversa (in questo caso, il
messaggio WM_MEASUREITEM
verrà
spedito separatamente per ogni elemento da
disegnare).
LBS_NODATA
, che funziona
solo assieme a LBS_OWNERDRAWFIXED
,
e senza LBS_HASSTRINGS
, permette di
avere controlli listbox con un numero enorme di elementi
(altrimenti, vi è un limite attorno al migliaio), a
patto naturalmente che la finestra contenitrice si
prenda tutte le responsabilità di disegno dell'aspetto
di ciascun elemento a fronte della sola informazione
sul "numero di riga" dell'elemento stesso (è questo
che viene passato, in questo specifico caso, come
campo itemID
della struttura dati
DRAWITEMSTRUCT
che accompagna ciascun
messaggio WM_DRAWITEM
).
Al contrario, per il caso molto comune in cui dal
listbox non si voglia altro che un elenco di stringhe
in ordine alfabetico, si può lasciare l'intera
responsabilità dell'ordinamento al controllo
stesso, semplicemente dotandolo dei bit di stile
LBS_SORT
. Questo bit si può usare
anche per listbox owner-drawn privi del bit di stile
LBS_HASSTRINGS
, nel qual caso la finestra
che contiene il controllo listbox dovrà
rispondere ai messaggi WM_COMPAREITEM
che il controllo le lancerà quando necessario
per effettuare il sort degli elementi.
Il lettore è, naturalmente, incoraggiato a
sperimentare con tutti questi bit di stile, e le loro
combinazioni, magari sviluppando per gli stili dei
listbox un programmino di sperimentazione analogo a
quello che scrivemmo per quelli degli editbox nel
Capitolo 22 e seguenti. Si
userà il messaggio LB_ADDSTRING
,
cui già abbiamo accennato nei due capitoli
precedenti, per "popolare" opportunamente il
controllo listbox.
Naturalmente, molto dell'effetto dei bit di stile che abbiamo qui esaminato è legato ai vari messaggi inviati al controllo, e ai messaggi di notifica che il controllo a sua volta spedisce al contenitore; proseguiremo, dunque, l'esame di questi aspetti, al prossimo capitolo.
Capitolo 41: dialoghi non modali
Capitolo 43: messaggi ai LISTBOX (1)
Elenco dei capitoli