Fórum Carregar menu Dinamico e jogar na tela conforme modelo #5755

18/05/2009

0

Boa noite

Sou iniciante em Delphi, porem tenho grande conhecimento em Firebird, ja com alguns anos de experiencia.

Eu assisti uma video aula no site da Devmedia, postada pelo Renato Matos, onde ele da um exemplo de carregar um Menu dinamico e tambêm estou seguindo uma video aula do mesmo autor com o assunto "Delphi OOP", dentro destes conceitos, eu gostatia de carregar um Menu de Forma dinamica (buscando de uma tabela no Firebird) baseado na empresa que o usuario irá logar.
Por exemplo:


Tenho 3 tipos de sistema, 1 basico, 1 intermediário e 1 completo, a diferença entre as 3 opções, é a quantida de menu disponivel no sistema.

Exemplificando:

Na opção 1 (Básico) o meu cliente terá apenas o Modúlo Contas a Receber que este contem o cadastro de Clientes, Lançamentos das parcelas e o Modulo Vendas que contem a Tela de Vendas e Cadastros de Produtos.

Na opção 2 (Intermediário) terá alem dos modulos contidos na opção 1, mais os modulos do Contas a Pagar com suas opções, o Modulo de Bancos, com suas opções e assim por diante na opção 3.

O tipo da opção do sistema contratado esta informado na tabela de Empresas no firebird.






Fiz um exemplo simbolico da Tela Inicial e abaixo a tela do Menu conforme eu gostaria de disponibilizar ao cliente.
No exemplo abaixo eu usei o ListView, não sei se é esta a melhor forma, mas pelo menos a disponização é importante para o produto que estou disponibilizando ao meu cliente.
Abaixo a tela do Menu:



Com esta configuração, ficará facil o acesso as opções, pois ele irá escolher o Modulo que se Encontra a Esquerda (Vendas, Caixa, etc) e do lado direito as opções do modulo (Cadastros, Relatórios, Movimentações, etc) que ele ira selecionar e escolher a opção que irá se abrir.



Sendo assim, ele irá escolher o modulo do lado esquerdo e do lado direito, ele irá mostrar a opção disponivel relacionada ao modulo.

Estes dados (Modulos e opções) eu gostaria de carregar conforme a opção informada no cadastro de empresa (tabela firebird), conforme o usuário logar e selecionar a empresa, ele irá trazer os modulos do menu e as opções do modulo.


Espero não ter abusado do meu primeiro chamado :D

Abraços,

Rogério.

Obs: Citei o listview, mas não precisa ser o mesmo, o importante para mim, é a flexibilidade do menu, ja que todas as opções estarão em apenas um banco de dados, disponibilizarei a opção conforme o cliente contratar (Basico, Intermediario e Completo) e a vizualização do mesmo para facilitar o manuseio do cliente, ja que eles reclamam muito dos MainMenus tradicionais.

Irei utilizar o Delphi 2009 e o Firebird 2.1.


Rogério Nascimento

Rogério Nascimento

Responder

Posts

19/05/2009

Rodrigo Mourão

Olá Rogério, fica tranquilo que não abusou não. Eu gosto de desafios. rsrsrsrs

Bem, não sei se você já assistiu alguma de minhas videos aulas. Eu sou bem prático, mas apesar disso não gosto de sair do padrão.
No seu caso temos duas opções: Ficar aqui durante dias desenvolvendo uma rotina que faça Exatamente o que você quer e com ListView. Digo dias pois a parte de montar os items do ListView e a parte mais simples, o mais complicado e linkar dinamicamente os eventos. O que também não é nada impossível de ser feito.

A segunda opção, e aí entra a praticidade, é criar manualmente todos os itens de menu conforme você quer na tela. E depois de criados apenas criamos uma rotina para exibir aqueles que o seu cliente tem acesso. Simples, prático, fácil e objetivo. O que acha ?

Isso irá lhe atender perfeitamente. Se estiver de acordo sinalize para que possamos dar início.

Abs!!!!!

P.S.: Gostei a ideia do ListView para trabalhar como menu. :-)


Atenciosamente,
Rodrigo Carreiro Mourão
Borland Instructor Certified
Coordenador da Consultoria em Delphi

Responder

Gostei + 0

19/05/2009

Rogério Nascimento

Fala Rodrigo, tudo na paz?!!!

Rapaz, estou acompanhando a sua video aula sobre Delphi 2007 e estou ansioso para ver o final. A sua proposta didatica e conceituosa sobre o assunto é muito boa.

Podemos fazer da forma que vc sugeriu, vindo de você a sugestão, ta feito.

