atribuir duas procedures a um evento

11/02/2006

dá para atribuir duas procedures a ao evento onExit?

acontece o seguinte:
na minha aplicação tenho uma rotina que atribui para todos os componentes que tem o evento OnExit uma determinada procedure. sendo que estou precisando colocar em um componente no evento OnExit um determinado código. no entanto não funciona pois ao executar a aplicação este é sobrescrito pela rotina que atribui para todos os componentes.


Raserafim

Respostas

11/02/2006

Marco Salles

eu nun sei se estendi direito , mas acho que voce pode usar um flag

Por exemplo , quando o componente receber o foco , no evento onenter voce atribui esta flag igual a true
No evento onexit geral voce testa este flag , se for verdadeiro voce executa

onexitGeral
begin
codigos comuns a todos os componentes
if flag then
 faça algo em especial
flag:=False;
end



Responder Citar

11/02/2006

Raserafim

marcos salles, não posso fazer desta forma pois esta minha rotina geral, uso ela também em outras aplicações, e portanto não pode ter nada em específico nela.


Responder Citar

11/02/2006

Marco Salles

marcos salles, não posso fazer desta forma pois esta minha rotina geral, uso ela também em outras aplicações, e portanto não pode ter nada em específico nela.


Se ela é geral , é usada em outras aplicaçoes , qual o problema se voce no componente onde voce quer acrescentar o código voce escrever

eventoOnexitDoComponete begin executarProcedureOnExitGeral ExecutarOqueQuero end;


porque a se é que eu estou entendendo , a saida para isso tem ,
1) voce altera o codigo do eventoOnexit do Componente especifico , conforme mencionei acima ou
2)voce altera o codigoGeral para atender um caso especifico

Sera que eu estou entendendo direito ???


Responder Citar

11/02/2006

Raserafim

o problema marcos salles, é que esta rotina é chamada no OnCreate dos forms, e então varre todo o form e atribui um procedimento ao evento OnExit de todos os componentes que tem este evento


Responder Citar

11/02/2006

Marco Salles

o problema marcos salles, é que esta rotina é chamada no OnCreate dos forms, e então varre todo o form e atribui um procedimento ao evento OnExit de todos os componentes que tem este evento


gostaria de entender melhor ...

Coloque um fragmento de codigo do evento OnCreateForm e o como voce faz para atribuir este evento OnExit a todos os componentes que tem esse evento


Responder Citar

14/02/2006

Raserafim

na verdade eu digo os tipos de componentes que quero que sejam atribuidos. no OnCreate do form chamo a rotina geral, que varre todos os componentes do form e os que forem do tipo que eu defini então ele atribui um procedimento ao componente


Responder Citar

14/02/2006

Raserafim

pensei na seguinte hipótese:

na rotina geral faço um código que crie uma procedure dinamicamente juntando as duas procedures. ex:

o Componente Edit1 teria em seu evento OnExit uma chamada a Edit1Exit.

ao abrir este form a rotina geral iria atribuir ao evento OnExit de todos os form a procedure ProcedGeral, sobrescrevendo a que já tinha.
a solução que vejo é: a rotina geral criaria uma procedure dinamicamente desta forma:

procedure Edit1Exit_Dinamica;
begin
Edit1Exit;
ProcedGeral;
end;


Responder Citar

14/02/2006

Marco Salles

Deixa ver se eu entendi

[b:6daa48510e]vamos supor que se tenha dois edits nun form[/b:6daa48510e]

[b:6daa48510e]os dois edits tem definidos um evento onexit a nivel de projeto[/b:6daa48510e]

procedure TForm1.Edit1Exit(Sender: TObject);
begin
showmessage(´evevento OnExit do edit1´);
end;


procedure TForm1.Edit2Exit(Sender: TObject);
begin
showmessage(´evento onexit do edit2´);
end;

[b:6daa48510e]defino na secção private do formulário a procedure[/b:6daa48510e]

procedure EditExit_Dinamica(sender:Tobject); que tem os mesmos paramentros do evento que sera substituido

type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; procedure Edit1Exit(Sender: TObject); procedure Edit2Exit(Sender: TObject); procedure FormCreate(Sender: TObject); private procedure EditExit_Dinamica(sender:Tobject); //definição { Private declarations } public { Public declarations } end;


defino também a procedure Geral

var Form1: TForm1; implementation {$R *.DFM} procedure Geral; begin showmessage(´Faço o que quiser´); end;


e finalmente no oncreate faço esta conexao da procedure onexit do edit2 com a procedure EditExit_Dinamica;

