MAINMENU APATIR DE UMA TABELA DO BANCO

Delphi

30/01/2009

Quero fazer um software onde o meu menu vai ser criado em tempo de execução através de uma tabela.

Na tabela vai ter os campos
NomeMenu Caption Nive1 Nivel2 Nivel3
Abaixo a tabela preenchida com alguns itens

NomeMenu Caption Nivel1 Nivel2 Nivel3
-------------------------------------------------------------------------
MnuCadastro Cadastro 1 0 0
MnuCadastroClientes Clientes 1 1 0
MnuCadastroProdutos Produtos 1 2 0
MnuLocalizar Localizar 2 0 0
MnuLocalizarClientes Clientes 2 1 0
MnuLocalizarProdutos Produtos 2 2 0
MnuRelatorio Relatorio 3 0 0
MnuRelatorioClientes Clientes 3 1 0
MnuRelatorioClientesDiario Diário 3 1 1
MnuRelatorioClientesMensal Mensal 3 1 2
MnuRelatorioProdutos Produtos 3 2 0
MnuRelatorioProdutosDiario Diário 3 2 1
MnuRelatorioProdutosMensal Mensal 3 2 2

Menu resultante

Cadastro Localizar Relatorio
Clientes Clientes Clientes--> Diário
Mensal
Produtos Produtos Produtos--> Diário
Mensal

Procedimento utilizado para criar o menu

procedure TForm.CriarMenu;
var
QryMenu:TQuery;
MenuPrincipal:TMainMenu;
ItemMenu:array of TMenuItem;
i,j:integer;
Rotina: procedure of object; // aqui começa a mudança
Begin
MenuPrincipal:=TMainMenu.Create(self); //Criar o menu
QryMenu:=TQuery.Create(self); //Criar a query
QryMenu.DatabaseName:=´sistema´; //Nome do meu alias(Em paradox)
//Selecionar todos os campos e ordenar de modo que crie um menu por vez
QryMenu.sql.Add(´select * from menus order by nivel1,nivel2,nivel3´);
QryMenu.Open;
SetLength(ItemMenu,QryMenu.RecordCount);//Define o tamanho do vetor de itens do menu
i:=0;
while not QryMenu.Eof do
begin
ItemMenu[i]:=TMenuItem.Create(self); //Criar item do menu
ItemMenu[i].Name:=QryMenu.FieldByName(´NomeMenu´).Value;
ItemMenu[i].Caption:=QryMenu.FieldByName(´Caption´).Value;

// aqui ´pega´ a procedure. note que a rotina deve estar no próprio formulário.
if QryMenu.FieldByName(´NomeMenu´).AsString <> EmptyStr then
begin
@Rotina := MethodAddress(QryMenu.FieldByName(´NomeMenu´).AsString);
// aqui verifica se a rotina existe.
if Assigned(Rotina) then
try
ItemMenu[i].OnClick:=TNotifyEvent(Rotina); //aqui atribui a rotina ao evento OnClick
except
end;
end;

if QryMenu.FieldByName(´nivel2´).Value=0 then //Se for menu
begin
MenuPrincipal.Items.Add(ItemMenu[i]); //Adiciona no principal
j:=i;
end
else
if QryMenu.FieldByName(´nivel3´).Value<>0 then //Se for item de submenu ex:Diário e mensal
ItemMenu[j+QryMenu.FieldByName(´nivel2´).AsInteger].Add(ItemMenu[i])
else //Se for comando de menu
ItemMenu[j].Add(ItemMenu[i]);
inc(i);
QryMenu.Next;
end;
end;

ATÉ AQUI BELEZA , AGORA IMPLEMENTEI NA TABELA UM NOVO CAMPO :
NIVEL4 E AI? COMO FICARIA A PROCEDURE,CONSIDERANDO QUE EXISTISSE UM 4 NIVEL DE MENU? JA TENTEI COMPLEMENTALA NA CONDIÇÃO DE EXITIR UM UM COMPO: NIVEL4 MAIS NAUM CONSIGO. PODES ME AJUDAR?


El-loeco

El-loeco

Curtidas 0

Respostas

Rudá

Rudá

30/01/2009

Cara você criou dois tópicos.


Para fazer isso vc tem que usar recursividade: http://pt.wikipedia.org/wiki/Recursividade

Vou lhe mostrar como fiz uma vez.

Criar uma tabela com +- essas configurações:

Tabela:
ID int (auto incremento)
Nome varchar
Menuint
Ordem int


como exemplo fiz esses inserts

