Jak utworzyć TreeView posiadający Checkbox

Szczawik

Aby utworzyć bardziej "zaawansowany" komponent TreeView, posiadający kontrlki CheckBox oraz pogrubienie, należy skorzystać z poniższych informacji. Do przykładu potrzeba nam: Form1 zawierający TreeView1 (dodajmy kilka wpisów w nim), Button1, Button2.

Do Uses dodajemy:

uses CommCtrl;

Przydadzą się też stałe (nie są niestety zdefiniowane wcześniej):

const TVIS_CHECKED  = $2000;
      TVIS_UNCHECKED= $1000;

Dodajmy akcję na tworzenie okna, by na starcie dodać Checkbox do TreeView:

procedure TForm1.FormCreate(Sender: TObject);
begin
SetWindowLong(TreeView1.Handle, GWL_STYLE, GetWindowLong(TreeView1.Handle, GWL_STYLE) or TVS_CHECKBOXES);
end;

Akcja na przycisk Button1, sprawdzająca stan zaznaczenia wybranego Node w TreeView:

procedure TForm1.Button1Click(Sender: TObject);
begin
if TreeView1.Selected=nil then exit;
if IsChecked(TreeView1.Selected) then
  Button1.Caption:='Zaznaczony: TAK'
else
  Button1.Caption:='Zaznaczony: NIE';
end;

Akcja na przycisk Button2, negująca stan zaznaczenia wybranego Node w TreeView:

procedure TForm1.Button2Click(Sender: TObject);
begin
if TreeView1.Selected=nil then exit;
SetChecked(TreeView1.Selected, not IsChecked(TreeView1.Selected) );
end;

No dobrze. To teraz warto ujawnić nasze dwie podstawowe funkcje, na jakich opiera się przykład: SetChecked(..) oraz IsChecked(..):

function IsChecked(Node :TTreeNode):boolean;
var TvItem:TTVItem;
begin
TvItem.Mask := TVIF_STATE;
TvItem.hItem := Node.ItemId;
TreeView_GetItem(Node.TreeView.Handle, TvItem);
Result :=(TvItem.State and TVIS_CHECKED>0);
end;

procedure SetChecked(Node:TTreeNode; Checked:boolean);
var TvItem:TTVItem;
begin
ZeroMemory(@TvItem, SizeOf(TvItem));
TvItem.hItem := Node.ItemId;
TvItem.Mask := TVIF_STATE;
TvItem.StateMask :=TVIS_STATEIMAGEMASK;
if Checked then
  TvItem.State :=TVIS_CHECKED
else
  TvItem.State :=TVIS_UNCHECKED;
TreeView_SetItem(Node.TreeView.Handle, TvItem);
end;

Na podobnych zasadach możemy np.: pogrubiać tekst elementów, bez stosowania rysowania ręczniego elementów TreeView. Polecam wypróbować poniższą procedurę SetChecked(..) w tej postaci:

procedure SetChecked(Node:TTreeNode; Checked:boolean);
var TvItem :TTVItem;
begin
ZeroMemory(@TvItem, SizeOf(TvItem));
TvItem.hItem := Node.ItemId;
TvItem.Mask := TVIF_STATE;
TvItem.StateMask := TVIS_STATEIMAGEMASK or TVIS_BOLD;
if Checked then
  TvItem.State :=TVIS_CHECKED or TVIS_BOLD
else
  TvItem.State :=TVIS_UNCHECKED;
TreeView_SetItem(Node.TreeView.Handle, TvItem);
end;

Więcej na temat dodatkowych stałych znajdziecie w MSDN.

FAQ

2 komentarzy

Czemu mi to nie działa? Nie pokazują się żadne checkBoxy. Windows XP

hmmm

A moj jest...