Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 08.04.2014, 17:45
kasimka kasimka вне форума
Прохожий
 
Регистрация: 08.04.2014
Адрес: Брест
Сообщения: 7
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию TreeView и CheckBox

Есть такой класс:
Код:
TCustomTreeView = class(TTreeView)
 private
   FCheckBox: Boolean;
   FAutoCheck: Boolean;
   procedure SetCheckBox(const Value: Boolean);
 public
   function GetChecked(Node: TTreeNode): Boolean;
   procedure SetChecked(Node: TTreeNode; Checked: Boolean);
 published
   property CheckBox: Boolean read FCheckBox write SetCheckBox default False;
   property AutoCheck: Boolean read FAutoCheck write FAutoCheck default False;
 end;

Методы:

const
 TVIS_CHECKED = $2000;

function TCustomTreeView.GetChecked(Node: TTreeNode): Boolean;
var
 Item :TTVItem;
begin
 Item.Mask  := TVIF_STATE;
 Item.hItem := Node.ItemId;
 TreeView_GetItem(Node.TreeView.Handle, Item);
 Result := (Item.State and TVIS_CHECKED) = TVIS_CHECKED;
end;

procedure TCustomTreeView.SetCheckBox(const Value: Boolean);
var
 FStyle: Integer;
begin
 FCheckBox := Value;
 FStyle := GetWindowLong(Handle, GWL_STYLE);
 if FCheckBox then
   FStyle := FStyle or TVS_CHECKBOXES
 else
   if (FStyle and TVS_CHECKBOXES) = TVS_CHECKBOXES then
     FStyle := FStyle and not TVS_CHECKBOXES;
 SetWindowLong(Handle, GWL_STYLE, FStyle);
 Repaint;
end;

procedure TCustomTreeView.SetChecked(Node: TTreeNode; Checked: Boolean);
var
 Item :TTVItem;
begin
 FillChar(Item, SizeOf(TTVItem), 0);
 with Item do
 begin
   hItem     := Node.ItemId;
   Mask      := TVIF_STATE;
   StateMask := TVIS_STATEIMAGEMASK;
   if Checked then
     Item.State :=TVIS_CHECKED
   else
     Item.State :=TVIS_CHECKED shr 1;
   TreeView_SetItem(Node.TreeView.Handle, Item);
 end;
end;

Как сделать так, чтобы при AutoCheck=True галочки выставлялись во всех дочерних чекбоксах?

Последний раз редактировалось kasimka, 09.04.2014 в 14:55.
Ответить с цитированием
  #2  
Старый 09.04.2014, 02:03
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

Поскольку до чекбокса добраться стандартными средствами не удалось, придётся немного извратиться в рантайме и для начала, при инициализации компонента нужно добавить строчку
Код:
...
CustomTreeView.OnMouseDown:= CTVMouseDown;
...
ну и сама процедура жима мышки
Код:
 procedure TMainForm.CTVMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
 ctv:     TCustomTreeView absolute Sender;
 Node:    TTreeNode;
 flg:     boolean;
begin
 if ctv.AutoCheck then
  begin
   Node:= ctv.GetNodeAt(X, Y);
   if (Node <> nil) and
      (Node.Parent = nil) and // Если Parent = nil то это корневой элемент
      (ctv.GetHitTestInfoAt(X, Y) = [htOnItem, htOnStateIcon]) then
    begin
     flg:=  ctv.GetChecked(Node);
     Node:= Node.getFirstChild;
     while Assigned(Node) do
      begin
       ctv.SetChecked(Node, flg);
       Node:= Node.GetNextChild(Node);
      end;
    end;
  end;
end;
конечно, работает немного не так как должно быть (повторюсь, не удалось достучаться до галки), но очень похоже


З.Ы. Достучался всё же до птисы, с помощью GetHitTestInfoAt, теперь точно похоже

Вложенность идёт на два уровня, если нужно "глубже" то тогда крутите цикл while ещё дополнительно, или вынесите его в рекурсивную внешнюю функцию

Последний раз редактировалось Alegun, 09.04.2014 в 10:02. Причина: дополнение
Ответить с цитированием
Этот пользователь сказал Спасибо Alegun за это полезное сообщение:
kasimka (09.04.2014)
  #3  
Старый 09.04.2014, 13:02
kasimka kasimka вне форума
Прохожий
 
Регистрация: 08.04.2014
Адрес: Брест
Сообщения: 7
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Спасибо огромное!

Может кому-нибудь пригодиться... Немного переписанное событие OnMouseDown и рекурсивная процедура (позволяет проставить галочки во всех дочерних нодах):

Код:
procedure TMainForm.CTVMouseDown(Sender: TObject; Button: TMouseButton; 
Shift: TShiftState; X, Y: Integer);
var
  Node: TTreeNode;
begin
  if (Sender as TCustomTreeView).AutoCheck=True then
  begin
    Node:=(Sender as TCustomTreeView).GetNodeAt(X, Y);
    if (Node <> nil) and 
((Sender as TCustomTreeView).GetHitTestInfoAt(X, Y) = [htOnItem, htOnStateIcon]) then
      CheckSubNode(Sender, Node);
  end;
end;

procedure TMainForm.CheckSubNode(Sender: TObject; Node: TTreeNode);
var
  flag: boolean;
begin
  if not Node.HasChildren then Exit;
  flag:=(Sender as TCustomTreeView).GetChecked(Node);
  Node:=Node.getFirstChild;
  while Assigned(Node) do
    begin
      (Sender as TCustomTreeView).SetChecked(Node, flag);
      CheckSubNode(Sender, Node);
      Node:=Node.GetNextChild(Node);
    end;
end;

Еще раз переписанное событие (позволяет снимать родительский чекбокс при снятии последнего дочернего и ставить родительский чекбокс при включении первого дочернего):
Код:
procedure TMainForm.CTVMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
  NodeParent, Node: TTreeNode;
begin
  if (Sender as TCustomTreeView).AutoCheck=True then
  begin
    Node:=(Sender as TCustomTreeView).GetNodeAt(X, Y);
    if (Node <> nil) and
((Sender as TCustomTreeView).GetHitTestInfoAt(X, Y) = [htOnItem, htOnStateIcon]) then
      CheckSubNode(Sender, Node);
    if Node.Parent<>nil then
      begin
        NodeParent:=Node.Parent;
        Node:=NodeParent.getFirstChild;
        while Assigned(Node) do
          begin
            if (Sender as TCustomTreeView).GetChecked(Node) then
              Checked:=True;
            Node:=NodeParent.GetNextChild(Node);
          end;
        if not Checked then
          (Sender as TCustomTreeView).SetChecked(NodeParent, false)
        else
          (Sender as TCustomTreeView).SetChecked(NodeParent, true);
      end;
  end;
end;
Рекурсивная процедура остается той же.
Таким образом, имеем полностью рабочее дерево с чекбоксами.

Последний раз редактировалось M.A.D.M.A.N., 15.04.2014 в 17:10.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 08:28.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter