TreeView z polami wyboru i przyciskami radiowymi

Składnik TTreeView Delphi (znajdujący się na karcie palety składników „Win32”) reprezentuje okno, w którym wyświetla się hierarchiczna lista elementów, takich jak nagłówki w dokumencie, wpisy w indeksie lub pliki i katalogi na dysk.

Węzeł drzewny z polem wyboru lub przyciskiem radiowym?

TTreeview Delphi nie obsługuje natywnie pól wyboru, ale bazowa kontrola WC_TREEVIEW tak. Możesz dodać pola wyboru do widok drzewa poprzez przesłonięcie procedury CreateParams TTreeView, określając styl TVS_CHECKBOXES dla kontrolki. Rezultat jest taki, że wszystko węzły w widoku drzewa będą do nich dołączone pola wyboru. Ponadto nie można już używać właściwości StateImages, ponieważ WC_TREEVIEW używa tej listy obrazków wewnętrznie do implementacji pól wyboru. Jeśli chcesz przełączać pola wyboru, musisz to zrobić za pomocą Wyślij wiadomość albo Makra TreeView_SetItem / TreeView_GetItem od CommCtrl.pas. WC_TREEVIEW obsługuje tylko pola wyboru, a nie przyciski opcji.

Podejście, które odkryjesz w tym artykule, jest znacznie bardziej elastyczne: możesz mieć pola wyboru i przyciski radiowe mieszane z innymi węzłami w dowolny sposób bez zmiany TTreeview lub tworzenia nowego

instagram viewer
klasa z tego, aby to zadziałało. Ponadto sam decydujesz, jakich obrazów użyć dla pól wyboru / przycisków radiowych, po prostu dodając odpowiednie obrazy do listy obrazków StateImages.

Dodaj pole wyboru lub przycisk opcji

W przeciwieństwie do tego, w co możesz uwierzyć, jest to dość proste do osiągnięcia Delfy. Oto kroki, aby to zadziałało:

  1. Skonfiguruj listę obrazów (składnik TImageList na karcie palety składników „Win32”) dla TTreeview. Właściwość StateImages zawierająca obrazy dla zaznaczonych i niezaznaczonych stanów dla pól wyboru i / lub przycisków opcji.
  2. Wywołaj procedurę ToggleTreeViewCheckBoxes (patrz poniżej) w zdarzeniach OnClick i OnKeyDown widoku drzewa. Procedura ToggleTreeViewCheckBoxes zmienia StateIndex wybranego węzła, aby odzwierciedlić bieżący stan zaznaczony / niezaznaczony.

Aby uczynić widok drzewa jeszcze bardziej profesjonalnym, przed przełączeniem obrazów stanu należy sprawdzić, gdzie kliknięto węzeł: przełączając węzeł tylko po kliknięciu rzeczywistego obrazu, użytkownicy mogą nadal wybierać węzeł bez zmiany jego stan.

Ponadto, jeśli nie chcesz, aby użytkownicy rozszerzali / zwijali widok drzewa, wywołaj procedurę FullExpand w zdarzeniu OnShow formularzy i ustaw AllowCollapse na wartość false w zdarzeniu OnCollapsing drzewa.

Oto implementacja procedury ToggleTreeViewCheckBoxes:

procedura ToggleTreeViewCheckBoxes (
Węzeł: TTreeNode;
cUnChecked,
cSprawdzono,
cRadioUnchecked,
cRadioChecked: liczba całkowita);
var
tmp: TTreeNode;
beginif Przypisany (węzeł) thenbeginif Węzeł. StateIndex = cUnChecked następnie
Węzeł. StateIndex: = cSprawdzone
jeszczegdyby Węzeł. StateIndex = cSprawdzone następnie
Węzeł. StateIndex: = cUnChecked
inaczej jeśli Węzeł. StateIndex = cRadioUnChecked wtedy zacznij
tmp: = węzeł. Rodzic;
Jeśli nie Przypisany (tmp) następnie
tmp: = TTreeView (węzeł. TreeView) .Items.getFirstNode
jeszcze
tmp: = tmp.getFirstChild;
podczas Przypisany (tmp) dobeginif (tmp. StateIndex w
[cRadioUnChecked, cRadioChecked]) następnie
tmp. StateIndex: = cRadioUnChecked;
tmp: = tmp.getNextSibling;
koniec;
Węzeł. StateIndex: = cRadioChecked;
koniec; // if StateIndex = cRadioUnCheckedkoniec; // if Assigned (Node)
koniec; (* ToggleTreeViewCheckBoxes *)