INSERT INTO Tabela VALUES("Menu", 0, 1); // ID = 1
INSERT INTO Tabela VALUES("Metérias", 0, 2); // ID = 2
INSERT INTO Tabela VALUES("Dentro do Menu", 1, 1); // ID = 3
INSERT INTO Tabela VALUES("Dentro de Dentro do Menu", 3, 1); // ID = 4
INSERT INTO Tabela VALUES("Dentro de Dentro de Dentro do Menu", 4, 1); // ID = 5
INSERT INTO Tabela VALUES("Dento de Materias", 2, 1); // ID = 6
INSERT INTO Tabela VALUES("Dento de Dentro de Materias", 6, 1); // ID = 7


Deve aparecer assim:

Menu // ID = 1
    Dentro do Menu // ID = 3
        Dentro de Dentro do Menu // ID = 4
            Dentro de Dentro de Dentro do Menu // ID = 5
Materias // ID = 2
    Dentro de Materias // ID = 6
        Dentro de Dentro de Materias // ID = 7


Crie uma TQuery ou outro tipo e coloque esse select ( vou chamar de qryMenu)
SELECT ID, Nome
FROM Tabela
WHERE Menu= :Menu
ORDER BY Ordem ASC, Nome ASC


Procedure para adicionar.

procedure TForm1.CriarMenu(ID: Integer; Menu: TMenuItem);
var
  AddMenu: TMenuItem;
begin
  qryMenu.Close;
  qryMenu.ParamByName(´Menu´).AsInteger:= ID;
  qryMenu.Open;
  while Not qryMenu.Eof do
  begin
    AddMenu:= TMenuItem.Create(Self);
    AddMenu.Caption:= qryMenu.FieldByName(´Nome´).AsString;
    AddMenu.Name:= ´mt´ + StringReplace(AddMenu.Caption,´ ´,´´,[rfReplaceAll]) + qryMenu.FieldByName(´ID´).AsString;
    Menu.Add(AddMenu);
    CriarMenu(qryMenu.FieldByName(´ID´).AsInteger,AddMenu);
    qryMenu.Next;
  end;


Depois é só vc chamar

CriarMenu(0,MainMenu1.Items);


Fiz aqui agora, mas não testei.


GOSTEI 0
Woinch

Woinch

30/01/2009

Favor criar um tópico só para tirar as suas dúvidas na próxima vez. Isso atrapalha o pessoal que está aqui tentando ajudar...

Obrigado.


GOSTEI 0
El-loeco

El-loeco

30/01/2009

Segui seu exemplo e ficou tudo beleza.Obrigado. Mas o que eu gostaria mesmo era de implementar no que já comecei.


GOSTEI 0
Rudá

Rudá

30/01/2009

É só você adaptar, mas pelo que vi só vai a um determinado nível.

Outra coisa que você vai ter que fazer é quando clicar no item do menu fazer algo. Mas para isso você vai ter que criar alguns parâmetros.

Você pode criar um outro campo chamado Componente.

Você muda essa procedure
procedure TForm1.CriarMenu(ID: Integer; Menu: TMenuItem); 
var 
  AddMenu: TMenuItem; 
begin 
  qryMenu.Close; 
  qryMenu.ParamByName(´Menu´).AsInteger:= ID; 
  qryMenu.Open; 
  while Not qryMenu.Eof do 
  begin 
    AddMenu:= TMenuItem.Create(Self);
    AddMenu.Caption:= qryMenu.FieldByName(´Nome´).AsString; 
    AddMenu.Name:= ´mt´ + StringReplace(AddMenu.Caption,´ ´,´´,[rfReplaceAll]) + ´_´ + qryMenu.FieldByName(´ID´).AsString; // Mudei aqui coloquei um _ para separar o ID da string;
    AddMenu.OnClick = OnMenuClick; // Adicionei essa linha para quando clicar chamar a procedure.
    Menu.Add(AddMenu); 
    CriarMenu(qryMenu.FieldByName(´ID´).AsInteger,AddMenu); 
    qryMenu.Next; 
  end;


Depois criar uma procedure
procedure TForm1.OnMenuClick(Sender: TObject);
var
  ID: Integer;
begin
  ID:= StrToInt(Copy(TMenuItem(Sender).Name, Pos(TMenuItem(Sender).Name,´_´) + 1, Length(TMenuItem(Sender).Name)));


Dentro dessa procedure você pega o ID:= ...
Depois você pode pesquisar usando uma query com esse select
SELECT * FROM Tabela WHERE ID = :ID


Depois passar o ParamByName(´ID´).AsInteger:= ID;
E da um Open;

Depois disso você pode fazer alguma coisa como procurar o componente pelo conteudo do campo Componente e depois disso fazer algo.

Se for tudo formulario você pode criar-los e da um show ou showmodal.

E assim vai.


GOSTEI 0
POSTAR