quarta-feira, 27 de fevereiro de 2008

MethodAddress

Método definido em TObject, retorna o endereço de um método published. Ou seja, um método definido na seção “published”. Entretanto, evocar o “MethodAddress” não é algo tão trivial. É preciso criar uma variável do tipo “procedure” que receberá o ponteiro para o método retornado por “MethodAddress”.
Exemplo 1:

unit Unit1;

interface

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

type
 TForm1 = class(TForm)
 BitBtn1: TBitBtn;
 procedure BitBtn1Click(Sender: TObject);
 private

 public

 published
   procedure MyZnMethod;
end;

var
 Form1: TForm1;

implementation

 {$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
var
AuxProcedure: Procedure(Sender: TObject);
begin
 AuxProcedure := Self.MethodAddress('MyZnMethod');
 AuxProcedure(Self);
end;

procedure TForm1.MyZnMethod;
begin
 Self.Caption := 'Estação ZN';
 Self.Color := clAqua;
 Self.Update;
 Self.Canvas.TextOut(12, 130, 'Dummy MethodAddress Teste Estação ZN!!!');
end;

end.



Ok, muito simples! Só que se eu desejar evocar um método que está definido em outra classe terei de usar uma estratégia, pois o método MethodAddress, só conhece os métodos definidos na própria classe. Para exemplificar, vamos criar uma classe ‘TMyZnClassDummy’ e no mesmo evento OnClick do BitBtn1 evocar o método “Dummy” da nova classe, “TMyZnClassDummy”. Exemplo2:

unit Unit1;

interface

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

type
 TForm1 = class(TForm)
 BitBtn1: TBitBtn;
 procedure BitBtn1Click(Sender: TObject);
 private

 public

ppublished
   procedure MyZnMethod;
end;

type
 TMyZnClassDummy = Class(TComponent)
 private

 protected
 published
   procedure Dummy;
end;

var
 Form1: TForm1;

implementation

 {$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
var
 AuxProcedure: Procedure(Sender: TObject);
 AuxProcedureBlah: Procedure(Sender: TObject);
begin
 AuxProcedure := Self.MethodAddress('MyZnMethod');
 AuxProcedure(Self);

 (*Testando o Blah*)
 ShowMessage('Testando o Blah!!');
 AuxProcedureBlah := MethodAddress('Dummy');
 AuxProcedureBlah(Self)
end;

procedure TForm1.MyZnMethod;
begin
 Self.Caption := 'Estação ZN';
 Self.Color := clAqua;
 Self.Update;
 Self.Canvas.TextOut(12, 130, 'Dummy MethodAddress Teste Estação ZN!!!');
end;

{ TMyZnClassDummy }

procedure TMyZnClassDummy.Dummy;
begin
 ShowMessage(Self.Name + ' Blah!!!!');
end;

end.


Como eu posso fazer para conseguir executar o método “Dummy”? Eu preciso (primeiro, se for o caso fazer uses da unit onde a classe, cujo o método desejo evocar, se encontra) criar na classe que vai chamar através do “MethodAddress” um outro método pblished, este por sua vez chamara o método definido na outra classe. Vou Criar no Form1 um método que evocará o método “Dummy” da classe “TMyZnClassDummy”.Exemplo:
unit Unit1;

interface

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

type
 TForm1 = class(TForm)
 BitBtn1: TBitBtn;
 procedure BitBtn1Click(Sender: TObject);
 private

 public

 published
   procedure MyZnMethod;
   procedure ExeucteDummy;
end;

type
 TMyZnClassDummy = Class(TComponent)
 private

 protected
 published
   procedure Dummy;
end;

var
 Form1: TForm1;

implementation

 {$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
var
 AuxProcedure: Procedure(Sender: TObject);
 AuxProcedureBlah: Procedure(Sender: TObject);
begin
 AuxProcedure := Self.MethodAddress('MyZnMethod');
 AuxProcedure(Self);

 (*Testando o Blah*)
 ShowMessage('Testando o Blah!!');
 (* Executo o Método procedure do Form1 "ExeucteDummy" *)
 AuxProcedureBlah := MethodAddress('ExeucteDummy');
 AuxProcedureBlah(Self)
end;

procedure TForm1.ExeucteDummy;
var
 MyZnClassDummy: TMyZnClassDummy;
begin
 MyZnClassDummy := TMyZnClassDummy.Create(Self);
 try
   MyZnClassDummy.Dummy;
 finally
   MyZnClassDummy.Free;
 end;

end;

procedure TForm1.MyZnMethod;
begin
 Self.Caption := 'Estação ZN';
 Self.Color := clAqua;
 Self.Update;
 Self.Canvas.TextOut(12, 130, 'Dummy MethodAddress Teste Estação ZN!!!');
end;

{ TMyZnClassDummy }

procedure TMyZnClassDummy.Dummy;
begin
 ShowMessage(Self.ClassName + ' Blah!!!!');
end;

end.

Baseado nisso, podemos criar um catálogo de métodos de classes distintas, os quais poderão ser exibidos numa interface, permitindo ao usuário uma forma de setup da aplicação. De maneira que ele possa definir que funcionalidade será executada a partir de uma determinada ação na interface. Sei que esse tipo de abordagem não é nada convencional, contudo acredito ela permita um flexibilização poderosa para algumas situações.


"A mente que se abre a uma nova idéia jamais voltará ao seu tamanho original". Albert Estein

Nenhum comentário:

Postar um comentário

 
BlogBlogs.Com.Br