De component TTreeView Delphi (op het tabblad van het componentpalet "Win32") vertegenwoordigt een venster met een hiërarchische lijst met items, zoals de koppen in een document, de vermeldingen in een index of de bestanden en mappen op een schijf.
TTreeview van Delphi ondersteunt geen native selectievakjes, maar het onderliggende WC_TREEVIEW-besturingselement wel. U kunt selectievakjes toevoegen aan de boomstructuur door de CreateParams-procedure van TTreeView te negeren en de stijl TVS_CHECKBOXES voor het besturingselement op te geven. Het resultaat is dat aan alle knooppunten in de boomstructuur selectievakjes zijn gekoppeld. Bovendien kan de eigenschap StateImages niet meer worden gebruikt omdat de WC_TREEVIEW deze beeldlijst intern gebruikt om selectievakjes te implementeren. Als u de selectievakjes wilt inschakelen, moet u dat doen met Bericht versturen of de TreeView_SetItem / TreeView_GetItem macro's van CommCtrl.pas. De WC_TREEVIEW ondersteunt alleen selectievakjes, geen keuzerondjes.
De benadering die u in dit artikel zult ontdekken, is veel flexibeler: u kunt selectievakjes en keuzerondjes op elke gewenste manier met andere knooppunten mengen zonder de TTreeview te wijzigen of er een nieuwe klasse van maken om dit te laten werken. U bepaalt ook zelf welke afbeeldingen u wilt gebruiken voor de selectievakjes / radioknoppen door de juiste afbeeldingen toe te voegen aan de imagelist van StateImages.
In tegenstelling tot wat je misschien denkt, is dit vrij eenvoudig te bereiken in Delphi. Hier zijn de stappen om het te laten werken:
Om uw boomweergave nog professioneler te maken, moet u controleren waar op een knoop wordt geklikt voordat u de statusbeelden omschakelt: door alleen op de knoop te schakelen wanneer op de werkelijke afbeelding wordt geklikt, kunnen uw gebruikers de knoop nog steeds selecteren zonder de status te wijzigen.
Als u niet wilt dat uw gebruikers de boomstructuur uitvouwen / samenvouwen, roept u de procedure FullExpand in de formulieren OnShow-gebeurtenis aan en stelt u AllowCollapse in op onwaar in de gebeurtenis OnCollapsing van de boomstructuur.
Hier is de implementatie van de ToggleTreeViewCheckBoxes-procedure:
procedure ToggleTreeViewCheckBoxes (
Knooppunt: TTreeNode;
cUnChecked,
cChecked,
cRadioUnchecked,
cRadioChecked: geheel getal);
var
tmp: TTreeNode;
beginif Toegewezen (Node) thenbeginif Node.StateIndex = cUnChecked vervolgens
Node.StateIndex: = cChecked
anders als Node.StateIndex = cChecked vervolgens
Node.StateIndex: = cUnChecked
anders als Node.StateIndex = cRadioUnChecked thenbegin
tmp: = Node.Parent;
als niet Toegewezen (TMP) vervolgens
tmp: = TTreeView (Node.TreeView) .Items.getFirstNode
anders
tmp: = tmp.getFirstChild;
terwijl Toegewezen (TMP) dobeginif (tmp.StateIndex in
[CRadioUnChecked, cRadioChecked]) vervolgens
tmp.StateIndex: = cRadioUnChecked;
tmp: = tmp.getNextSibling;
einde;
Node.StateIndex: = cRadioChecked;
einde; // if StateIndex = cRadioUnCheckedeinde; // if Assigned (Node)
einde; (* ToggleTreeViewCheckBoxes *)
Zoals u kunt zien in de bovenstaande code, begint de procedure met het zoeken naar eventuele selectievakjes en deze gewoon in of uit te schakelen. Vervolgens, als het knooppunt een niet-aangevinkt keuzerondje is, wordt de procedure verplaatst naar het eerste knooppunt op het huidige niveau, worden alle knooppunten op dat niveau ingesteld op cRadioUnchecked (als ze cRadioUnChecked of cRadioChecked zijn) en schakelt u eindelijk Knooppunt naar cRadioChecked.
Merk op dat alle aangevinkte keuzerondjes worden genegeerd. Het is duidelijk dat dit komt omdat een reeds aangevinkt keuzerondje wordt uitgeschakeld of uitgeschakeld, waardoor de knooppunten ongedefinieerd blijven. Nauwelijks wat je de meeste tijd zou willen.
Ga als volgt te werk om de code nog professioneler te maken: schrijf in het OnClick-evenement van de Treeview de volgende code om alleen de selectievakjes in of uit te schakelen als op de statusafbeelding is geklikt (de cFlatUnCheck, cFlatChecked enz. Constanten worden elders gedefinieerd als indexen in de StateImages-afbeeldingenlijst) :
procedure TForm1.TreeView1Click (Sender: TObject);
var
P: TPoint;
beginnen
GetCursorPos (P);
P: = TreeView1.ScreenToClient (P);
als (htOnStateIcon in
TreeView1.GetHitTestInfoAt (P.X, P.Y)) vervolgens
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
einde; (* TreeView1Click *)
De code krijgt de huidige muispositie, converteert naar treeview-coördinaten en controleert of er op de StateIcon is geklikt door de functie GetHitTestInfoAt aan te roepen. Als dit het geval was, wordt de schakelprocedure aangeroepen.
Meestal verwacht je dat de spatiebalk selectievakjes of keuzerondjes inschakelt, dus hier is hoe je de TreeView OnKeyDown-gebeurtenis schrijft met behulp van die standaard:
procedure TForm1.TreeView1KeyDown (
Afzender: TObject;
var Sleutel: Word;
Shift: TShiftState);
beginif (Sleutel = VK_SPACE) en
Toegewezen (TreeView1.Selected) vervolgens
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
einde; (* TreeView1KeyDown *)
Eindelijk, hier is hoe het formulier OnShow en de OnChanging-evenementen van Treeview eruit zouden kunnen zien als je wilde voorkomen dat de knooppunten van de boomstructuur ineenstorten:
procedure TForm1.FormCreate (Sender: TObject);
beginnen
TreeView1.FullExpand;
einde; (* FormCreate *)
procedure TForm1.TreeView1Collapsing (
Afzender: TObject;
Knooppunt: TTreeNode;
var AllowCollapse: Boolean);
beginnen
AllowCollapse: = false;
einde; (* TreeView1Collapsing *)
Ten slotte, om te controleren of een knoop is aangevinkt, doet u eenvoudig de volgende vergelijking (bijvoorbeeld in de OnClick-gebeurtenishandler van een Button):
procedure TForm1.Button1Click (Sender: TObject);
var
BoolResult: boolean;
tn: TTreeNode;
beginif Toegewezen (TreeView1.Selected) thenbegin
tn: = TreeView1.Selected;
BoolResult: = tn.StateIndex in
[CFlatChecked, cFlatRadioChecked];
Memo1.Text: = tn.Text +
# 13 # 10 +
'Geselecteerd: ' +
BoolToStr (BoolResult, True);
einde;
einde; (* Button1Click *)
Hoewel dit type codering niet als bedrijfskritisch kan worden beschouwd, kan het uw applicaties een professionelere en soepelere uitstraling geven. Door de selectievakjes en keuzerondjes oordeelkundig te gebruiken, kunnen ze uw toepassing ook gemakkelijker te gebruiken maken. Ze zullen er zeker goed uitzien!
Deze afbeelding hieronder is afkomstig van een test-app met de code die in dit artikel wordt beschreven. Zoals je kunt zien, kun je vrijelijk knooppunten met selectievakjes of keuzerondjes combineren met die zonder, hoewel je "lege" knooppunten niet moet combineren met "selectievakje" -knooppunten (kijk naar de keuzerondjes in de afbeelding) omdat dit maakt het erg moeilijk om te zien welke knooppunten gerelateerd zijn.