Il componente TTreeView Delphi (situato nella scheda della tavolozza dei componenti "Win32") rappresenta una finestra che visualizza un elenco gerarchico di elementi, come le intestazioni in un documento, le voci in un indice o i file e le directory su un disco.
La TTreeview di Delphi non supporta nativamente le caselle di controllo ma il controllo WC_TREEVIEW sottostante lo fa. È possibile aggiungere caselle di controllo alla vista ad albero ignorando la procedura CreateParams di TTreeView, specificando lo stile TVS_CHECKBOXES per il controllo. Il risultato è che tutti i nodi nella treeview avranno caselle di controllo associate. Inoltre, la proprietà StateImages non può più essere utilizzata perché WC_TREEVIEW utilizza questa lista immagini internamente per implementare le caselle di controllo. Se vuoi attivare / disattivare le caselle di controllo, dovrai farlo utilizzando Invia messaggio o il Macro TreeView_SetItem / TreeView_GetItem a partire dal CommCtrl.pas. WC_TREEVIEW supporta solo caselle di controllo, non pulsanti di opzione.
L'approccio che stai per scoprire in questo articolo è molto più flessibile: puoi avere caselle di controllo e pulsanti di opzione mescolati con altri nodi come preferisci senza cambiare il TTreeview o creare una nuova classe da esso per farlo funzionare. Inoltre, decidi tu quali immagini utilizzare per le caselle di controllo / i pulsanti radio semplicemente aggiungendo le immagini appropriate all'immagine di StateImages.
Contrariamente a quello che potresti credere, questo è abbastanza semplice da realizzare in Delphi. Ecco i passaggi per farlo funzionare:
Per rendere la tua treeview ancora più professionale, dovresti controllare dove si fa clic su un nodo prima di attivare / disattivare le immagini di stato: attivando / disattivando il nodo solo quando si fa clic sull'immagine effettiva, gli utenti possono comunque selezionare il nodo senza modificarne lo stato.
Inoltre, se non si desidera che gli utenti espandano / comprimano il treeview, chiamare la procedura FullExpand nell'evento OnShow dei moduli e impostare AllowCollapse su false nell'evento OnCollapsing del treeview.
Ecco l'implementazione della procedura ToggleTreeViewCheckBoxes:
procedura ToggleTreeViewCheckBoxes (
Nodo: TTreeNode;
cUnChecked,
cChecked,
cRadioUnchecked,
cRadioChecked: intero);
var
tmp: TTreeNode;
beginif Assegnato (Node) thenbeginif Node.StateIndex = cUnChecked poi
Node.StateIndex: = cChecked
altro Se Node.StateIndex = cChecked poi
Node.StateIndex: = cUnChecked
altro se Node.StateIndex = cRadioUnChecked thenbegin
tmp: = Node.Parent;
altrimenti Assegnato (tmp) poi
tmp: = TTreeView (Node.TreeView) .Items.getFirstNode
altro
tmp: = tmp.getFirstChild;
mentre Assegnato (tmp) dobeginif (tmp.StateIndex nel
[CRadioUnChecked, cRadioChecked]) poi
tmp.StateIndex: = cRadioUnChecked;
tmp: = tmp.getNextSibling;
fine;
Node.StateIndex: = cRadioChecked;
fine; // se StateIndex = cRadioUnCheckedfine; // se assegnato (nodo)
fine; (* ToggleTreeViewCheckBoxes *)
Come puoi vedere dal codice sopra, la procedura inizia trovando tutti i nodi della casella di controllo e semplicemente attivandoli o disattivandoli. Successivamente, se il nodo è un pulsante di opzione non selezionato, la procedura passa al primo nodo al livello corrente, imposta tutti i nodi su quel livello su cRadioUnchecked (se sono nodi cRadioUnChecked o cRadioChecked) e infine attiva Nodo su cRadioChecked.
Notare come i pulsanti di opzione già selezionati vengono ignorati. Ovviamente, questo perché un pulsante di opzione già selezionato verrebbe disattivato, lasciando i nodi in uno stato indefinito. Difficilmente quello che vorresti la maggior parte del tempo.
Ecco come rendere il codice ancora più professionale: nell'evento OnClick di Treeview, scrivi il codice seguente per attivare o disattivare le caselle di controllo solo se è stato fatto clic sullo stato dell'immagine (le costanti cFlatUnCheck, cFlatChecked ecc sono definite altrove come indici nell'elenco di immagini StateImages) :
procedura TForm1.TreeView1Click (Mittente: TObject);
var
P: TPoint;
inizio
GetCursorPos (P);
P: = TreeView1.ScreenToClient (P);
Se (htOnStateIcon nel
TreeView1.GetHitTestInfoAt (P.X, P.Y)) poi
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
fine; (* TreeView1Click *)
Il codice ottiene la posizione corrente del mouse, si converte in coordinate di treeview e verifica se è stato fatto clic su StateIcon chiamando la funzione GetHitTestInfoAt. In tal caso, viene chiamata la procedura di attivazione / disattivazione.
Per lo più, ti aspetteresti che la barra spaziatrice commuti le caselle di controllo o i pulsanti di opzione, quindi ecco come scrivere l'evento TreeView OnKeyDown usando quello standard:
procedura TForm1.TreeView1KeyDown (
Mittente: TObject;
var chiave: Word;
Maiusc: TShiftState);
beginif (Key = VK_SPACE) e
Assegnato (TreeView1.Selected) poi
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
fine; (* TreeView1KeyDown *)
Infine, ecco come potrebbero apparire gli eventi OnShow del modulo e OnChanging di Treeview se si volesse impedire il collasso dei nodi del treeview:
procedura TForm1.FormCreate (Mittente: TObject);
inizio
TreeView1.FullExpand;
fine; (* FormCreate *)
procedura TForm1.TreeView1Collapsing (
Mittente: TObject;
Nodo: TTreeNode;
var AllowCollapse: Boolean);
inizio
AllowCollapse: = false;
fine; (* TreeView1Collapsing *)
Infine, per verificare se un nodo è selezionato, devi semplicemente fare il seguente confronto (ad esempio nel gestore di eventi OnClick di Button):
procedura TForm1.Button1Click (Mittente: TObject);
var
BoolResult: boolean;
tn: TTreeNode;
beginif Assegnato (TreeView1.Selected) thenbegin
tn: = TreeView1.Selected;
BoolResult: = tn.StateIndex nel
[CFlatChecked, cFlatRadioChecked];
Memo1.Text: = tn.Text +
# 13 # 10 +
'Selezionato: ' +
BoolToStr (BoolResult, True);
fine;
fine; (* Button1Click *)
Sebbene questo tipo di codifica non possa essere considerato mission-critical, può dare alle tue applicazioni un aspetto più professionale e fluido. Inoltre, utilizzando le caselle di controllo e i pulsanti di opzione in modo giudizioso, possono semplificare l'utilizzo dell'applicazione. Di sicuro staranno bene!
L'immagine seguente è stata presa da un'app di test usando il codice descritto in questo articolo. Come puoi vedere, puoi mescolare liberamente nodi con caselle di controllo o pulsanti di opzione con quelli che non ne hanno, anche se non dovresti mescolare nodi "vuoti" con nodi "checkbox" (dai un'occhiata ai pulsanti di opzione nell'immagine) come questo rende molto difficile vedere quali nodi sono correlati.