xe7 que portable lite licencia full embarcadero architect delphi delphi-2009

que - licencia delphi



¿Puedo utilizar un cierre en un controlador de eventos(es decir, TButton OnClick) (4)

Si trato de usar un cierre en un controlador de eventos, el compilador se queja con:

Tipos incompatibles: "puntero del método y procedimiento regular"

lo cual entiendo ... pero ¿hay alguna manera de usar un clouser en los punteros del método? y cómo definir si puede?

p.ej :

Button1.Onclick = procedure( sender : tobject ) begin ... end;

¡Gracias!


Una excelente pregunta.

Por lo que yo sé, no es posible hacerlo en la versión actual de Delphi. Esto es muy desafortunado ya que esos procedimientos anónimos serían geniales para configurar rápidamente los manejadores de eventos de un objeto, por ejemplo cuando se configuran los dispositivos de prueba en un tipo de marco de prueba automático xUnit.

Debe haber dos formas en que CodeGear implemente esta función:

1: Permitir la creación de métodos anónimos. Algo como esto:

Button1.OnClick := procedure( sender : tobject ) of object begin ... end;

El problema aquí es qué poner como el auto puntero para el método anónimo. Uno podría usar el puntero del objeto desde el que se creó el método anónimo, pero luego solo se pueden crear métodos anónimos desde un contexto de objeto. Una mejor idea podría ser simplemente crear un objeto falso detrás de las escenas para contener el método anónimo.

2: Alternativamente, se podría permitir que los tipos de eventos acepten tanto métodos como procedimientos, siempre que compartan la firma definida. De esta forma, puede crear el controlador de eventos de la manera que desee:

Button1.OnClick := procedure( sender : tobject ) begin ... end;

En mi opinión, esta es la mejor solución.


En las versiones anteriores de Delphi, puede usar un procedimiento regular como controlador de eventos agregando el puntero auto oculto a los parámetros y encasillarlo duro:

procedure MyFakeMethod(_self: pointer; _Sender: TObject); begin // do not access _self here! It is not valid ... end; ... var Meth: TMethod; begin Meth.Data := nil; Meth.Code := @MyFakeMethod; Button1.OnClick := TNotifyEvent(Meth); end;

No estoy seguro de que lo anterior realmente compila, pero debería darle la idea general. He hecho esto previamente y funcionó para procedimientos regulares. Como no sé qué código genera el compilador para los cierres, no puedo decir si esto funcionará para ellos.


@Button1.OnClick := pPointer(Cardinal(pPointer( procedure (sender: tObject) begin ((sender as TButton).Owner as TForm).Caption := ''Freedom to anonymous methods!'' end )^ ) + $0C)^;

trabaja en Delphi 2010


Es fácil extender el siguiente para manejar más tipos de eventos de formulario.

Uso

procedure TForm36.Button2Click(Sender: TObject); var Win: TForm; begin Win:= TForm.Create(Self); Win.OnClick:= TEventComponent.NotifyEvent(Win, procedure begin ShowMessage(''Hello''); Win.Free; end); Win.Show; end;

Código

unit AnonEvents; interface uses SysUtils, Classes; type TEventComponent = class(TComponent) protected FAnon: TProc; procedure Notify(Sender: TObject); class function MakeComponent(const AOwner: TComponent; const AProc: TProc): TEventComponent; public class function NotifyEvent(const AOwner: TComponent; const AProc: TProc): TNotifyEvent; end; implementation { TEventComponent } class function TEventComponent.MakeComponent(const AOwner: TComponent; const AProc: TProc): TEventComponent; begin Result:= TEventComponent.Create(AOwner); Result.FAnon:= AProc; end; procedure TEventComponent.Notify(Sender: TObject); begin FAnon(); end; class function TEventComponent.NotifyEvent(const AOwner: TComponent; const AProc: TProc): TNotifyEvent; begin Result:= MakeComponent(AOwner, AProc).Notify; end; end.