procedure TForm1.FormCreate(Sender: TObject);
begin
form1.Edit2.OnExit:=nil;
form1.Edit2.OnExit:=EditExit_Dinamica;
end;


[b:6daa48510e][color=darkred:6daa48510e]finalmente voce deve testar [/color:6daa48510e][/b:6daa48510e]... :arrow: e so ai dar o seu parecer do que esta certo e do que esta errado dentro da sua necessidade..

quero destacar que existem rotinas que varrem todos os edits de todos os form , atribuindo automaticamente o novo evento EditExit_Dinamica aos componentes... Alem disso existe a propriedade [b:6daa48510e]tag[/b:6daa48510e] dos componentes que pode ser usada para determinar , quais são os edits que terao seu evento alterado.. Tipo isso

procedure TForm1.FormCreate(Sender: TObject);
var
i:integer;
begin
for i:=0 to form1.ComponentCount-1 do
if form1.Components[i] is TEdit Then
if Tform1(form1.Components[i]).tag = 2 then ///seleção
begin
form1.Edit2.OnExit:=nil;
form1.Edit2.OnExit:=EditExit_Dinamica;
end;
end;

[b:6daa48510e]e claro que previamente esses edits a nivel de projeto , terao que ter os seu tag no valor igual a 2[/b:6daa48510e]


Responder Citar

18/02/2006

Raserafim

entenda uma coisa:
a rotina geral não está dentro do form. está em uma Unit que quero usar em outros projetos. também não existe declarado esta procedure dinamica EditExit_Dinamica.
esta procedure dinâmica foi uma idéia de sugestão para resolver o meu problema. mas que não sei implementar.
ou seja, seria uma procedure que eu iria criar em tempo de execução que concatenasse o procedimento que quero atribuir aos OnExit e o provável procedimento que poderá estar configurado já no componente em tempo de projeto de algum componente.

portanto é o seguinte:
imagine que vc tenha o seu projeto já prontinho. vc colocou alguns tratamentos no evento OnExit de seus Edits. sendo que vc quer ter o a funcionalidade que a minha Unit quer proporcionar. então eu lhe forneço o .DCU dela e te digo: é só vc fazer a chamada a tal procedimento no OnCreate.
pronto. é isso que quero fazer. mas se vc fizer isso a minha rotina foi sobrepro os seus eventos que já existiam no OnExit.
o que quero então é que a minha rotina consiga de alguma forma executar o código dela e mais o código que já existia no seu projeto.


Responder Citar

18/02/2006

Marco Salles

entenda uma coisa:

seria uma procedure que eu iria criar em tempo de execução


desculpe , mas para mim ta dificil de entender :cry: :cry: :cry:

[b:cdff9b0c75]Voce disse que esta conseguindo concatenar [/b:cdff9b0c75]

mas se vc fizer isso a minha rotina foi sobrepro os seus eventos que já existiam no OnExit.


o que quero então é que a minha rotina consiga de alguma forma executar o código dela e mais o código que já existia no seu projeto
.

eu não sei como voce esta fazendo esta concatenação .. O que sei é que se estivessemos pensando em [b:cdff9b0c75]classe pai e classe filho [/b:cdff9b0c75], fariamos isto com as directivas [b:cdff9b0c75][color=darkblue:cdff9b0c75]Virtual , Override e Inherited[/color:cdff9b0c75][/b:cdff9b0c75]

Mas , mostre o seu codigo talves alguem entenda e lhe responda

Boa sorte...


Responder Citar

21/02/2006

Raserafim

Mascos Salles, apesar de eu achar que o código não é necessário para a resolução, mas aí vai pelo menos para melhor entendimento do problema:

criei uma Unit mais ou menos assim:
unit UFun_Form;


interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  StdCtrls, ExtCtrls, Dialogs;

type
  TFun_Form = class(TForm)
  private
    procedure Funcionalidade (Sender: TObject);
  public
    procedure Funcao (Sender: TForm);
  end;

var
  Fun_Form: TFun_Form;
  Frm: TForm;

implementation

procedure TFun_Form.Funcao (Sender: TForm);
var
  C: Smallint;