Jak widać z powyższego kodu, procedura rozpoczyna się od znalezienia dowolnych węzłów pola wyboru i po prostu ich włączenia lub wyłączenia. Następnie, jeśli węzeł jest niezaznaczonym przyciskiem radiowym, procedura przechodzi do pierwszego węzła na bieżącym poziomie, ustawia wszystkie węzły na tym poziomie do cRadioUnchecked (jeśli są to węzły cRadioUnChecked lub cRadioChecked) i na koniec przełącza Node na cRadioChecked.

Zauważ, że wszystkie zaznaczone przyciski opcji są ignorowane. Oczywiście dzieje się tak, ponieważ już zaznaczony przycisk opcji zostałby przełączony na niezaznaczony, pozostawiając węzły w nieokreślonym stanie. Prawie nie chciałbyś przez większość czasu.

Oto jak uczynić kod jeszcze bardziej profesjonalnym: w zdarzeniu OnClick w widoku drzewa napisz następujący kod, aby przełączać tylko pola wyboru, jeśli kliknięto obraz stanu (stałe cFlatUnCheck, cFlatChecked itp. są zdefiniowane gdzie indziej jako indeksy do StateImages lista zdjęć):

procedura TForm1.TreeView1Click (Sender: TObject);
var
P: TPoint;
zaczynać
GetCursorPos (P);
P: = TreeView1.ScreenToClient (P);
gdyby (htOnStateIcon w
TreeView1.GetHitTestInfoAt (P.X, P.Y)) następnie
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
koniec; (* TreeView1Click *)

Kod pobiera bieżącą pozycję myszy, konwertuje do współrzędnych widoku drzewa i sprawdza, czy kliknięto StateIcon, wywołując funkcję GetHitTestInfoAt. Jeśli tak, wywoływana jest procedura przełączania.

Przeważnie można oczekiwać, że spacja przełączy pola wyboru lub przyciski opcji, więc oto jak napisać zdarzenie TreeView OnKeyDown przy użyciu tego standardu:

procedura TForm1.TreeView1KeyDown (
Nadawca: TObject;
var Klucz: Word;
Shift: TShiftState);
beginif (Klucz = VK_SPACE) i
Przypisany (TreeView1.Selected) następnie
ToggleTreeViewCheckBoxes (
TreeView1.Selected,
cFlatUnCheck,
cFlatChecked,
cFlatRadioUnCheck,
cFlatRadioChecked);
koniec; (* TreeView1KeyDown *)

Na koniec oto, jak mogą wyglądać zdarzenia OnShow i OnChanging w formularzu Treeview, jeśli chcesz zapobiec zwijaniu się węzłów widoku drzewa:

procedura TForm1.FormCreate (Sender: TObject);
zaczynać
TreeView1.FullExpand;
koniec; (* FormCreate *)
procedura TForm1.TreeView1Collapsing (
Nadawca: TObject;
Węzeł: TTreeNode;
var AllowCollapse: Boolean);
zaczynać
AllowCollapse: = false;
koniec; (* TreeView1Collapsing *)

Na koniec, aby sprawdzić, czy węzeł jest zaznaczony, wystarczy wykonać następujące porównanie (na przykład w module obsługi zdarzeń OnClick przycisku):

procedura TForm1.Button1Click (Sender: TObject);
var
BoolResult: boolean;
tn: TTreeNode;
beginif Przypisany (TreeView1.Selected) wtedy zacznij
tn: = TreeView1.Selected;
BoolResult: = tn. StateIndex w
[cFlatChecked, cFlatRadioChecked];
Nota 1. tekst: = tn. Tekst +
#13#10 +
„Wybrane:” +
BoolToStr (BoolResult, True);
koniec;
koniec; (* Button1Click *)

Chociaż tego rodzaju kodowania nie można uznać za kluczowy dla misji, może on nadać aplikacjom bardziej profesjonalny i gładszy wygląd. Ponadto dzięki rozsądnemu użyciu pól wyboru i przycisków opcji mogą ułatwić korzystanie z aplikacji. Z pewnością będą dobrze wyglądać!

To zdjęcie zostało pobrane z aplikacji testowej przy użyciu kodu opisanego w tym artykule. Jak widać, możesz swobodnie mieszać węzły posiadające pola wyboru lub przyciski opcji z tymi, które ich nie mają, chociaż nie należy mieszać „pustych” węzłów z „pole wyboru„węzły (spójrz na przyciski opcji na obrazie), ponieważ bardzo trudno jest zobaczyć, które węzły są powiązane.