2010-12-21 25 views
11

necesito colocar a través de componentes y asignar un controlador de eventos (por ejemplo dinámicamente la asignación de evento OnClick para todos TButton aDelphi: cómo asignar dinámicamente un controlador de eventos sin sobrescribir el controlador de eventos existente?

ShowMessage('You clicked on ' + (Sender as TButton).Name); 

El problema es que en algunos casos ya asignado el evento TButton OnClick.

¿hay una manera de resolver el problema

Imaginemos que tengo Button1 para el que el controlador de eventos onclick harcoded es:?

ShowMessage('This is Button1'); 

Después de mi "análisis" Me gustaría que el controlador de eventos completo para Button1 se convierte en:

ShowMessage('This is Button1'); // design time event handler code 
ShowMessage('You clicked on ' + (Sender as TButton).Name); // runtime added 

Nota: Busco a una soliution que me permite usar TButton ya que es sin heredar de ella.

+0

Pregunta similar (con el código completo como respuesta): http://stackoverflow.com/questions/2441672/how-can-i-dynamically-inject-code-into-event-handlers-in-delphi – mjn

+0

eche un vistazo a TApplicationEvents fuente, hay el mismo evento que usted desea. –

+3

El término general para lo que quiere es * eventos de multidifusión *, pero Delphi no tiene esa característica. –

Respuesta

16

puede buscar una asignación de OnClick antes de sobreescribirla, persistir en esto y usarla en su nuevo controlador, básicamente encadenando los eventos.

Algo como esto:

var original : TNotifyEvent; 

    original := Component.OnClick; 
    Component.OnClick := NewMethod; 

y luego en su newMethod:

if assigned(original) then original(Sender); 

es probable que no quieren una sola variable original, pero en cambio sostienen una colección manipulada en el componente.

+0

Gracias por la idea, debería funcionar. También la idea de la colección (un TDictionary de genéricos por ejemplo) es muy buena. – LaBracca

2

Si está escribiendo los manipuladores de reemplazo a sí mismo que podría hacer lo siguiente:

  • antes de la asignación del nuevo controlador, almacenar una referencia al objeto y una referencia al controlador original en una lista u otra estructura.

  • En su controlador de reemplazo, código incluido para verificar la lista para ver si el objeto actual tiene una entrada. Si lo hace, llame al método almacenado antes de hacer su propio trabajo.

Esto es bastante liviano (una lista donde cada entrada es de dos punteros). Con un poco de trabajo adicional (para respaldar el pedido) probablemente podrías encadenar más de un controlador reemplazado.

1

No puede hacer eso directamente ya que Delphi no admite eventos encadenados (supongo que VCL Delphi).

Por lo tanto, cualquier cosa que desee hacer que implique la asignación directa del evento OnClick no funcionará. Lo que se podría hacer es crear un componente interceptor, es decir, algo con esta firma:

type 
    TButton = class(stdctrls.TButton) 

Vas a tener que reemplazar la propiedad OnClick para que el evento de escritura almacena el controlador de eventos en una lista interna, a disposición de clase.

property OnClick: TNotifyEvent read GetOnClick write SetOnClick; 

Luego, en el controlador SetOnClick solo podrá almacenar su controlador de eventos en la lista interna.

Ahora, tendrá que anular el procedimiento Click para que invoque cada delegado (cada controlador de eventos) sucesivamente.

procedure Click; override; 

Y eso lo hará.

Ten en cuenta que después de todo estarás subclasando la clase TButton, incluso si estás usando el mismo nombre ... De todos modos esa es la mejor solución que se me ocurre. Lo bueno de esto es que todavía se puede utilizar asignaciones sin tener que saber acerca de los acontecimientos encadenados, que sólo puede hacer:

MyButton.OnClick := MyHandler 

y va a encadenados de forma automática con el resto de controladores de eventos.

Cuestiones relacionadas