begin
  Frm := Sender;
  with Sender do
  begin
    for C := 0 to ComponentCount - 1 do
    begin
      if (Components[C&93;.ClassType = TEdit) then
      begin
        TEdit(Components&91;C&93;).OnExit := Funcionalidade;
      end
    end;
  end;
end;

procedure TFun_Form.Funcionalidade(Sender: TObject);
begin
  Beep; //apenas para simplificar o exemplo.
end;

end.


e em cada form do meu projeto declaro esta Unit, e no evento OnShow coloco:
  Fun_Form.Funcao(Self);


resultado:
ao chamar o procedimento Funcao e passar como parâmetro o form que a chamou, consigo varrer o form e ver todos os componentes que são do tipo TEdit e com isso atribuir ao evento OnExit de cada um o procedimento Funcionalidade.
então neste exemplo iria acontecer o seguinte: ao sair de cada componente TEdit seria emitido um beep.

o problema:
ao chamar o procedimento Funcao ele vai atribuir o procedimento Funcionalidade aos eventos OnExit. e se eu em algum edit em particular eu quiser colocar masis algum código?
do jeito que está este código particular vai ser desprezado. sendo que eu não posso colocar nada em particular neste código que apresentei, pois que utilizar tb em outros projetos.

e eu não disse que eu consegui concatenar para criar uma procedure dinâmica, esta foi apenas uma hipótese que idealizei, mas não consegui implementar.


Responder Citar

21/02/2006

Raserafim

Mascos Salles, apesar de eu achar que o código não é necessário para a resolução, mas aí vai pelo menos para melhor entendimento do problema:

criei uma Unit mais ou menos assim:
unit UFun_Form;


interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  StdCtrls, ExtCtrls, Dialogs;

type
  TFun_Form = class(TForm)
  private
    procedure Funcionalidade (Sender: TObject);
  public
    procedure Funcao (Sender: TForm);
  end;

var
  Fun_Form: TFun_Form;
  Frm: TForm;

implementation

procedure TFun_Form.Funcao (Sender: TForm);
var
  C: Smallint;
begin
  Frm := Sender;
  with Sender do
  begin
    for C := 0 to ComponentCount - 1 do
    begin
      if (Components[C&93;.ClassType = TEdit) then
      begin
        TEdit(Components&91;C&93;).OnExit := Funcionalidade;
      end
    end;
  end;
end;

procedure TFun_Form.Funcionalidade(Sender: TObject);
begin
  Beep; //apenas para simplificar o exemplo.
end;

end.


e em cada form do meu projeto declaro esta Unit, e no evento OnShow coloco:
  Fun_Form.Funcao(Self);


resultado:
ao chamar o procedimento Funcao e passar como parâmetro o form que a chamou, consigo varrer o form e ver todos os componentes que são do tipo TEdit e com isso atribuir ao evento OnExit de cada um o procedimento Funcionalidade.
então neste exemplo iria acontecer o seguinte: ao sair de cada componente TEdit seria emitido um beep.

o problema:
ao chamar o procedimento Funcao ele vai atribuir o procedimento Funcionalidade aos eventos OnExit. e se eu em algum edit em particular eu quiser colocar masis algum código?
do jeito que está este código particular vai ser desprezado. sendo que eu não posso colocar nada em particular neste código que apresentei, pois que utilizar tb em outros projetos.

e eu não disse que eu consegui concatenar para criar uma procedure dinâmica, esta foi apenas uma hipótese que idealizei, mas não consegui implementar.


Responder Citar

21/02/2006

Michael

Olá [b:dd9a4fb5f1]raserafim[/b:dd9a4fb5f1]!

Múltiplos manipuladores para um mesmo evento não são permitidos em Delphi Win32. Essa característica está disponível apenas no .NET framework.

Porém, nada impede que vc faça algo assim:

(...)
if (Components[C&93;.ClassType = TEdit) and not Assigned(TWinControl(Components&91;C&93;).OnExit) then
  begin
    TEdit(Components&91;C&93;).OnExit := Funcionalidade;
  end;
(...)


A função [b:dd9a4fb5f1]Assigned [/b:dd9a4fb5f1]não vai permitir que vc sobrescreva o manipulador do evento [b:dd9a4fb5f1]OnExit [/b:dd9a4fb5f1]de um controle que já tenha implementado um. Cada [b:dd9a4fb5f1]TEdit [/b:dd9a4fb5f1]que implementar seu próprio evento [b:dd9a4fb5f1]OnExit [/b:dd9a4fb5f1]deve chamar a rotina [b:dd9a4fb5f1]Funcionalidade[/b:dd9a4fb5f1], antes ou depois do código, dependendo do que vc quer fazer. Para não ficar preso ao nome [i:dd9a4fb5f1]Funcionalidade[/i:dd9a4fb5f1], se ele já não for genérico, crie uma variável de ponteiro de procedure, e use-a para chamar a rotina dentro dos eventos [b:dd9a4fb5f1]OnExit [/b:dd9a4fb5f1]específicos.

TForm1 = class(TForm)
  private
    FOnExitProc: TNotifyEvent;
(...)

procedure TForm1.FormCreate(Sender: TObject);
begin
  FOnExitProc := Funcionalidade;
(...)
end;

procedure TEdit1.OnExit(Sender: TObject);
begin
  FOnExitProc(Edit1);
  // Código específico de Edit1
end;


[]´s


Responder Citar

21/02/2006

Marco Salles

Mascos Salles, apesar de eu achar que o código não é necessário para a resolução, mas aí vai pelo menos para melhor entendimento do problema:


[b:4a2b9db8d8]Ajuda de mais.... Vale mais do que mil palavras[/b:4a2b9db8d8]

Múltiplos manipuladores para um mesmo evento não são permitidos em Delphi Win32. Essa característica está disponível apenas no .NET framework. Porém, nada impede que vc faça algo assim:


então como escreveu o nosso amigo michel , tecnicamente o delphi win.32 não permite uma solução mais tecnica do problema , porem como ele mesmo disse , nada impede que voce ache uma solução para o problema

e pensando nisso eu fiz assim :

[color=blue:4a2b9db8d8][b:4a2b9db8d8]1)
mudei os parametros da função Funcionalidade ,
Mudei tb de Privativo para protegido
intoduce a palavra chave virtual no método Funcionalidade;[/b:4a2b9db8d8][/color:4a2b9db8d8]

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  protected
      procedure Funcionalidade (Sender: TObject);virtual;
    { Private declarations }
  public
    procedure Funcao (form: TForm);
    { Public declarations }
  end;


ate ai tudo bem, o resto continua o mesmo..

[color=red:4a2b9db8d8]2)Parte[/color:4a2b9db8d8]
e em cada form do meu projeto declaro esta Unit, e no evento OnShow coloco:


[b:4a2b9db8d8]a)Não , agora esta unit tem que ser definida na uses da secção interface [/b:4a2b9db8d8]e nao mais na uses da secçao implementacion. Alem disso :

