MAINMENU APATIR DE UMA TABELA DO BANCO
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?
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
Curtidas 0
Respostas
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:
como exemplo fiz esses inserts
Deve aparecer assim:
Crie uma TQuery ou outro tipo e coloque esse select ( vou chamar de qryMenu)
Procedure para adicionar.
Depois é só vc chamar
Fiz aqui agora, mas não testei.
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 = 7Deve 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
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.
Obrigado.
GOSTEI 0
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á
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
Depois criar uma procedure
Dentro dessa procedure você pega o ID:= ...
Depois você pode pesquisar usando uma query com esse select
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.
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