Mensaje    Asunto: TreeView para perfiles de usuario Responder citando

Hola !!!

Hace algún tiempo me dediqué a buscar algún TreeView con Checkbox y que funcionara de manera recursiva, encontré en un lugar japonés una parte del código y solamente le agregé la recursividad, en pocas palabras, aquí les pongo el código de este componente que compuse, espero les sea util.

Si le agregan actualizaciones, bienvenidas !!!

Saludos !!!

Código del TPerfiles.cpp
Código:

//Edwin José Hernández Pinto
//Mérida, Yucatán, México
//---------------------------------------------------------------------------
 
#include <vcl.h>

#pragma hdrstop

#include "TPerfiles.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//     

static inline void ValidCtrCheck(TPerfiles *)
{
        new TPerfiles(NULL);
}
//---------------------------------------------------------------------------
__fastcall TPerfiles::TPerfiles(TComponent* Owner)
        : TTreeView(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TPerfiles::CreateParams(TCreateParams &Params){
        TTreeView::CreateParams(Params);
        Params.Style |= TVS_CHECKBOXES;
}

void __fastcall TPerfiles::SetNodeState(TTreeNode *ANode,bool IsSetToChecked)
{
  TVITEM tvItem;

  tvItem.mask = TVIF_HANDLE | TVIF_STATE;
  tvItem.hItem = ANode->ItemId;
  tvItem.stateMask = TVIS_STATEIMAGEMASK;
  tvItem.state = INDEXTOSTATEIMAGEMASK(IsSetToChecked?2:1);
  TreeView_SetItem(ANode->TreeView->Handle, &tvItem);
}

bool __fastcall TPerfiles::GetNodeState(TTreeNode *ANode)
{
  bool resp(false);
  TVITEM tvItem;

  tvItem.mask = TVIF_HANDLE | TVIF_STATE;
  tvItem.hItem = ANode->ItemId;
  tvItem.stateMask = TVIS_STATEIMAGEMASK;
  TreeView_GetItem(ANode->TreeView->Handle, &tvItem);
  resp = ((bool)((tvItem.state >> 12) -1 ));
  return resp;
}

void __fastcall TPerfiles::MouseMove(Classes::TShiftState Shift, int X, int Y)
{
 ClickNode = this->GetNodeAt(X,Y);

 if ( ClickNode != NULL )
  UltimoEstado = GetNodeState(ClickNode);

 if ( FOnMouseMove )
  FOnMouseMove(this,Shift,X,Y);
}

void __fastcall TPerfiles::MouseUp(TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
 TTreeNode* Nodo;
 THitTests Elemento;
 
 if ( OnCambioNodo )
 {
   Nodo     = GetNodeAt(X,Y);
   Elemento = GetHitTestInfoAt(X,Y);

   if ( Nodo && Elemento.Contains(htOnStateIcon) )
     OnCambioNodo(Nodo,GetNodeState(Nodo));
 }
   
 if ( FOnMouseUp )
  FOnMouseUp(this,Button,Shift,X,Y);
}

void __fastcall TPerfiles::MouseDown(TMouseButton Button,
                        Classes::TShiftState Shift, int X, int Y)
{
 bool EstadoActual;
 if (ClickNode!=NULL)
 {
  if ( FRecursivo )
  {
     EstadoActual = GetNodeState(ClickNode);

     if ( EstadoActual != UltimoEstado )
     {
       if ( EstadoActual )
        HabilitaNodos(ClickNode);
       else
        DeshabilitaNodos(ClickNode);
     }
  }
 }
}

void __fastcall TPerfiles::DeshabilitaArriba(TTreeNode* Nodo)
{
 TTreeNode* Noditos;

 Noditos = Nodo->Parent;
 if ( Noditos )
 {
  bool Estan(false);

  for (int i=0;i<Noditos->Count && !Estan;i++)
  {
   if ( GetNodeState(Noditos->Item[i]) )
    Estan = true;
  }

  if ( !Estan )
  {
   SetNodeState(Noditos,false);
   ChecaPadre(Noditos);
  }
 }
}

void __fastcall TPerfiles::ChecaPadre(TTreeNode* Nodo)
{
  bool Estan(false);
  TTreeNode* Noditos;

  if ( Nodo )
  {
    Noditos = Nodo->Parent;
    if ( Noditos )
    {
      for (int i=0;i<Noditos->Count && !Estan;i++)
      {
       if ( GetNodeState(Noditos->Item[i]) )
        Estan = true;
      }

      if ( !Estan )
      {
       SetNodeState(Noditos,false);
       ChecaPadre(Noditos);
      }
    }
  } 
}

void __fastcall TPerfiles::DeshabilitaNodos(TTreeNode* Nodo)
{
 DeshabilitaArriba(Nodo);
 HabilitaAbajo(Nodo,false);
}

void __fastcall TPerfiles::HabilitaNodos(TTreeNode* Nodo)
{
 HabilitaArriba(Nodo);
 HabilitaAbajo(Nodo,true);
}

void __fastcall TPerfiles::HabilitaAbajo(TTreeNode* Nodo,bool Estado)
{
 TTreeNode* Nodos;

 for (int i=0;i<Nodo->Count;i++)
 {
  SetNodeState(Nodo->Item[i],Estado);
  AsignaHijos(Nodo->Item[i],Estado);
 }
}

void __fastcall TPerfiles::AsignaHijos(TTreeNode* Nodo,bool Estado)
{
 TTreeNode* Nodos;

 for (int i=0;i<Nodo->Count;i++)
 {
  SetNodeState(Nodo->Item[i],Estado);
  AsignaHijos(Nodo->Item[i],Estado);
 }
}

void __fastcall TPerfiles::HabilitaArriba(TTreeNode* Nodo)
{
 TTreeNode* Nodito;

 Nodito = Nodo->Parent;
 while ( Nodito )
 {
  SetNodeState(Nodito,true);
  Nodito = Nodito->Parent;
 }
}

namespace Tperfiles
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass classes[1] = {__classid(TPerfiles)};
                 RegisterComponents("General", classes, 0);
        }
}
//---------------------------------------------------------------------------
 


Código del TPerfiles.h


Código:


 //---------------------------------------------------------------------------

#ifndef TPerfilesH
#define TPerfilesH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <ComCtrls.hpp>
#include <Controls.hpp>
//---------------------------------------------------------------------------

typedef void __fastcall (__closure *TMouseMove)(System::TObject* Sender, Classes::TShiftState Shift, int X,int Y);
typedef void __fastcall (__closure *TMouseUp)(System::TObject* Sender,TMouseButton Button, Classes::TShiftState Shift, int X,int Y);
typedef void __fastcall (__closure *TCambioNodo)(TTreeNode* Nodo,bool NuevoEstado);

class PACKAGE TPerfiles : public TTreeView
{
private:
        TTreeNode* ClickNode;
        TMouseMove  FOnMouseMove;
        TMouseUp  FOnMouseUp;
        TCambioNodo FOnCambioNodo;
        bool       FRecursivo;
        bool       UltimoEstado;
        void __fastcall HabilitaNodos(TTreeNode* Nodo);
        void __fastcall DeshabilitaNodos(TTreeNode* Nodo);
        void __fastcall HabilitaAbajo(TTreeNode* Nodo,bool Estado);
        void __fastcall HabilitaArriba(TTreeNode* Nodo);
        void __fastcall AsignaHijos(TTreeNode*,bool);
        void __fastcall ChecaPadre(TTreeNode* Nodo);
        void __fastcall DeshabilitaArriba(TTreeNode* Nodo);
protected:
        virtual void __fastcall CreateParams(TCreateParams &Params);
        DYNAMIC void __fastcall MouseMove(Classes::TShiftState Shift, int X, int Y);
        DYNAMIC void __fastcall MouseDown(TMouseButton Button,Classes::TShiftState Shift, int X, int Y);
        DYNAMIC void __fastcall MouseUp(TMouseButton Button, Classes::TShiftState Shift, int X, int Y);
public:
        __fastcall TPerfiles(TComponent* Owner);
        bool __fastcall GetNodeState(TTreeNode *ANode);
        void __fastcall SetNodeState(TTreeNode *ANode,bool IsSetToChecked);
__published:
        __property bool       Recursivo   = {read=FRecursivo, write=FRecursivo };
        __property TMouseMove OnMouseMove = {read=FOnMouseMove, write=FOnMouseMove};
        __property TMouseUp   OnMouseUp   = {read=FOnMouseUp, write=FOnMouseUp};
        __property TCambioNodo OnCambioNodo = {read=FOnCambioNodo, write=FOnCambioNodo};

};
//---------------------------------------------------------------------------
#endif



_________________
Si puedo ayudarles en algo, no duden en consultarme !!!