权限树

unit uckDroitTreeView;

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, ComCtrls,CommCtrl;

{权限树}
type
  TuckDroitTreeView = class(TTreeView)
  private
    FCheckBoxReadOnly : Boolean;
    FOldState : Boolean;
    FOnCheckedChange : TTVChangedEvent;
    function IsNodeChecked(Node :TTreeNode) :Boolean;
    function CheckDroitString(const DroitStr: String): Boolean;
    procedure SetNodeChecked(Node :TTreeNode; Checked :Boolean);
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
    procedure SetChildren(Node: TTreeNode; Checked: Boolean);
    procedure SetParant(Node: TTreeNode; Checked: Boolean);
    function GetDroitString: String;
    procedure SetDroitString(DroitStr: String);
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  public
    constructor Create(AOwner: TComponent); override;
    function Checked(Node: TTreeNode): Boolean;
    procedure SetChecked(Node: TTreeNode; Checked: Boolean);
  published
    property CheckBoxReadOnly: Boolean read FCheckBoxReadOnly write FCheckBoxReadOnly;
    property OnCheckedChange: TTVChangedEvent read FOnCheckedChange write FOnCheckedChange;
    property DroitString: String read GetDroitString write SetDroitString;
  end;

procedure Register;

implementation



procedure Register;
begin
  RegisterComponents('Samples', [TuckDroitTreeView]);
end;


//-----------------------------------------------------------------------------------
function TuckDroitTreeView.CheckDroitString(const DroitStr: String): Boolean;
var
  I : Integer;
begin
  Result := False;
  if DroitStr = '' then  Exit;
  for I :=1 to Length(DroitStr) do begin
    if not( (DroitStr[I] = '0') or (DroitStr[I] = '1') ) then begin
      Result := False;
      Exit;
    end;
  end;
  Result := True;
end;

//-----------------------------------------------------------------------------------
function TuckDroitTreeView.Checked(Node: TTreeNode): Boolean;
begin
  Result := IsNodeChecked(Node);
end;

//-----------------------------------------------------------------------------------
constructor TuckDroitTreeView.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCheckBoxReadOnly := False;
end;

//-----------------------------------------------------------------------------------
procedure TuckDroitTreeView.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.Style:=Params.Style or TVS_CHECKBOXES;
end;

//-----------------------------------------------------------------------------------
function TuckDroitTreeView.GetDroitString: String;        
var
  I : Integer;
begin
  Result := '';
  if Self.Items.Count < 1 then  Exit;
  for I :=0 to Self.Items.Count - 1 do begin
    if Self.Checked(Self.Items[I]) then  Result := Result + '1'
    else  Result := Result + '0';
  end;
end;

//-----------------------------------------------------------------------------------
procedure TuckDroitTreeView.SetDroitString(DroitStr: String);
var
  I, Len : Integer;
begin
  if Self.Items.Count < 1 then  Exit;
  if not CheckDroitString(DroitStr) then  Exit;
  for I :=0 to Self.Items.Count - 1 do
    Self.SetChecked(Self.Items[I], False);
  Len := Length(DroitStr);  
  for I :=0 to Self.Items.Count - 1 do begin
    if I + 1 <= Len then begin
      Self.SetChecked(Self.Items[I], (DroitStr[I+1]='1'));
    end;
  end;
end;

//-----------------------------------------------------------------------------------
function TuckDroitTreeView.IsNodeChecked(Node: TTreeNode): Boolean;
const
  TVIS_CHECKED = $2000;
var
  TvItem :TTVItem;
begin
  TvItem.Mask  := TVIF_STATE;
  TvItem.hItem := Node.ItemId;
  TreeView_GetItem(Node.TreeView.Handle, TvItem);
  Result := (TvItem.State and TVIS_CHECKED) = TVIS_CHECKED;
end;

//-----------------------------------------------------------------------------------
procedure TuckDroitTreeView.SetChecked(Node: TTreeNode; Checked: Boolean);
begin
  if Node <> nil then
    SetNodeChecked(Node, Checked);
end;

//-----------------------------------------------------------------------------------
procedure TuckDroitTreeView.SetChildren(Node: TTreeNode; Checked: Boolean);
var
  TmpNode : TTreeNode;
begin
  TmpNode := Node.GetFirstChild;
  while TmpNode <> nil do begin
    Self.SetChecked(TmpNode, Checked);
    if TmpNode.HasChildren then  SetChildren(TmpNode, Checked);
    TmpNode := Node.GetNextChild(TmpNode);
  end;
end;

//-----------------------------------------------------------------------------------
procedure TuckDroitTreeView.SetNodeChecked(Node: TTreeNode; Checked: Boolean);
const
  TVIS_CHECKED = $2000;
var
  TvItem :TTVItem;
begin
  FillChar(TvItem, SizeOf(TvItem), 0);
  with TvItem do begin
    hItem     := Node.ItemId;
    Mask      := TVIF_STATE;
    StateMask := TVIS_STATEIMAGEMASK;
    if Checked then
      TvItem.State :=TVIS_CHECKED
    else
      TvItem.State :=TVIS_CHECKED shr 1;
    TreeView_SetItem(Node.TreeView.Handle, TvItem);
  end;
end;

//-----------------------------------------------------------------------------------
procedure TuckDroitTreeView.SetParant(Node: TTreeNode; Checked: Boolean);
var
  TmpNode : TTreeNode;
begin        
  TmpNode := Node.Parent;
  while TmpNode <> nil do begin
    Self.SetChecked(TmpNode, Checked);
    TmpNode := TmpNode.Parent;
  end;
end;

//-----------------------------------------------------------------------------------
procedure TuckDroitTreeView.WMLButtonDown(var Message: TWMLButtonDown);
var
  TmpNode : TTreeNode;
  OldState, bChecked : Boolean;
begin
  TmpNode := Self.GetNodeAt(Message.XPos, Message.YPos);
  if TmpNode <> nil then  OldState := IsNodeChecked(TmpNode);

  inherited;

  if TmpNode <> nil then begin
    if FCheckBoxReadOnly then
      SetNodeChecked(TmpNode, OldState);
    FOldState := IsNodeChecked(TmpNode);
    //----
    if TmpNode.HasChildren then
      SetChildren(TmpNode, Self.Checked(TmpNode));
    if TmpNode.Parent <> nil then begin
      bChecked := Self.Checked(TmpNode);
      if bChecked then  SetParant(TmpNode, bChecked);
    end;
    //----
    if Assigned(OnCheckedChange) then
      if FOldState <> OldState then
        OnCheckedChange(Self, TmpNode);
  end;
end;

end.

 
原文地址:https://www.cnblogs.com/hnxxcxg/p/2941047.html