TTreeView Delphi-komponenten (placeret på fanen "Win32" -komponentpalette) repræsenterer et vindue, der viser et hierarkisk liste over elementer, såsom overskrifter i et dokument, posterne i et indeks eller filer og mapper på en disk.
Træknudepunkt med afkrydsningsfelt eller radioknap?
Delphis TTreeview understøtter ikke afkrydsningsfelter, men den underliggende WC_TREEVIEW-kontrol gør det. Du kan tilføje afkrydsningsfelter til treeview ved at tilsidesætte CreateParams-proceduren i TTreeView og specificere TVS_CHECKBOXES-stilen for kontrollen. Resultatet er, at alt knuder i oversigten vil der være tilknyttet afkrydsningsfelter. Derudover kan ejendommen StateImages ikke bruges mere, fordi WC_TREEVIEW bruger denne imageliste internt til at implementere afkrydsningsfelter. Hvis du vil skifte afkrydsningsfelterne, skal du gøre det ved hjælp af Send besked eller den TreeView_SetItem / TreeView_GetItem-makroer fra CommCtrl.pas. WC_TREEVIEW understøtter kun afkrydsningsfelter, ikke radioknapper.
Den fremgangsmåde, du skal opdage i denne artikel, er meget mere fleksibel: Du kan have afkrydsningsfelter og radioknapper blandet med andre noder, som du vil uden at ændre TTreeview eller oprette en ny klasse fra det at gøre dette arbejde. Du bestemmer også dig selv, hvilke billeder du skal bruge til afkrydsningsfelterne / radioknapperne ved blot at tilføje de rigtige billeder til StateImages-forestillingen.
Tilføj et afkrydsningsfelt eller radioknap
I modsætning til hvad du måske tror, er dette ganske enkelt at udføre i Delphi. Her er trinnene for at få det til at fungere:
- Opret en billedliste (TImageList-komponent på fanen "Win32" -komponentpalette) til TTreeview. StatImages egenskaber, der indeholder billederne til de markerede og ikke-markerede tilstand (er) til afkrydsningsfelter og / eller radioknapper.
- Ring til ToggleTreeViewCheckBoxes-proceduren (se nedenfor) i OnClick- og OnKeyDown-begivenhederne i treeview. ToggleTreeViewCheckBoxes-proceduren ændrer StateIndex for den valgte knude for at afspejle den aktuelle markerede / ikke-markerede tilstand.
For at gøre din treeview endnu mere professionel skal du kontrollere, hvor der klikkes på en knude, før du skifter til statebilleder: ved kun at skifte knude, når der klikkes på det faktiske billede, kan dine brugere stadig vælge noden uden at ændre dens stat.
Hvis du ikke ønsker, at dine brugere skal udvide / kollaps treeview, skal du ringe til FullExpand-proceduren i formularerne OnShow-begivenhed og indstille AllowCollapse til falsk i treeviews OnCollapsing-begivenhed.
Her er implementeringen af ToggleTreeViewCheckBoxes-proceduren:
procedure ToggleTreeViewCheckBoxes (
Knude: TTreeNode;
cUnChecked,
cChecked,
cRadioUnchecked,
cRadioChecked: heltal);
Var
tmp: TTreeNode;
beginif Tildelt (knudepunkt) thenbeginif Node. StateIndex = cUnchecked derefter
Node. StateIndex: = cChecked
andethvis Node. StateIndex = cChecked derefter
Node. StateIndex: = cUnChecked
ellers hvis Node. StateIndex = cRadioUnChecked thenbegin
tmp: = Knude. Forældre;
hvis ikke Tildelt (tmp) derefter
tmp: = TTreeView (knude. TreeView) .Items.getFirstNode
andet
tmp: = tmp.getFirstChild;
mens Tildelt (tmp) dobeginif (Tmp. StateIndex i
[cRadioUnChecked, cRadioChecked]) derefter
tmp. StateIndex: = cRadioUnChecked;
tmp: = tmp.getNextSibling;
ende;
Node. StateIndex: = cRadioChecked;
ende; // hvis StateIndex = cRadioUnCheckedende; // hvis tildelt (knudepunkt)
ende; (* ToggleTreeViewCheckBoxes *)
Som du kan se fra koden ovenfor, starter proceduren ved at finde nogen afkrydsningsfelt noder og bare slå dem til eller fra. Dernæst, hvis noden er en ikke-markeret radioknap, flytter proceduren til den første knude på det aktuelle niveau, indstiller alle noder på det niveau til cRadioUnchecked (hvis de er cRadioUnChecked eller cRadioChecked nodes) og skifter til sidst Node til cRadioChecked.
Bemærk, hvordan alle allerede kontrollerede radioknapper ignoreres. Det er klart, at det skyldes, at en allerede kontrolleret radioknap skulle skiftes til ikke-markeret og efterlade knudepunkterne i en udefineret tilstand. Næppe hvad du gerne vil have det meste af tiden.
Sådan gør du koden endnu mere professionel: I OnClick-begivenheden i Treeview skal du skrive følgende kode for kun at skifte til afkrydsningsfelter, hvis der blev klikket på stateimage (konstanterne cFlatUnCheck, cFlatChecked osv. er defineret andetsteds som indekser til statenImages billedliste):
procedure TForm1.TreeView1Klik (afsender: TObject);
Var
P: TPoint;
begynde
GetCursorPos (P);
P: = TreeView1.ScreenToClient (P);
hvis (htOnStateIcon i
TreeView1.GetHitTestInfoAt (P.X, P.Y)) derefter
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
ende; (* TreeView1Click *)
Koden får den aktuelle museposition, konverteres til treeview-koordinater og kontrollerer, om der blev klikket på StateIcon ved at kalde GetHitTestInfoAt-funktionen. Hvis det var tilfældet, kaldes koblingsproceduren.
Oftest ville du forvente, at mellemrumslinjen skifter afkrydsningsfelter eller radioknapper, så her er hvordan du skriver TreeView OnKeyDown-begivenheden ved hjælp af denne standard:
procedure TForm1.TreeView1KeyDown (
Afsender: TObject;
var Nøgle: Word;
Skift: TShiftState);
beginif (Nøgle = VK_SPACE) og
Tildelt (TreeView1.Selected) derefter
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
ende; (* TreeView1KeyDown *)
Endelig, her er hvordan formens OnShow og Treeviews OnChanging-begivenheder kunne se ud, hvis du ville forhindre sammenbrud i treeviewets knudepunkter:
procedure TForm1.FormCreate (Afsender: TObject);
begynde
TreeView1.FullExpand;
ende; (* FormCreate *)
procedure TForm1.TreeView1Collapsing (
Afsender: TObject;
Knude: TTreeNode;
Var Tillad kollaps: Boolsk);
begynde
Tillad kollaps: = falsk;
ende; (* TreeView1Collapsing *)
Til sidst, for at kontrollere, om en knude er kontrolleret, skal du blot foretage følgende sammenligning (i en Buttons OnClick-begivenhedshåndterer, for eksempel):
procedure TForm1.Button1Click (Afsender: TObject);
Var
BoolResult: boolean;
tn: TTreeNode;
beginif Tildelt (TreeView1.Selected) thenbegin
tn: = TreeView1.Valget;
BoolResult: = tn. StateIndex i
[cFlatChecked, cFlatRadioChecked];
Memo1.Text: = tn. Tekst +
#13#10 +
'Valgt:' +
BoolToStr (BoolResult, sandt);
ende;
ende; (* Button1Click *)
Selvom denne type kodning ikke kan betragtes som missionskritisk, kan den give dine applikationer et mere professionelt og glattere look. Ved at bruge afkrydsningsfelterne og radioknapperne med omtanke kan de også gøre din applikation lettere at bruge. De vil helt sikkert se godt ud!
Dette billede nedenfor er taget fra en testapp ved hjælp af koden beskrevet i denne artikel. Som du kan se, kan du frit blande noder med afkrydsningsfelter eller radioknapper med dem, der ikke har nogen, selvom du ikke bør blande "tomme" noder med "afkrydsningsfeltet"noder (se på radioknapperne på billedet), da dette gør det meget svært at se, hvilke noder der er relateret.