Como agregar código en tiempo de ejecución a un control creado en tiempo de ejecución.

3,235 views
Skip to first unread message

Miguel Ab

unread,
Jul 29, 2013, 1:17:15 PM7/29/13
to publice...@googlegroups.com
Hola.

Creo botones de forma dinámica en un formulario y necesito que cuando se pulsen en los mismos se lance un método que está en el formulario con un parámetro que depende de cada botón (puedo ponerlo y sacarlo del nombre del botón).

El código que meto en el Init del form es:

LOCAL boton AS String

boton="bMaquina001"
thisform.AddObject(boton,"CommandButton")
thisform.&boton..Caption = "Maquina 001"
thisform.&boton..Height = 16
thisform.&boton..Width = 170
thisform.&boton..FontSize = 8
thisform.&boton..FontName = "Arial"
thisform.&boton..Left = thisform.Width - thisform.&boton..Width - 10
thisform.&boton..Top = 10
thisform.&boton..Enabled = .T.
thisform.&boton..Visible = .T.
BINDEVENT(thisform.&boton, "Click", thisform, "msgshow_click")

boton="bMaquina002"
thisform.AddObject(boton,"CommandButton")
thisform.&boton..Caption = "Maquina 002"
thisform.&boton..Height = 16
thisform.&boton..Width = 170
thisform.&boton..FontSize = 8
thisform.&boton..FontName = "Arial"
thisform.&boton..Left = thisform.Width - thisform.&boton..Width - 10
thisform.&boton..Top = 30
thisform.&boton..Enabled = .T.
thisform.&boton..Visible = .T.
BINDEVENT(thisform.&boton, "Click", thisform, "msgshow_click")


Además tengo el método en el "msgshow_click":

LOCAL nMaquina AS String
nMaquina=RIGHT(ALLTRIM(this.Caption),3)
MESSAGEBOX("Probando probando "+this.Name+" "+nMaquina,0,"traza")


El problema es que cuando pulso los botones el objeto de referencia es el propio form y no el botón. ¿Hay alguna forma de que se sepa que botón lanzó el evento? ¿Alguna otra forma de hacer esto, controles de código dinámico y código dinámico para estos controloes?

No se si me he explicado bien.
Muchas gracias.
Saludos.

Ricardo Pina

unread,
Jul 29, 2013, 1:33:32 PM7/29/13
to Grupo VFP
Hola Miguel
 
Puedes "subclasear" un commandbutton y agregarle el método personalizado a esa clase, y solamente tendrías que realizar el addobject de esta clase.
 
Saludos
--
            

                   Ricardo Pina

Desarrollo y Servicios Informáticos

                  Profesionales
               www.dsip.com.ar

 

 

Ariel D'Alfeo

unread,
Jul 29, 2013, 1:41:23 PM7/29/13
to publice...@googlegroups.com
para agregar el evento en tu boton podes usar BINDEVENT("CommandButton","Click",THISFORM,metodo_formulario")
y en el evento del formulario pones esto:
LOCAL axEvt[1]
AEVENTS(axEvt, 0)


que te va a indicar desde que botón se lanzo el método.
y para saber por ejemplo el nombre del botón que lanzo el método seria:
axEvt[1,1].name


-- 
Ariel D'Alfeo
Córdoba, Argentina

Fernando D. Bozzo

unread,
Jul 29, 2013, 2:16:29 PM7/29/13
to publice...@googlegroups.com
Hola Miguel:

No sé por qué te complicás tanto usando BINDEVENT cuando lo que querés se puede hacer con una simple llamada de toda la vida.

cmdBotonX.Click()
THISFORM.msgshow_click( THIS )

Y ya está. Luego el método msgshow_click está recibiendo la referencia del objeto botón que lo llamó:

PROCEDURE msgshow_click( toBoton )
messagebix( "Soy el botón " + toBoton.Name )


Saludos.-

Ariel D'Alfeo

unread,
Jul 29, 2013, 2:46:32 PM7/29/13
to publice...@googlegroups.com
perdón por meterme, pero como se hace para poner este evento (con el parámetro) al botón en tiempo de ejecución?


cmdBotonX.Click()
THISFORM.msgshow_click( THIS )




-- 
Ariel D'Alfeo
Córdoba, Argentina

Fernando D. Bozzo

unread,
Jul 29, 2013, 3:11:57 PM7/29/13
to publice...@googlegroups.com
Se hace como dijo Ricardo Pina más arriba: Se hace una clase botón que tenga ese código dentro, y luego, al agregar instancias de ese botón al formulario en tiempo de ejecución (con addobject o similar), cuando se pulse se ejecutará el método programado. Así de simple.


Saludos.-



Fidel Charny

unread,
Jul 29, 2013, 5:07:14 PM7/29/13
to publice...@googlegroups.com
Aunque lo comentado por Ricardo y Fernando es más práctico, se puede mejorar algo el código.

*****************************
LOCAL boton AS String , lnatop
lnatop=10
FOR i=1 TO 2
boton="bMaquina"+PADL(i,3,"0")
Thisform.NewObject(boton,"CommandButton")
WITH thisform.&boton
.Caption = "Maquina "+PADL(i,3,"0")
.Height = 16
.Width = 170
.FontSize = 8
* .FontName = "Arial"      && por defecto
.Left = thisform.Width - .Width - 10
.Top = lnaTop
* .Enabled = .T.           && por defecto
.Visible = .T.
ENDWITH
lnatop=lnatop+20
BINDEVENT(thisform.&boton, "Click", thisform, "msgshow_click")
NEXT

*Metodo msgshow_click
***********************
LOCAL obj,nEvents
nEvents=AEVENTS(gaEvents,0)
IF nEvents=0
RETURN
ENDIF
obj=gaEvents[1]
MESSAGEBOX("Este el el botón "+obj.Name,0,"MsgShow_Click",2000)

Fernando D. Bozzo

unread,
Jul 29, 2013, 6:21:22 PM7/29/13
to publice...@googlegroups.com
Hola Fidel:

No es buena idea abusar de BINDEVENT cuando se puede lograr lo mismo de forma directa. El problema es que a la larga un sistema con bindeos es más complejo de analizar y de mantener. Ese mecanismo conviene reservarlo para abstracciones necesarias o más útiles, por ejemplo el ejemplo que le puse el otro día a Edgar Kummers sobre un programa (capa de negocio) que genera unas notificaciones a las que te podés suscribir desde un form con indicador de progreso (capa visual). En este caso se justifica, ya que la capa de negocio no debe depender de la capa visual, pero en este caso es todo capa visual.

Saludos.-

Fidel Charny

unread,
Jul 29, 2013, 7:14:40 PM7/29/13
to publice...@googlegroups.com
Hola Fernando:
No creas que soy un abusador. En la observación que hice en el hilo aprovechaba para quejarme de la macrosustitución, nada más porque me llama la atención que conociendo el nombre del objeto, lo ponga en una variable y luego recurra al &boton. 
Pero en realidad tengo un mal día. Me han abandonado las musas y ando por ahí contestando para el ranking... Y nunca me sobró habilidad, solo perseverancia.
En cuanto al tema, coincido totalmente. 
BindEvent() me resultó simpático y práctico para resolver algunas cuestiones en los controles grid.
Después tengo hecho para mí algunas tonterías basadas en BindEvent(). 

Muchas gracias
Fidel.

Fer

unread,
Jul 29, 2013, 7:22:59 PM7/29/13
to publice...@googlegroups.com

Lo siento Fidel :-(  espero que tu día mejore.

Un abrazo

Miguel Ab

unread,
Jul 30, 2013, 3:08:57 AM7/30/13
to publice...@googlegroups.com
Muchas gracias y en especial a Ariel.
Funciona.

Lo que quiero hacer es algo similar a esto:

LOCAL boton AS String
LOCAL i AS Integer

SET STEP ON

FOR i=1 TO 9 && esto vendrá de una tabla
    boton="bMaquina00"+TRANSFORM(i)
    thisform.AddObject(boton,"CommandButton")
    thisform.&boton..Caption = "Maquina 00"+TRANSFORM(i)

    thisform.&boton..Height = 16
    thisform.&boton..Width = 170
    thisform.&boton..Left = thisform.Width - thisform.&boton..Width - 10
    thisform.&boton..Top = 5 + i*20

    thisform.&boton..Enabled = .T.
    thisform.&boton..Visible = .T.
    BINDEVENT(thisform.&boton, "Click", thisform, "msgshow_click")
NEXT

Vamos crear un botón por registro que se tenga en la tabla y que cuando lo pulse se ejecute otro evento que dependerá del número de máquina que se trata ... por eso de sacar de algún sitio el botón que se trata.

Encontré esta página: http://msdn.microsoft.com/en-us/library/cszcy2ac%28v=vs.80%29.aspx  que creo que sería la forma correcta, pero esta forma "digamos" que modifica menos el código.

Y el caso es que la tabla tendrá muy pocos cambios (no se cambian máquinas todos los días), pero "quien paga manda".

Saludos.

Fernando D. Bozzo

unread,
Jul 30, 2013, 4:26:41 PM7/30/13
to publice...@googlegroups.com
Hola Miguel:

La página del MSDN que ponés tiene el mismo addobject que te había comentado en mi mensaje.
Me alegro que te haya servido.

Saludos.-



ZeRoberto

unread,
Jul 30, 2013, 8:31:46 PM7/30/13
to publicesvfoxpro
Creas una Class boton que en el evento click haga ThisForm.ButtonClick(This.ButtonID) y en el Metodo ButtonClick del Formulario haces esto

Procedure ButtonClick(tcButtonID)

   Do Case
        Case tcButtonID = '001'
        Case tcButtonID = '002'
        Case tcButtonID = '003'
   EndCase

Return


Saludos



Daniel Sánchez

unread,
Jul 31, 2013, 8:50:00 AM7/31/13
to Comunidad de Visual Foxpro en Español

Lo que te comentan que crees una subclase del commandbutton es la forma correcta cómo debes trabajar tu sub clase, ahí programas tu botón click colocando el código deseado, luego en tu formulario simplemente cambiarías el llamado de la clase deseada en lugar de instanciar el comandbutton instanciarias tu clase basada en el commandbutton, además en esta clase podrías adicionar propiedades a la clase creada, estas propiedades posteriormente al ser instanciadas le asignas sus valores correspondientes y así al ser presionadas podrías saber cual de los botones presionastes.

Saludos

Ariel D'Alfeo

unread,
Jul 31, 2013, 9:02:07 AM7/31/13
to publice...@googlegroups.com
Me alegro que te haya servido.

saludos


--
Ariel D'Alfeo
Córdoba, Argentina


Reply all
Reply to author
Forward
0 new messages