b)crie uma [b:4a2b9db8d8]classe filha [/b:4a2b9db8d8], note a introdução da palavra chave[b:4a2b9db8d8][color=darkred:4a2b9db8d8] Override[/color:4a2b9db8d8][/b:4a2b9db8d8]

Type
 Meuformulario =Class (TForm1)
 private
   procedure Funcionalidade (sender: TObject);Override;
end;


:idea: :idea:
[b:4a2b9db8d8]3)nesta classe de um ´CTRL+C´ para que o editor do delphi inclua automaticamente a definição .. Ira aparecer a palavra Chave Inherited
ficando mais ou menos assim:[/b:4a2b9db8d8]

procedure Meuformulario.Funcionalidade(sender: TObject);
begin
  inherited;
  case TEdit(sender).tag of
    0:showmessage(´incluir metodos de nivel 0´);
    1:showmessage(´incluir metodos de nivel 1´);
    2:showmessage(´incluir metodos de nivel 2´);
  end;
end;


:idea: :idea:
note que eu coloquei ainda a propriedade[b:4a2b9db8d8][color=darkred:4a2b9db8d8] tag [/color:4a2b9db8d8][/b:4a2b9db8d8]definindo diversos tipos de métodos.. [b:4a2b9db8d8]é claro que os valores do tag tem que serem definidos a nivel de projeto[/b:4a2b9db8d8]

[b:4a2b9db8d8][color=blue:4a2b9db8d8]4)falta ainda eu criar uma variavel do tipo MeuFormulario[/color:4a2b9db8d8][/b:4a2b9db8d8]

var
  Form2: TForm2;
  Novoformulario:Meuformulario;


:arrow:
e finamente eu istancio esta variavel , uso e libero no show como voce mesmo sugeriu

procedure TForm2.FormShow(Sender: TObject);
begin
formularioexato:=formulario.Create(self);
Formularioexato.Funcao(form2); ***********
freeandnil(formularioexato);
end;


[b:4a2b9db8d8]note que no meu caso eu estou atribuindo aos edits do formulario2 (Form2) os evento onexit que eu quero[/b:4a2b9db8d8]

eu acho que o que voce quer é isso ai ..

boa sorte.


Responder Citar

27/02/2006

Raserafim

masco salles valeu por algumas sugestões (que acabei acatando), mas ainda não é isso que quero. caso eu não consiga exatamente da forma que quero vou acabar utilizando como base o que vc colocou.
e Michael, acho que o nome que vc disse: ´Múltiplos manipuladores´ está bem próximo ou exatamente o que eu quero.

será que não estou conseguindo me expressar?


Responder Citar