Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 30-07-2014
Avatar de hgiacobone
hgiacobone hgiacobone is offline
Miembro
 
Registrado: may 2003
Ubicación: La Plata, Bs. As., Argentina
Posts: 165
Poder: 21
hgiacobone Va por buen camino
Question Evento OnClick en runtime

Tal vez sea la pregunta del millón...
¿ Cómo disparar dinámicamente (runtime) un evento OnClick ?

Ejemplo:
Tenemos un procedimiento que en runtime crea un formulario, un Memo y un Boton.
El fin de esto, es que, el usuario final escriba algo en el Memo y al hacer clic en el Boton lo pueda enviar a imprimir o a realizar otro tipo de tarea (en este caso no importa mucho).
El código es similar a esto:
Código Delphi [-]
procedure TForm1.MostrarFormularioDinamico;
var
  DebugForm: TForm;
  memo1: TMemo;
  Btn1: TButton;
  Pnl1: TPanel;
begin
    DebugForm:= TForm.Create(self);
    DebugForm.Width:= Trunc(Self.Width/2);

    Pnl1:= TPanel.Create(DebugForm);
    Pnl1.Parent:= DebugForm;
    Pnl1.Align:= alBottom;

    Btn1:= TButton.Create(DebugForm);
    Btn1.Parent:= Pnl1;
    Btn1.OnClick:= ClickMe; //<----este es el problematico

    memo1:= Tmemo.Create(DebugForm);
    memo1.Parent:= DebugForm;
    memo1.Align:= alClient;
    memo1.ScrollBars:= ssBoth  ;

    DebugForm.Show;
end;