Vamos lá, pode fazer da forma que você achou melhor.
Responder

Gostei + 0

19/05/2009

Rodrigo Mourão

Ok!

Começo a trabalhar nisto hoje mesmo. Em breve posto a solução.

Atenciosamente,
Rodrigo Carreiro Mourão
Borland Instructor Certified
Coordenador da Consultoria em Delphi


 
Responder

Gostei + 0

19/05/2009

Rodrigo Mourão

Olá Rogério, segue solução:

Vá no seu Form Principal e crie a seguinte procedure:     procedure CarregaMenu(Nivel: Byte);
A implementação deste metodo fica assim:

procedure TFrmPrincipal.CarregaMenu(Nivel: Byte);
var
  i: Integer;
  J: Integer;
begin
 for I := 0 to Pred(ComponentCount) do
    if Components[I] is TListView then
    begin
      J := Pred(TListView(Components[I]).Items.Count);
      while J >= 0 do
      begin
        if TListView(Components[I]).Items[J].StateIndex > Nivel then
        begin
          TListView(Components[I]).Items.Delete(J);
        end;
        Dec(J);
      end;
    end;
end;

O que faço ai na verdade é o seguinte. Eu varro o form e procuro por componentes TListView, pois pode haver mais de um. Quando localizo um TListView então percorro todos seus items e comparo a propriedade StateIndex com o Nivel passado, ou seja, cada item que você criar nos ListView você terá que alterar a propriedade StateIndex e colocar ali o nivel necessario para ele ser mostrado. Exemplo: 1, 2, 3, 4 Etc.

Assim quando você passar CarregaMenu(2) ele vai mostrar so os Items com StateIndex 1 e 2. No link abaixo te envio um exemplo feito em Delphi. Claro que o nivel voce traz do banco de dados.


http://video.devmedia.com.br/RodrigoCarreiro/Consultoria/MenuDinamico.zip


Abs.

Atenciosamente,
Rodrigo Carreiro Mourão
Borland Instructor Certified
Coordenador da Consultoria em Delphi
Responder

Gostei + 0

20/05/2009

Rodrigo Mourão

Olá Rogério !

Há mais alguma dúvida referente a este chamado?
Estamos aguardando para podermos encerrá-lo.

Abs.

Atenciosamente,
Rodrigo Carreiro Mourão
Borland Instructor Certified
Coordenador da Consultoria em Delphi

 
Responder

Gostei + 0

20/05/2009

Rogério Nascimento

Olá Rodrigo, tudo bem?  Perfeito, é isto mesmo, porem vou precisar da sua ajuda um pouco mais.
Vejamos pela imagem anexada, temos dois Listview, o da Esquerda é o Menu na qual eu irei carregar pela procedure, eu preciso que vc me ajude a chamar e passar o resultado da procedure para o listView da Esquerda.

Eu irei chamar a procedure que carrega os Menus e as Opçoes do Menu, apos o usuario logar no sistema e em seguida escolher a empresa que vai conectar, pois o mesmo pode ter mais de uma empresa no banco. 

Abaixo da imagem, eu mandei 3 tabelas e 1 procedure exemplificando como seria.





Fiz um pequeno exemplo de como seria as tabelas:

CREATE TABLE EMPRESA (
    CODIGO         INTEGER NOT NULL,
    RAZAOSOCIAL    VARCHAR(60),
    PACOTESISTEMA  INTEGER DEFAULT 0
);


/* Fields descriptions */

COMMENT ON COLUMN EMPRESA.PACOTESISTEMA IS
'1 = versao basica
2 = versao intermediaria
3 = versao completa';



INSERT INTO EMPRESA (CODIGO, RAZAOSOCIAL, PACOTESISTEMA) VALUES (1, 'BRUNI QUIMICA LTDA', 1);
INSERT INTO EMPRESA (CODIGO, RAZAOSOCIAL, PACOTESISTEMA) VALUES (20, 'BRUNI QUIMICA LTDA MATRIZ', 2);
INSERT INTO EMPRESA (CODIGO, RAZAOSOCIAL, PACOTESISTEMA) VALUES (50, 'PEQUIMIK SOLVENTES', 3);

COMMIT WORK;



=====================================================================


CREATE TABLE MENU (
    MENU_ID    INTEGER NOT NULL,
    MENUOPCAO  VARCHAR(20) NOT NULL,
    IMAGE       INTEGER DEFAULT 0
);

INSERT INTO MENU (MENU_ID, MENUOPCAO, IMAGE) VALUES (1, 'Contas a Receber', 0);
INSERT INTO MENU (MENU_ID, MENUOPCAO, IMAGE) VALUES (2, 'Contas a Pagar', 1);
INSERT INTO MENU (MENU_ID, MENUOPCAO, IMAGE) VALUES (3, 'Vendas', 2);
INSERT INTO MENU (MENU_ID, MENUOPCAO, IMAGE) VALUES (4, 'PCP', 3);
INSERT INTO MENU (MENU_ID, MENUOPCAO, IMAGE) VALUES (5, 'Compras', 4);
INSERT INTO MENU (MENU_ID, MENUOPCAO, IMAGE) VALUES (6, 'Cheques', 5);
INSERT INTO MENU (MENU_ID, MENUOPCAO, IMAGE) VALUES (7, 'Faturamento', 6);

COMMIT WORK;


=====================================================================

CREATE TABLE MENU_ITENS (
    MENU_ID             INTEGER NOT NULL,
    DESCRICAOITENSMENU  VARCHAR(30) NOT NULL,
    ABAOPCAO            INTEGER NOT NULL,
    IMAGEM              INTEGER DEFAULT 0 ,
    OPCAOCONTRATADA     INTEGER DEFAULT 0
);


COMMENT ON COLUMN MENU_ITENS.ABAOPCAO IS
' SE PERTENCE A CADASTROS, RELATORIOS, MOVIMENTACOES, ETC
 1 = CADASTROS
 2 = MOVIMENTACOES
 3 = RELATORIOS';



CREATE PROCEDURE SP_MENUS (
    cod_empresa integer)
returns (
    menu varchar(30),
    menuindex integer,
    item_menu varchar(30),
    menu_imagem integer,
    item_menu_imagem integer,
    abacontrole integer)
as
begin
   for select menu.menu_id, menu.menuopcao, menu.image,
              menu_itens.abaopcao, menu_itens.descricaoitensmenu, menu_itens.imagem
   from menu
   left join menu_itens on menu.menu_id = menu_itens.menu_id
   where menu_itens.opcaocontratada <= (select empresa.pacotesistema from Empresa Where Empresa.codigo = :cod_empresa)
   into menuindex, menu, menu_imagem,
        abacontrole, item_menu, item_menu_imagem do
  suspend;
end




Responder

Gostei + 0

21/05/2009

Rodrigo Mourão

Olá Rogério, é como eu lhe expliquei no início. O que você quer fazer e Montar todos os menus dinamicamente para isso ficar flexivel não é? Mas é uma false Flexibilidade. Repare que na tabela menu vc passa o Caption do Menu e o Index da imagem.

Mas onde está essa imagem?
 - No imageList dentro do Delphi.

Então se você quiser alterar o nome de um menu altera no banco, mas trocar o ícone tem que abrir a aplicação e trocar a imagem no ImageList. Com isso você tem parte da rotina no banco e parte na aplicação. Isso é extremamente ruim.

Você chegou  a rodar o código que lhe falei? Pois você pode ter 1,2,3 quantas listview quiser na aplicação com os itens que ele vai ocultar ou não.

Faça o seguinte em cada item que de cada ListView que você tem ai configura a propriedade StateIndex com 1, 2 ou 3 de acordo com o PACOTESISTEMA da empresa. Ex. menu Contas a Pagar coloca state Index 3 isso fara com que ele so aparceça na 3;

Agora como isso vai funcionar? Simples. Ao se logra você vai no banco e pega o PACOTESISTEMA da empresa e passar para a rotina CarregaMenu(Nivel: Byte); E mais.

Essa listView lateral tambem pode ter seus itens ocultados. Basta configurar a propriedade StateIndex dos itens também.

Rógerio esta é a melhor solução pois montar o menu e tranquilo mas se for feito dinamicamente como vai "injetar" o Onclick.

Por isso acho mais vantajoso deixar todos os itens criados em Design Time, com os onClick's ja programados e apenas ocultar os itens que a empresa não tenha acesso !!

Se quiser manda a sua aplicacao com o banco que implemento a rotina pra voce ver !!!

Abs !!!


Responder

Gostei + 0

21/05/2009

Rogério Nascimento

Olá Rodrigo, tdo bem?   Você tem razão !!!! Vamos fazer assim, eu vou testar conforme vc me orientou hoje a noite e caso eu tiver alguma duvida te passo ou encerro o chamado, combinado !!!?   Abraços.
Responder

Gostei + 0

24/05/2009

Rodrigo Mourão

Olá Amigo !!

Por falta de retonro encerramos o seu chamado. Caso ainda possua alguma dúvida sobre esse assunto, por favor, post a mesma que o consultor voltará a lhe atender e o chamado será reaberto.
Abs !!


Responder

Gostei + 0

12/06/2009

Rogério Nascimento

Olá Rodrigo, tudo bem? Olha eu aqui novamente !!!

Esbarrei com um problema não previsto na rotina implementada e preciso de sua ajuda.

Conforme a rotina que vc me passou, esta acontecendo o seguinte:

//////////  Rotina implementada //////////////


procedure TfrmPrincipal.CarregaMenu(Nivel: Byte);
var
  i: Integer;
  J: Integer;
begin
// Filtra as opções do ListView conforme o Modulo Relacionado (Rodrigo Carreiro / DevMedia);
 for I := 0 to Pred(ComponentCount) do
    if Components[I] is TListView then
    begin
      J := Pred(TListView(Components[I]).Items.Count);
      while J >= 0 do
      begin
        if TListView(Components[I]).Items[J].StateIndex > Nivel then
        begin
          TListView(Components[I]).Items.Delete(J);
        end;
        Dec(J);
      end;
    end;
end;


O Menu, tem vários modulos a esquerda e do lado direito tem o listview que aparece as opções do modulo selecionado, conforme vc tinha me orientado, adicionei todos os itens no listview e depois conforme clico no modulo, ele apaga os itens diferentes do modulo selecionado, porem acontece o seguinte:

Entrei no modulo Contas a Receber, beleza, os itens que estão no listview, são relacionados a ele, qdo vou para outro modulo, Vendas por exemplo, ja não aparece mais as opções no listview, ja que qdo eu entrei no Contas a Receber, ele apagou o que foi diferente dele, qdo entrei no vendas, ele tbm apagou o que foi diferente dele, porem não carregou as opções relacionadas a ele, assim o listview fica vazio.


Pensei na seguinte situação, como uso Tabsheet, adicionar uma Tab que não ficará visivel ao usuário e nesta adiciono um listView, com todas as opções do sistema ja inseridas nele e conforme eu clicar no menu na tela inicial, ele capta as opçoes relacionadas ao menu pelo State Index (conforme sugerido por você) e adiciona no listview principal. Se esta for a forma mais facil, gostaria que vc me ajudasse a implementar isto, ou, sugerir algo para isto.

Abaixo a tela principal de como esta.



Abraços,

Rogério Nascimento.
Responder

Gostei + 0

15/06/2009

Rodrigo Mourão

Olá Rogério,


Bem vamos lá, eu acredito que a melhor maneira de resolver o problema seja restaurar a condição inicial ao mudar o módulo. Por exemplo, quando vc entra no Contas a Pagar vc oculta alguns itens. Quando vc trocar de modulo faça um loop e coloque todos os itens visíveis. Assim volta ao estado original e ai vc poderá chamar a rotina para outro modulo.

Assim é mais simples de implementar.

Abs!!


Atenciosamente,
Rodrigo Carreiro Mourão
Borland Instructor Certified
Coordenador da Consultoria em Delphi
Responder

Gostei + 0

15/06/2009

Rogério Nascimento

Olá Rodrigo

Como eu faço para restaurar as opções que foram deletadas?
Responder

Gostei + 0

17/06/2009

Rodrigo Mourão

Rogério agora você me colocou em check rsrsrsrs!


Não me atentei ao detalhe que estavamos deletando o item. Mas deixar eu ver aqui. Se não tiver a opção visible no Item (E acho que não tem) então vamos tentar reconstruir o controle. Aqui no momento estou sem Delphi mas assim que chegar no cliente eu vou fazer os teste e te enviar.

Abs!!

Atenciosamente,
Rodrigo Carreiro Mourão
Borland Instructor Certified
Coordenador da Consultoria em Delphi
Responder

Gostei + 0

17/06/2009

Rogério Nascimento

Olá Rodrigo, sem problemas !!!

Você tem alguma sugestão para substituir-mos o listview por outro componente que seja mais facil a manutenção, mas que de a mesma aparencia, pois o meu foco é dar facilidade ao acesso ao menu, ficando bem visivel todas opções ao entrar no modulo, evitando o incoveniente de ficar navegando pelo menu até achar a outra opção.
Responder

Gostei + 0

17/06/2009

Rodrigo Mourão

Rogério, não se atreva rsrsrsrsrsrsrs

Este disposição e esta ideia do ListView foi uma grande sacada você está de parabéns.
Eu fiquei enrolado durante o dia mas ja estou fazendo o teste com o repaint e o CreateWND acho que vai nos ajudar. 

Peço que aguardo mais um pouco !!

Abs!!


Atenciosamente,
Rodrigo Carreiro Mourão
Borland Instructor Certified
Coordenador da Consultoria em Delphi
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar