Executar procedure através de uma string

Delphi

02/07/2004

Na verdade são 2 perguntas que eu quero fazer.

1º Tem como eu executar uma procedure através de uma string, tipo.

procedure mensagem;
begin
  showmessage(´Teste´);
end;

form1.button1click(sender:tobject);
begin
  [b]execute[/b](´mensagem´);
end;


2º Tem como criar uma procedure em tempo de execução onde o código da mesma estará em um arquivo externo.[/code]


Jprogramador

Jprogramador

Curtidas 0

Respostas

Sandra

Sandra

02/07/2004

1º Tem como eu executar uma procedure através de uma string, tipo.
procedure mensagem;
begin
  showmessage(´Teste´);
end;

form1.button1click(sender:tobject);
begin
  [b]execute[/b](´mensagem´);
end;


JProgramador,

Se eu entendi seu propósito, a 1ª procedure está correta; a 2ª, altere para:
form1.button1click(sender:tobject);
begin
  mensagem;
end;

Cada vez que clicar no button1, automaticamente, está chamando a procedure [b:2eae37bff7]mensagem[/b:2eae37bff7] e exibirá o showmessage. É isso?


GOSTEI 0
Jprogramador

Jprogramador

02/07/2004

Acho que não me expliquei direito, então deixa eu por a situação real.
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 CaptionNivel1Nivel2Nivel3
MnuCadastro Cadastro100
MnuCadastroClientes Clientes110
MnuCadastroProdutos Produtos120
MnuLocalizar Localizar200
MnuLocalizarClientes Clientes210
MnuLocalizarProdutos Produtos220
MnuRelatorio Relatorio300
MnuRelatorioClientes Clientes310
MnuRelatorioClientesDiarioDiário311
MnuRelatorioClientesMensalMensal312
MnuRelatorioProdutos Produtos320
MnuRelatorioProdutosDiarioDiário321
MnuRelatorioProdutosMensalMensal322

Menu resultante

CadastroLocalizarRelatorio
ClientesClientesClientes--> Diário
Mensal
ProdutosProdutosProdutos--> Diário
Mensal

Procedimento utilizado para criar o menu

procedure criarmenu;
var
  QryMenu:TQuery;  
  MenuPrincipal:TMainMenu;  
  ItemMenu:array of TMenuItem;
  i,j:integer;
Begin
  MenuPrincipal:=TMainMenu.Create(self);  //Criar o menu
  QryMenu:=TQuery.Create(self);  //Criar a query
  QryMenu.DatabaseName:=´sistema´;  //Nome do meu alias(Em paradox)
  QryMenu.sql.Add(´select * from menus order by nivel1,nivel2,nivel3´); //Selecionar todos os campos e ordenar de modo que crie um menu por vez
  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;
{Ai vem o motivo da 1º pergunta
Neste ponto queria passar o nome de uma procedure criada previamente com o mesmo nome do menu ex:
ItemMenu[i].OnClick:=QryMenu.FieldByName(´NomeMenu´).Value;
Só que OnClick é TNotifyEvent e QryMenu.FieldByName(´NomeMenu´).Value é string
outra alternativa seria criar a procedure nesse momento com o conteudo de um outro campo que eu criaria na tabela
Esse é o motivo da 2º pergunta
}
    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]);
    i:=i+1;
    QryMenu.Next;
  end;
end;


Espero ter sido mais claro, qual o objetivo disso?
se conseguir criar a procedure na hora sempre que quiser criar um novo menu é só criar um novo registro na tabela
se não der pra criar na hora mas der pra passar uma procedure, de qualquer forma fica mais organizado para eu trocar o menu para um treeview, botoes ou qualquer outro tipo de componente.
não sei dá pra criar a procedure na hora pelo delphi, mas passar uma procedure para um evento atraves do nome sei que é possível.
Se alguém quiser me ajudar, a facilitar nossas vidas em manutenção de softwares ficarei grato.

Ficou um pouquinho grande né ;-)


GOSTEI 0
Jprogramador

Jprogramador

02/07/2004

sobe


GOSTEI 0
Jprogramador

Jprogramador

02/07/2004

sobe


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

02/07/2004

[b:7b234f6173][size=18:7b234f6173]veja se isso aqui funciona:[/size:7b234f6173][/b:7b234f6173]

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;


GOSTEI 0
Jprogramador

Jprogramador

02/07/2004

Valeu Emerson, funcionou como vc disse. Muito obrigado.
Se vc descobrir se é possível criar uma procedure em tempo de execução como eu havia comentado, por favor me avise.


GOSTEI 0
El-loeco

El-loeco

02/07/2004

Olá emerson e JProgramador eu também usei essas dicas e funcionou beleza. Mas se pudece-mos adicionar mais um campo na tabela de ´NIVEL4... como ficaria o codigo? Ja tentei implementar mas não consegui. Se puder me ajudar fico grato. Abraço.


GOSTEI 0
POSTAR