Por lo general, el evento se declara en el formulario principal, en su sección privada y funciona correctamente (mientras se haga referencia a componentes, procedimientos, variables, etc, que sean visibles al TForm principal):
Código Delphi [-]
type
  TForm1 = class(TForm
  ...
  ...
  private
    procedure ClickMe(Sender : TObject);
  published
  end;

El problema reside es que a este evento no lo puedo asignar a un procedimiento "pre-declarado" ya que hace referencia y uso de elementos que se crean dinámicamente tal como el TMemo.
Tampoco fue posible dispararlo con un procedimiento local, al estilo:
Código Delphi [-]
procedure TForm1.MostrarFormularioDinamico;
var
  DebugForm: TForm;
  memo1: TMemo;
  Btn1: TButton;
  Pnl1: TPanel;
      
      procedure ClickMe(Sender: TObject);
      var
        s: string;
      begin
            try   
              s:= memo1.Text;
              ...
              ...
            except
              on E:Exception do MessageDlg(E.Message, mtWarning, [mbOk],0);
            end;
      end;

begin
    DebugForm:= TForm.Create(self);
    DebugForm.Width:= Trunc(Self.Width/2);

    Pnl1:= TPanel.Create(DebugForm);
    Pnl1.Parent:= DebugForm;
    Pnl1.Align:= alBottom;

    Btn1:= TButton.Create(DebugForm);
    Btn1.Parent:= Pnl1;
    Btn1.OnClick:= ClickMe; 

    memo1:= Tmemo.Create(DebugForm);
    memo1.Parent:= DebugForm;
    memo1.Align:= alClient;
    memo1.ScrollBars:= ssBoth  ;

    DebugForm.Show;
end;

¿ Alguien tiene alguna aproximación para su solución ?
__________________
Gracias de antemano por vuestra ayuda.
·.:*:.·Yako·.:*:.·
Responder Con Cita
  #2  
Antiguo 30-07-2014
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Asignando nombres a los componentes y usando FindComponent no debería ser difícil.
POdría ser una primera forma sin muchas complicaciones.

Código Delphi [-]
procedure TForm1.MostrarFormularioDinamico;
var
  DebugForm: TForm;
  memo1: TMemo;
  Btn1: TButton;
  Pnl1: TPanel;
begin
    DebugForm:= TForm.Create(self);
    DebugForm.Width:= Trunc(Self.Width/2);
    DebugForm.Name := 'FormException';

    Pnl1:= TPanel.Create(DebugForm);
    Pnl1.Parent:= DebugForm;
    Pnl1.Align:= alBottom;
    Pnl1.Name := 'pnl1';

    Btn1:= TButton.Create(DebugForm);
    Btn1.Parent:= Pnl1;
    Btn1.Name := 'Btn1';
    Btn1.OnClick := ClickMe; //<----Ahora ya no da problemas  ;-)

    memo1:= Tmemo.Create(DebugForm);
    memo1.Parent:= DebugForm;
    memo1.Align:= alClient;
    memo1.ScrollBars:= ssBoth  ;
    memo1.Name := 'memo1';

    DebugForm.Show;
end;

En el evento ClickMe puedes hacer algo así (no he puesto comprobaciones de error):

Código Delphi [-]
procedure TForm1.ClickMe(Sender: TObject);
var
  s: string;
  f:TForm;
  m:TMemo;
begin
  try
    f := TForm(TComponent(Sender).Owner);
    m := TMemo(f.FindComponent('memo1'));
    s := m.Text;

    MessageDlg(Format('Se ha pulsado el botón en el Formulario: %s'+
                      #13+#10+'En el Memo hay lo siguiente:'+#13+#10+
                      '----------------------------------------------'+
                      #13+#10+'%s'+#13+#10+'----------------------------------------------',
                      [f.Name, m.Text]), mtInformation, [mbOK], 0);

  except
    on E:Exception do MessageDlg(E.Message, mtWarning, [mbOk],0);
  end;
end;

Un saludo.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #3  
Antiguo 30-07-2014
Avatar de hgiacobone
hgiacobone hgiacobone is offline
Miembro
 
Registrado: may 2003
Ubicación: La Plata, Bs. As., Argentina
Posts: 165
Poder: 21
hgiacobone Va por buen camino
Cita:
Empezado por Neftali Ver Mensaje
...POdría ser una primera forma sin muchas complicaciones.
Esa es muy buena querido Neftali... lo voy a probar en la semana.
Es una lástima que haya que "duplicar" los componentes en variables locales en el segundo procedimiento para poder trabajarlos, pero al menos, algo es algo...
Saludos cordiales,
__________________
Gracias de antemano por vuestra ayuda.
·.:*:.·Yako·.:*:.·
Responder Con Cita
  #4  
Antiguo 31-07-2014
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola hgiacobone.
Cita:
Empezado por hgiacobone Ver Mensaje
...Es una lástima que haya que "duplicar" los componentes en variables locales en el segundo procedimiento para poder trabajarlos, pero al menos, algo es algo...
Creo que Neftali escribió el código de ese modo para hacerlo mas claro y didáctico, pero es posible prescindir totalmente de las variables locales al método ClickMe:
Código Delphi [-]
procedure TForm1.ClickMe(Sender: TObject);
begin
  try
    MessageDlg(Format('Se ha pulsado el botón en el Formulario: %s'+
                      #13+#10+'En el Memo hay lo siguiente:'+#13+#10+
                      '----------------------------------------------'+
                      #13+#10+'%s'+#13+#10+'----------------------------------------------',
                      [TForm(TComponent(Sender).Owner).Name,
                       TMemo(TForm(TComponent(Sender).Owner).FindComponent('memo1')).Text]),
                       mtInformation, [mbOK], 0);

  except
    on E:Exception do MessageDlg(E.Message, mtWarning, [mbOk],0);
  end;
end;
Fijate que lo único que hice, fué reemplazar los nombres de variables por los moldeos y funciónes que estaban en el el ejemplo de Germán. En lo personal, me parece que usar las variables locales da un código mas eficiente y menos propenso a confusiones y errores.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....

Última edición por ecfisa fecha: 31-07-2014 a las 09:19:34.
Responder Con Cita
  #5  
Antiguo 31-07-2014
Avatar de ozsWizzard
ozsWizzard ozsWizzard is offline
Miembro
 
Registrado: may 2004
Ubicación: Murcia
Posts: 190
Poder: 20
ozsWizzard Va por buen camino
Estoy con ecfisa. , no sé que tiene de malo usar variables.
__________________
La Madurez se llama...
~~~Gaia~~~
Responder Con Cita
  #6  
Antiguo 31-07-2014
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por hgiacobone Ver Mensaje
Es una lástima que haya que "duplicar" los componentes en variables locales en el segundo procedimiento para poder trabajarlos, pero al menos, algo es algo...
Tal y como ha comentado ecfisa, la definición de esas variables está principalmente para "clarificar" el código (sobre todo en este caso que mostraba un ejemplo de uso). No es obligatoria.

De todas yo habitualmente lo uso, por varias razones.
Lo pimero que hay que aclarar es que "no está duplicando componentes" simplemente estás creando variables que apuntan a ellos, por lo tanto no estás "duplicando" nada, y esas variables (no los componentes) se liberan al salir de ese procedimiento.
Por otro lado, tal y como he dicho, si se utilizara ese método, habría que añadir comprobaciones de seguridad de este tipo, cosa que se facilita/simplifica si defines la variables:

Código Delphi [-]
  ...
  // Si el owner está asignado
  if Assigned(TComponent(Sender).Owner ) then begin  
    // es un tForm?
  if (TComponent(Sender) is TForm) then begin
    TForm(TComponent(Sender).Owner).FindCom('memo1') ...
    
    ...
    // Asignar valor
    TMemo(TForm(TComponent(Sender).Owner).FindComponent('memo1')).Text := ...

Por último (personalmente) la estética de este código no me gusta, me "choca", es poco legible para un programador que llegue detrás tuyo a revisarlo, además de que soy "vago" y no me gusta escribir de más de la cuenta. Además cuantas más cosas vas poniendo en el código más tienes que repetir esos "churros".
Es algo personal, pero yo prefiero definir un par de variables y que el código se parezca al que he puesto anteriormente.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Evento onclick en Dbctrlgrid Choclito OOP 2 13-05-2013 00:30:31
evento onclick del button richard187 OOP 8 08-04-2008 04:01:59
evento OnClick de un TRichEdit aranel OOP 4 01-12-2005 11:43:28
Evento OnClick vtdeleon OOP 4 08-08-2005 23:40:18
Evento onClick jzk OOP 4 27-10-2004 18:46:02


La franja horaria es GMT +2. Ahora son las 16:09:53.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi