Hola amigos.
Ya solucioné el problema. Dejaré el código completo por si alguien mas quisiera hacer los mismo.
Explico el objetivo:
Llenar un treeview con todas los items de un tmainmenu. seleccionar en el treeview, el item que deberá mostrarse en las opciones del menu principal del sistema. almacenar dicha configuracion con una clave del tipo de menu creado, asi como todas los items del tmainmenu, almacenando en un campo de control, la clave que permitirá ser comparada cuando el usuario se conecte al sistema y se activen solamente aquellas opciones que coincidan con el campo de control.
Para lograr lo anterior, cree una tabla con la siguiente estructura:
Código SQL
[-]CREATE TABLE SEG_MENU_OPC_CONFIG (
MENU_TIPO_ID NUMERIC(2,0) NOT NULL,
NODO_PADRE INTEGER NOT NULL,
NIVEL INTEGER,
NODO INTEGER NOT NULL,
OPC_VISIBLE VARCHAR(5),
OPC_DESCRIPCION VARCHAR(60),
OPC_TAG INTEGER,
OPC_ABSOLUTE_INDEX INTEGER
);
MENU_TIPO_ID.- Clave del tipo de menú con el cual se guardará la configuración de las opciones del menu(EJ. MENU DE ADMINISTRADOR, MENU DE CAPTURISTA, etc).
NODO_PADRE.- Almacenará el nodo padre del TreeView.
NIVEL.- Almacenaré el nivel que guarda el item en el treeview
NODO.- Numero de nodo del item.
OPC_VISIBLE.- Campo de control que servirá para identificar si se mostrará o no la opción en el menú principal.(Ej. 0=visible,1=no visible, T=True, F=False ,etc). ya aqui lo pueden hacer como gusten.
OPC_DESCRIPCION.- Nombre o descripción del item que ostenta en el TMainMenu
OPC_TAG.- El TAG que guarda el item en el TMainMenu (A todos los item les puse un numero el cual servirá luego para comparar y ver si se mostrara o no la opción)
OPC_ABSOLUTE_INDEX.- El numero que tiene almacenado en la propiedad de TreeView.AbsoluteIndex.
Y este es el código completo con el cual se cumplió con el objetivo: (Por cierto aclaro que el form tiene un PageControl, en donde en la primer TabSheet es la pantalla para crear/guardar la descripción del tipo de menu que voy a configurar)
Código Delphi
[-]unit SegMenuNiv;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, Buttons, ToolWin, ExtCtrls, CommCtrl, StdCtrls, Mask, DB,
IBCustomDataSet, DBCtrls, sSkinProvider, IBQuery, Menus, IBTable, StrUtils,
ImgList, Grids, DBGrids;
type
TfrmSegMenuNiv = class(TForm)
Panel2: TPanel;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
Panel1: TPanel;
Panel4: TPanel;
Label1: TLabel;
mskIDMenu: TMaskEdit;
GroupBox1: TGroupBox;
dsTipoMenu: TIBDataSet;
dSoTipoMenu: TDataSource;
dsTipoMenuMENU_TIPO_ID: TSmallintField;
dsTipoMenuMENU_TIPO_DESCRIP: TIBStringField;
dsTipoMenuMENU_HABILITAR: TIBStringField;
DBEdit1: TDBEdit;
Panel3: TPanel;
btnGrabar: TBitBtn;
btnCancelar: TBitBtn;
sSkinProvider1: TsSkinProvider;
Panel5: TPanel;
Panel7: TPanel;
Panel8: TPanel;
Label2: TLabel;
cbxTipoMenu: TDBLookupComboBox;
GroupBox2: TGroupBox;
TreeView1: TTreeView;
Panel6: TPanel;
btnGrabarCFG: TBitBtn;
btnCancelarCFG: TBitBtn;
GroupBox3: TGroupBox;
DBCheckBox1: TDBCheckBox;
btnEliminar: TBitBtn;
qryTipoMenu: TIBQuery;
dSoTipoMenuCFG: TDataSource;
qryTipoMenuMENU_TIPO_ID: TSmallintField;
qryTipoMenuMENU_TIPO_DESCRIP: TIBStringField;
qryTipoMenuMENU_HABILITAR: TIBStringField;
dsMenuOpCFG: TIBDataSet;
dSoMenuOpCFG: TDataSource;
qryMenu: TIBQuery;
btnEliminarCFG: TBitBtn;
qryMenuNODO_PADRE: TIntegerField;
qryMenuNODO: TIntegerField;
qryMenuOPC_DESCRIPCION: TIBStringField;
qryMenuOPC_TAG: TIntegerField;
tblOpcMenu: TIBTable;
dsMenuOpCFGMENU_TIPO_ID: TSmallintField;
dsMenuOpCFGNODO: TIntegerField;
dsMenuOpCFGNODO_PADRE: TIntegerField;
dsMenuOpCFGOPC_VISIBLE: TIBStringField;
PopupMenu1: TPopupMenu;
Activar1: TMenuItem;
Desactivar1: TMenuItem;
ImageList1: TImageList;
DataSource1: TDataSource;
qryActVisible: TIBQuery;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Panel1Enter(Sender: TObject);
procedure Panel1Exit(Sender: TObject);
procedure btnGrabarClick(Sender: TObject);
procedure btnEliminarClick(Sender: TObject);
procedure btnCancelarClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Panel7Enter(Sender: TObject);
procedure cbxTipoMenuCloseUp(Sender: TObject);
procedure TreeView1Click(Sender: TObject);
procedure btnGrabarCFGClick(Sender: TObject);
procedure Activar1Click(Sender: TObject);
procedure Desactivar1Click(Sender: TObject);
procedure Visible();
private
procedure ToggleTreeViewCheckBoxes(Node:TTreeNode; cUnChecked, cChecked: Integer);
public
i, iParent,nivel,nodo_padre,nodo, nodo_ant:integer;
tv, tvParent, tv_hijo,tv_nieto:TTreeNode;
bitMap:TBitmap;
end;
var
frmSegMenuNiv: TfrmSegMenuNiv;
const cStateUnCheck = 1;
cStateChecked = 2;
implementation
uses ModuloBD,MenuPrincipal;
{$R *.dfm}
procedure TfrmSegMenuNiv.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Action:=caFree;
end;
procedure TfrmSegMenuNiv.Panel1Enter(Sender: TObject);
begin
dMod.trscMMS.Active:=False;
dMod.trscMMS.StartTransaction;
mskIDMenu.Text:='';
btnGrabar.Enabled:=False;
btnEliminar.Enabled:=False;
btnCancelar.Enabled:=False;
end;
procedure TfrmSegMenuNiv.Panel1Exit(Sender: TObject);
begin
dsTipoMenu.Close;
dsTipoMenu.ParamByName('menu_id').AsString:=mskIDMenu.Text;
dsTipoMenu.Open;
if dsTipoMenu.IsEmpty then
begin
btnGrabar.Enabled:=True;
btnEliminar.Enabled:=False;
btnCancelar.Enabled:=True;
dsTipoMenu.Append;
dsTipoMenu.FieldByName('menu_tipo_id').AsString:=mskIDMenu.Text;
end Else
begin
btnGrabar.Enabled:=True;
btnEliminar.Enabled:=True;
btnCancelar.Enabled:=True;
dsTipoMenu.Edit;
end;
end;
procedure TfrmSegMenuNiv.btnGrabarClick(Sender: TObject);
begin
try
dsTipoMenu.Post;
dsTipoMenu.ApplyUpdates;
dMod.trscMMS.Commit;
Application.MessageBox('Datos grabados correctamente','Aviso',mb_ok+mb_IconInformation);
except
on E: Exception do
begin
Application.MessageBox('Los registros no pueden ser grabados, consulte al administrador del sistema','Error', mb_ok+mb_IconError);
ShowMessage(E.Message);
dMod.trscMMS.Rollback;
end;
end;
mskIDMenu.SetFocus;
end;
procedure TfrmSegMenuNiv.btnEliminarClick(Sender: TObject);
begin
try
dsTipoMenu.Delete;
dsTipoMenu.ApplyUpdates;
dMod.trscMMS.Commit;
Application.MessageBox('El Registro ha sido eliminado de forma correcta','Aviso',mb_ok+mb_IconInformation);
except
on E: Exception do
begin
Application.MessageBox('El Registro no se puede eliminar, consulte al administrador del sistema','Error', mb_ok+mb_IconError);
ShowMessage(E.Message);
dMod.trscMMS.Rollback;
end;
end;
mskIDMenu.SetFocus;
end;
procedure TfrmSegMenuNiv.btnCancelarClick(Sender: TObject);
begin
mskIDMenu.SetFocus;
end;
procedure TfrmSegMenuNiv.FormShow(Sender: TObject);
begin
PageControl1.ActivePageIndex:=0;
end;
procedure TfrmSegMenuNiv.Panel7Enter(Sender: TObject);
begin
dMod.trscMMS.Active:=False;
dMod.trscMMS.StartTransaction;
btnGrabarCFG.Tag:=0;
TreeView1.Items.Clear;
btnGrabarCFG.Enabled:=False;
btnEliminarCFG.Enabled:=False;
btnCancelarCFG.Enabled:=False;
dsMenuOpCFG.Close;
qryMenu.Close;
qryTipoMenu.Close;
qryTipoMenu.Open;
qryTipoMenu.FetchAll;
tblOpcMenu.Close;
end;
procedure TfrmSegMenuNiv.cbxTipoMenuCloseUp(Sender: TObject);
procedure VerificaMenu(Menu: TMenuItem; Nod: TTreeNode);
Var
i: Integer;
Nodo: TTreeNode;
Begin
for i:= 0 To (Menu.Count - 1) Do Begin
If Not(Menu.Parent Is TMenuItem) then begin
Nodo:= TreeView1.Items.Add(Nil,Menu.Items[i].Caption+'-'+IntToStr(Menu.Items[i].Tag) );
Nodo.StateIndex:=0;
End
Else begin
Nodo:= TreeView1.Items.AddChild(Nod,Menu.Items[i].Caption+'-'+IntToStr(Menu.Items[i].Tag) );
Nodo.StateIndex:=0;
end;
If Menu.Items[i].Count > 0 Then begin
VerificaMenu(Menu.Items[i], Nodo);
end;
End;
End;
begin
TreeView1.Items.Clear;
tblOpcMenu.Filter:='MENU_TIPO_ID='+IntToStr(cbxTipoMenu.KeyValue);
tblOpcMenu.Filtered:=True;
tblOpcMenu.Open;
if tblOpcMenu.IsEmpty then
begin
btnGrabarCFG.Caption:='Grabar';
btnGrabarCFG.Tag:=0;
btnGrabarCFG.Enabled:=True;
btnEliminarCFG.Enabled:=False;
btnCancelarCFG.Enabled:=False;
VerificaMenu(frmMenu.MainMenu1.Items, Nil);
TreeView1.Items.Item[0].Selected:=True;
end Else
begin
btnGrabarCFG.Tag:=1;
btnGrabarCFG.Caption:='Actualizar';
btnGrabarCFG.Enabled:=True;
btnEliminarCFG.Enabled:=True;
btnCancelarCFG.Enabled:=True;
tblOpcMenu.First;
while not (tblOpcMenu.Eof) do
begin
if tblOpcMenu.FieldValues['NIVEL']=0 then
begin
tv:= TreeView1.Items.Add(nil, tblOpcMenu.FieldValues['OPC_DESCRIPCION']);
end;
if tblOpcMenu.FieldValues['NIVEL']=1 then
begin
tv_hijo:= TreeView1.Items.AddChild(tv, tblOpcMenu.FieldValues['OPC_DESCRIPCION']);
end;
if tblOpcMenu.FieldValues['NIVEL']=2 then
begin
TreeView1.Items.AddChild(tv_hijo,tblOpcMenu.FieldValues['OPC_DESCRIPCION']);
end;
tblOpcMenu.Next;
end;
Visible();
TreeView1.Items.Item[0].Selected:=True;
end;
end;
procedure TfrmSegMenuNiv.Visible;
var
i : integer;
begin
tblOpcMenu.First;
While not(tblOpcMenu.Eof) do
begin
for i:=0 to TreeView1.Items.Count - 1 do
begin
if tblOpcMenu.FieldValues['opc_descripcion']=TreeView1.Items[i].Text then
TreeView1.Items[i].StateIndex:=tblOpcMenu.FieldValues['OPC_VISIBLE'];
tblOpcMenu.Next;
end;
end;
end;
procedure TfrmSegMenuNiv.TreeView1Click(Sender: TObject);
var
P: TPoint;
begin
if TreeView1.Selected.StateIndex=0 then
begin
if TreeView1.Selected.Count>0 then
begin
TreeView1.Selected.Expanded:=False;
Application.MessageBox('Para poder expandir y ver las sub-opciones, '+CHR(13)+
'deberá primeramente ACTIVAR la opción dando click '+CHR(13)+
'derecho y seleccionar "Activar"','Aviso',mb_ok+mb_IconWarning);
end;
end else
begin
TreeView1.Selected.Expanded:=True;
end;
end;
procedure TfrmSegMenuNiv.ToggleTreeViewCheckBoxes(Node: TTreeNode; cUnChecked,
cChecked: Integer);
begin
end;
procedure TfrmSegMenuNiv.btnGrabarCFGClick(Sender: TObject);
var
i, nNodoPadre : integer;
begin
tblOpcMenu.Open; if btnGrabarCFG.Tag=0 then
begin
for i := 0 to (TreeView1.Items.Count -1) do begin
tv := TreeView1.Items[i]; tblOpcMenu.Append;
if ( Assigned(tv.Parent) ) then
nNodoPadre:=tv.Parent.Index
else
nNodoPadre:=-1;
tblOpcMenu.FieldByName('MENU_TIPO_ID').AsInteger:=cbxTipoMenu.KeyValue;
tblOpcMenu.FieldByName('NODO_PADRE').AsInteger := nNodoPadre;
tblOpcMenu.FieldByName('NIVEL').AsInteger:=tv.Level;
tblOpcMenu.FieldByName('NODO').AsInteger := tv.Index;
tblOpcMenu.FieldByName('OPC_DESCRIPCION').AsString := tv.Text;
tblOpcMenu.FieldByName('OPC_TAG').AsString :=COPY( tv.Text,AnsiPOS('-',tv.Text)+1,LENGTH(tv.Text) );
tblOpcMenu.FieldByName('OPC_ABSOLUTE_INDEX').AsInteger:=tv.AbsoluteIndex;
tblOpcMenu.FieldByName('OPC_VISIBLE').AsInteger:= tv.StateIndex;
tblOpcMenu.Post;
end;
tblOpcMenu.ApplyUpdates;
tblOpcMenu.Close;
end Else
begin
for i:=0 to TreeView1.Items.Count - 1 do
begin
qryActVisible.Close;
qryActVisible.ParamByName('visible').AsInteger:=TreeView1.Items[i].StateIndex;
qryActVisible.ParamByName('menu').AsInteger:=cbxTipoMenu.KeyValue;
qryActVisible.ParamByName('absolute_index').AsInteger:=TreeView1.Items[i].AbsoluteIndex;
qryActVisible.ExecSQL;
end
end;
dMod.trscMMS.Commit;
Application.MessageBox('Configuración de Menú grabado exitosamente','Aviso',mb_ok+mb_IconInformation);
Panel7Enter(Sender);
end;
procedure TfrmSegMenuNiv.Activar1Click(Sender: TObject);
begin
TreeView1.Selected.StateIndex:=1;
TreeView1.Selected.Expanded:=True;
end;
procedure TfrmSegMenuNiv.Desactivar1Click(Sender: TObject);
begin
TreeView1.Selected.StateIndex:=0;
TreeView1.Selected.Expanded:=False;
end;
end.
Tengo pendiente el proceso de comparación para que muestre o no las opciones del menú, cuando el usuario se conecte. En cuanto lo tengo lo publicaré para tenerlo todo completo.
Sé que puede quedar mejor, pero considero que mis conocimientos no son tan avanzados como algunos o la gran mayoría de los que integran este club, asi que dejo en ustedes -en la medida de sus tiempo y si asi lo desean- lo puedan mejorar, enriquecerlo y dejarlo disponible para los demás.
(Lo escribí en mayúsculas solo para resaltar el mensaje, no significa q este gritando...jejejeje)
Saludos.