TreeView med kryssrutor och radioknappar

TTreeView Delphi-komponenten (som finns på fliken "Win32" -komponentpalett) representerar ett fönster som visar ett hierarkiska lista över objekt, såsom rubriker i ett dokument, poster i ett index eller filer och kataloger på en skiva.

Trädnod med kryssruta eller radioknapp?

Delphis TTreeview stöder inte naturligtvis kryssrutor men den underliggande WC_TREEVIEW-kontrollen gör det. Du kan lägga till kryssrutor i trädvy genom att åsidosätta proceduren CreateParams i TTreeView, ange TVS_CHECKBOXES-formatet för kontrollen. Resultatet är att allt knutpunkter i trevisningen har kryssrutor kopplade till dem. Dessutom kan egenskapen StateImages inte användas längre eftersom WC_TREEVIEW använder denna bildlista internt för att implementera kryssrutor. Om du vill växla i kryssrutorna måste du göra det med Skicka meddelande eller den TreeView_SetItem / TreeView_GetItem-makron från CommCtrl.pas. WC_TREEVIEW stöder endast kryssrutor, inte radioknappar.

Den metod du ska upptäcka i den här artikeln är mycket mer flexibel: du kan ha kryssrutor och radioknappar blandade med andra noder som du vill utan att ändra TTreeview eller skapa en ny

instagram viewer
klass från det för att få detta att fungera. Du bestämmer också själv vilka bilder du ska använda för kryssrutorna / radioknapparna genom att helt enkelt lägga till de rätta bilderna till StateImages-fantasin.

Lägg till en kryssruta eller radioknapp

I motsats till vad du kanske tror är detta ganska enkelt att utföra Delphi. Här är stegen för att få det att fungera:

  1. Ställ in en bildlista (TImageList-komponent på fliken "Win32" -komponentpalett) för TTreeview. Egenskapen StateImages som innehåller bilderna för de markerade och oavkryssade lägena för kryssrutor och / eller radioknappar.
  2. Ring proceduren ToggleTreeViewCheckBoxes (se nedan) i OnClick- och OnKeyDown-händelserna i treeview. ToggleTreeViewCheckBoxes-förfarandet ändrar StateIndex för den valda noden för att återspegla det aktuella kontrollerade / avmarkerade tillståndet.

För att göra din trevy ännu mer professionell bör du kontrollera var du klickar på en nod innan du växlar till statliga bilder: genom att bara växla till noden när man klickar på den verkliga bilden kan dina användare fortfarande välja noden utan att ändra den stat.

Om du inte vill att dina användare ska utöka / kollapsa treeviewen kan du dessutom ringa FullExpand-proceduren i formuläret OnShow-händelse och ställa AllowCollapse till falsk i treeviews OnCollapsing-händelse.

Här är implementeringen av ToggleTreeViewCheckBoxes-proceduren:

procedur ToggleTreeViewCheckBoxes (
Nod: TTreeNode;
cUnChecked,
cChecked,
cRadioUnchecked,
cRadioChecked: heltal);
var
tmp: TTreeNode;
beginif Tilldelad (nod) thenbeginif Nod. StateIndex = cUnChecked sedan
Nod. StateIndex: = cChecked
annanom Nod. StateIndex = cChecked sedan
Nod. StateIndex: = cUnChecked
annars om Nod. StateIndex = cRadioUnChecked thenbegin
tmp: = Nod. Förälder;
om inte Tilldelad (tmp) sedan
tmp: = TTreeView (Node. Treeview) .Items.getFirstNode
annan
tmp: = tmp.getFirstChild;
medan Tilldelad (tmp) dobeginif (Tmp. StateIndex i
[cRadioUnChecked, cRadioChecked]) sedan
tmp. StateIndex: = cRadioUnChecked;
tmp: = tmp.getNextSibling;
slutet;
Nod. StateIndex: = cRadioChecked;
slutet; // om StateIndex = cRadioUnCheckedslutet; // if Tilldelad (Node)
slutet; (* ToggleTreeViewCheckBoxes *)

Som du kan se från koden ovan, börjar proceduren genom att hitta alla kryssrutanoder och bara slå på eller av dem. Därefter, om noden är en okontrollerad radioknapp, flyttar proceduren till den första noden på den aktuella nivån, ställer in alla noder på den nivån till cRadioUnchecked (om de är cRadioUnChecked eller cRadioChecked noder) och växlar slutligen Node till cRadioChecked.

Lägg märke till hur någon redan kontrollerad radioknapp ignoreras. Uppenbarligen beror detta på att en redan kontrollerad radioknapp skulle växlas till okontrollerad och lämna noderna i ett odefinierat tillstånd. Knappast vad du vill ha mest av tiden.

Så här gör du koden ännu mer professionell: i OnClick-händelsen i Treeview, skriv följande kod för att bara växla kryssrutor om statisk bild klickades (konstaterna cFlatUnCheck, cFlatChecked etc definieras på annat håll som index till statenImages bildlista):

procedur TForm1.TreeView1Click (avsändare: TObject);
var
P: TPoint;
Börja
GetCursorPos (P);
P: = TreeView1.ScreenToClient (P);
om (htOnStateIcon i
TreeView1.GetHitTestInfoAt (P.X, P.Y)) sedan
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
slutet; (* TreeView1Click *)

Koden får den aktuella muspositionen, konverterar till treeview-koordinater och kontrollerar om StateIcon klickades genom att ringa GetHitTestInfoAt-funktionen. Om det var så kallas växlingsproceduren.

Vanligtvis kan du förvänta dig att mellanslagsfältet växlar kryssrutor eller radioknappar, så här skriver du TreeView OnKeyDown-händelsen med den standarden:

procedur TForm1.TreeView1KeyDown (
Avsändare: TObject;
var Nyckel: Word;
Skift: TShiftState);
beginif (Nyckel = VK_SPACE) och
Tilldelad (TreeView1.Selected) sedan
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
slutet; (* TreeView1KeyDown *)

Slutligen, här är hur formens OnShow och Treeviews OnChanging-händelser kan se ut om du ville förhindra att treeviews noder kollapsar:

procedur TForm1.FormCreate (avsändare: TObject);
Börja
TreeView1.FullExpand;
slutet; (* FormCreate *)
procedur TForm1.TreeView1Collapsing (
Avsändare: TObject;
Nod: TTreeNode;
var AllowCollapse: Boolean);
Börja
AllowCollapse: = falsk;
slutet; (* TreeView1Collapsing *)

Slutligen, för att kontrollera om en nod är markerad, gör du bara följande jämförelse (i en Buttons OnClick-händelseshanterare, till exempel):

procedur TForm1.Button1Click (avsändare: TObject);
var
BoolResult: boolean;
tn: TTreeNode;
beginif Tilldelad (TreeView1.Selected) thenbegin
tn: = TreeView1.Valt;
BoolResult: = tn. StateIndex i
[cFlatChecked, cFlatRadioChecked];
Memo1.Text: = tn. Text +
#13#10 +
'Vald:' +
BoolToStr (BoolResult, True);
slutet;
slutet; (* Button1Click *)

Även om den här typen av kodning inte kan betraktas som uppdragskritisk, kan den ge dina applikationer ett mer professionellt och smidigare utseende. Genom att använda kryssrutorna och radioknapparna på ett korrekt sätt kan de göra din applikation lättare att använda. De kommer säkert att se bra ut!

Den här bilden nedan togs från en testapp med koden som beskrivs i den här artikeln. Som du kan se kan du fritt blanda noder med kryssrutor eller radioknappar med de som inte har några, även om du inte bör blanda "tomma" noder med "kryssruta"noder (titta på radioknapparna i bilden) eftersom det gör det mycket svårt att se vilka noder som är relaterade.

instagram story viewer