De TTreeView Delphi-component (op het tabblad "Win32" -componentenpalet) 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.
Boomknooppunt met selectievakje of keuzerondje?
Delphi's TTreeview ondersteunt niet standaard selectievakjes, maar het onderliggende WC_TREEVIEW-besturingselement wel. U kunt selectievakjes toevoegen aan de boom zicht door de procedure CreateParams van TTreeView te overschrijven, waarbij de stijl TVS_CHECKBOXES voor het besturingselement wordt gespecificeerd. Het resultaat is dat alles knooppunten in de boomstructuur staan selectievakjes. Bovendien kan de eigenschap StateImages niet meer worden gebruikt omdat WC_TREEVIEW deze afbeeldingenlijst intern gebruikt om selectievakjes te implementeren. Als u de selectievakjes wilt omschakelen, 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 aanpak die u in dit artikel moet ontdekken, is veel flexibeler: u kunt selectievakjes hebben en keuzerondjes gemengd met andere knooppunten op elke gewenste manier zonder de TTreeview te wijzigen of een nieuwe te maken klasse ervan om dit te laten werken. U bepaalt ook zelf welke afbeeldingen u wilt gebruiken voor de selectievakjes / radiobuttons door simpelweg de juiste afbeeldingen toe te voegen aan de StateImages-afbeeldingenlijst.
Voeg een selectievakje of keuzerondje toe
In tegenstelling tot wat je misschien denkt, is dit vrij eenvoudig te bereiken Delphi. Hier zijn de stappen om het te laten werken:
- Stel een afbeeldingslijst in (TImageList-component op het tabblad "Win32" -componentenpalet) voor de TTreeview. StateImages-eigenschap met de afbeeldingen voor de aangevinkte en niet-aangevinkte staat (en) voor selectievakjes en / of keuzerondjes.
- Roep de ToggleTreeViewCheckBoxes-procedure aan (zie hieronder) in de OnClick- en OnKeyDown-gebeurtenissen van de boomweergave. De ToggleTreeViewCheckBoxes-procedure verandert de StateIndex van het geselecteerde knooppunt om de huidige gecontroleerde / niet-gecontroleerde status weer te geven.
Om uw boomweergave nog professioneler te maken, moet u controleren waar op een knooppunt wordt geklikt voordat u de statusafbeeldingen wijzigt: door alleen het knooppunt te wisselen wanneer er op de daadwerkelijke afbeelding wordt geklikt, kunnen uw gebruikers het knooppunt nog steeds selecteren zonder het te wijzigen staat.
Als u bovendien niet wilt dat uw gebruikers de boomweergave uitbreiden / samenvouwen, roept u de FullExpand-procedure aan in de vorm OnShow-gebeurtenis en stelt u AllowCollapse in op false in de OnCollapsing-gebeurtenis van de boomstructuur.
Hier is de implementatie van de ToggleTreeViewCheckBoxes-procedure:
procedure ToggleTreeViewCheckBoxes (
Knooppunt: TTreeNode;
cUnChecked,
cGecontroleerd,
cRadioUnchecked,
cRadioChecked: integer);
var
tmp: TTreeNode;
beginif Toegewezen (knooppunt) thenbeginif Knooppunt. StateIndex = cUnChecked vervolgens
Knooppunt. StateIndex: = cChecked
andersals Knooppunt. StateIndex = cChecked vervolgens
Knooppunt. StateIndex: = cUnChecked
anders als Knooppunt. StateIndex = cRadioUnChecked dan beginnen
tmp: = Knooppunt. Ouder;
als niet Toegewezen (tmp) vervolgens
tmp: = TTreeView (Knooppunt. TreeView) .Items.getFirstNode
anders
tmp: = tmp.getFirstChild;
terwijl Toegewezen (tmp) dobeginif (tmp. StateIndex in
[cRadioUnChecked, cRadioChecked]) vervolgens
tmp. StateIndex: = cRadioUnChecked;
tmp: = tmp.getNextSibling;
einde;
Knooppunt. StateIndex: = cRadioChecked;
einde; // als StateIndex = cRadioUnCheckedeinde; // indien toegewezen (knooppunt)
einde; (* ToggleTreeViewCheckBoxes *)
Zoals je kunt zien aan de hand van de bovenstaande code, begint de procedure met het vinden van checkbox-knooppunten en deze gewoon in- of uitschakelen. Als het knooppunt vervolgens een niet-aangevinkt keuzerondje is, wordt de procedure verplaatst naar het eerste knooppunt op het huidige niveau, worden alle knooppunten ingesteld op dat niveau naar cRadioUnchecked (als het cRadioUnChecked of cRadioChecked nodes zijn) en schakelt tenslotte Node naar cRadioChecked.
Merk op hoe reeds aangevinkte keuzerondjes worden genegeerd. Het is duidelijk dat dit komt omdat een reeds aangevinkt keuzerondje zou worden omgeschakeld naar niet-aangevinkt, waardoor de knooppunten in een ongedefinieerde staat blijven. Bijna niet wat je meestal zou willen.
Hier leest u hoe u de code nog professioneler kunt maken: in het OnClick-evenement van de Treeview, schrijft u de volgende code om alleen de selectievakjes als op de statusafbeelding is geklikt (de constanten cFlatUnCheck, cFlatChecked enz.) worden elders gedefinieerd als indexen in de StateImages afbeelding lijst):
procedure TForm1.TreeView1Click (Afzender: TObject);
var
P: TPoint;
beginnen
GetCursorPos (P);
P: = TreeView1.ScreenToClient (P);
als (htOnStateIcon in
TreeView1.GetHitTestInfoAt (P.X, P.Y)) vervolgens
ToggleTreeViewCheckBoxes (
TreeView1. Geselecteerd,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
einde; (* TreeView1Click *)
De code krijgt de huidige muispositie, wordt geconverteerd naar treeview-coördinaten en controleert of er op de StateIcon is geklikt door de functie GetHitTestInfoAt aan te roepen. Als dat zo was, wordt de wisselprocedure aangeroepen.
Meestal zou je verwachten dat de spatiebalk selectievakjes of keuzerondjes omschakelt, dus hier is hoe je de TreeView OnKeyDown-gebeurtenis schrijft met die standaard:
procedure TForm1.TreeView1KeyDown (
Afzender: TObject;
var Sleutel: Word;
Shift: TShiftState);
beginif (Sleutel = VK_SPACE) en
Toegewezen (TreeView1.Selected) vervolgens
ToggleTreeViewCheckBoxes (
TreeView1. Geselecteerd,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
einde; (* TreeView1KeyDown *)
Tot slot, hier is hoe de OnShow van het formulier en de OnChanging-gebeurtenissen van de Treeview eruit zouden kunnen zien als u wilt voorkomen dat de knooppunten van de treeview inklappen:
procedure TForm1.FormCreate (Afzender: TObject);
beginnen
TreeView1.FullExpand;
einde; (* FormCreate *)
procedure TForm1.TreeView1Collapsing (
Afzender: TObject;
Knooppunt: TTreeNode;
var AllowCollapse: Boolean);
beginnen
AllowCollapse: = false;
einde; (* TreeView1Collapsing *)
Om ten slotte te controleren of een knooppunt is gecontroleerd, doet u eenvoudig de volgende vergelijking (bijvoorbeeld in de OnClick-gebeurtenishandler van een knop):
procedure TForm1.Button1Click (Afzender: TObject);
var
BoolResult: boolean;
tn: TTreeNode;
beginif Toegewezen (TreeView1.Selected) dan beginnen
tn: = TreeView1.Selected;
BoolResult: = tn. StateIndex in
[cFlatChecked, cFlatRadioChecked];
Memo1.Text: = tn. Tekst +
#13#10 +
'Geselecteerd:' +
BoolToStr (BoolResult, True);
einde;
einde; (* Button1Click *)
Hoewel dit type codering niet als bedrijfskritisch kan worden beschouwd, kan het uw applicaties een professioneler en soepeler uiterlijk geven. Door de selectievakjes en keuzerondjes oordeelkundig te gebruiken, kunnen ze uw toepassing ook gebruiksvriendelijker maken. Ze zien er zeker goed uit!
Deze afbeelding hieronder is afkomstig uit een test-app met behulp van de code die in dit artikel wordt beschreven. Zoals u kunt zien, kunt u knooppunten met selectievakjes of keuzerondjes vrij combineren met die zonder, hoewel u geen "lege" knooppunten moet mengen met "checkbox"knooppunten (bekijk de keuzerondjes in de afbeelding) omdat dit het erg moeilijk maakt om te zien welke knooppunten gerelateerd zijn.