Una de las ventajas de la programación orientada a objetos es que resulta fácil enlazar o relacionar a un objeto con otro objeto. Lo único que se necesita es que el objeto controlador tenga una referencia al objeto controlado. Si tiene esa referencia entonces podrá acceder a todas las propiedades y a todos los métodos del objeto controlado.
¿Y por qué haríamos algo así?
Una de las utilidades es poder modificar la apariencia o el comportamiento de un formulario o de cualquiera de sus controles sin cambiar casi nada del código fuente ni del formulario ni de los controles contenidos en ese formulario. En general, además de agregar el control controlador al formulario lo único que deberemos hacer es llamar a uno de los métodos de ese control en el método INIT() de nuestro formulario. Y ya está.
Ejemplo. Mostrando mensajes cuando el usuario hace clic derecho en un «Header»
Primero. Creamos la clase:
CREATE CLASS MOSTRAR_TOTALES OF CONTROLES AS CUSTOM
No necesariamente nuestra nueva clase debe estar basada en CUSTOM, puede estar basada en cualquier otra clase, nativa o no nativa del Visual FoxPro, por ejemplo podría ser: COMBOBOX, COMMANDBUTTON, LABEL, LISTBOX, TEXTBOX, etc. Y la biblioteca de clases puede tener cualquier nombre, aquí se usó CONTROLES pero tú puedes darle cualquier otro nombre que prefieras.
Segundo. Le agregamos algunas propiedades a la nueva clase
Como en este caso queremos que nuestra nueva clase modifique el comportamiento de una grilla entonces le agregamos las propiedades:
- cNombreGrilla
- oGrilla
En la propiedad cNombreGrilla escribiremos el nombre de la grilla que será controlada. Por ejemplo: «ThisForm.Grid1»
En la propiedad oGrilla tendremos una referencia a la grilla que será controlada.
Tercero. Le agregamos algunos métodos a la nueva clase
En este ejemplo los métodos son:
- BOTON_DERECHO()
- CONFIGURAR()
El método BOTON_DERECHO() se enlazará mediante la función BINDEVENT() con el método RightClick() de cada «Header» de la grilla.
El método CONFIGURAR() será llamado desde el método INIT() del formulario y realizará todas las tareas de inicialización necesarias.
Listado 1. El método CONFIGURAR()
LOCAL loColumna, lcHeader, loHeader
IF !EMPTY(This.cNombreGrilla) THEN
This.oGrilla = EVALUATE(This.cNombreGrilla)
ELSE
This.oGrilla = .NULL.
RETURN
ENDIF
FOR EACH loColumna IN This.oGrilla.Columns
lcHeader = "This.oGrilla." + loColumna.Name + ".Header1"
loHeader = EVALUATE(lcHeader)
=BINDEVENT(loHeader, "RightClick", This, "BOTON_DERECHO")
ENDFOR
RETURN
*
*
Este método primero guarda en la propiedad oGrilla una referencia a la grilla que será manipulada. Eso nos permitirá acceder a todas las propiedades y a todos los métodos de esa grilla. Luego enlaza el método RigthClick() de cada «Header» de la grilla con el método BOTON_DERECHO() de nuestra clase controladora. ¿Para qué? para que así podremos escribir código en el método BOTON_DERECHO() y ese código se ejecutará cuando el usuario haga clic derecho sobre cualquiera de los «Header».
O sea que, sin tocar para nada a la grilla, podremos manipularla según nuestros deseos.
Listado 2. El método BOTON_DERECHO()
LOCAL ARRAY laHeader[1, 1]
LOCAL loHeaderActual, loColumnaActual, lcControlSourceActual, lcVarTypeActual
LOCAL lnRecNo, lnSumaColumna
=AEVENTS(laHeader, 0)
loHeaderActual = laHeader[1]
loColumnaActual = loHeaderActual.Parent
lcControlSourceActual = loColumnaActual.ControlSource
lcVarTypeActual = VARTYPE(EVALUATE(lcControlSourceActual))
DO CASE
CASE lcVarTypeActual == "C"
=MESSAGEBOX("Hmmmm...no puedo totalizar una columna de tipo carácter")
CASE lcVarTypeActual == "D"
=MESSAGEBOX("No sé como totalizar a las fechas")
CASE lcVarTypeActual == "L"
=MESSAGEBOX("Vaya...hay valores lógicos en esta columna")
CASE lcVarTypeActual == "N" .OR. lcVarTypeActual == "Y"
lnRecNo = RECNO()
SUM EVALUATE(lcControlSourceActual) TO lnSumaColumna
IF lnRecNo <= RECCOUNT() THEN
GO lnRecNo
ENDIF
=MESSAGEBOX("La suma de la columna " + loColumnaActual.NAME + " es: " + TRANSFORM(lnSumaColumna))
OTHERWISE
=MESSAGEBOX("Aún no sé como procesar este tipo de variables")
ENDCASE
RETURN
*
*
En este método lo primero que hacemos es llamar a la función AEVENTS(). Esa función crea un array que contiene el objeto que desencadenó al último evento. ¿Por qué se la usa? porque nosotros sabemos que el usuario hizo clic derecho sobre un «Header», por eso se llamó al método BOTON_DERECHO() pero ¿en cual de los «Header» hizo clic derecho? ¿el de la columna 1, el de la columna 2, el de la columna 3, …?
Ahora podremos saberlo porque al tener una referencia al «header» que desencadenó el último evento podremos averiguar en cual columna está ese «header» simplemente accediendo a su parent.
Y si tenemos una referencia a la columna correcta también tenemos acceso a todas las propiedades y a todos los métodos de esa columna. Por ejemplo podemos saber el nombre del campo guardado en la propiedad ControlSource.
Y si sabemos cual es el campo que está guardado en la propiedad ControlSource entonces averiguar cual es el tipo de datos (carácter, fecha, lógico, numérico, etc.) de ese campo ya es muy fácil
Como puedes ver, controlar a un objeto (una grilla en este ejemplo) desde otro objeto no es complicado. Solamente debemos tener una propiedad (oGrilla en este ejemplo) que haga referencia al objeto que será controlado.
En uno de los formularios que puedes descargar más abajo se agregaron una grilla y un controlador de esa grilla.
En un formulario puede haber varias grillas, ¿cómo sabe el objeto controlador a cual de esas grillas debe controlar? pues ese dato lo especificamos en la propiedad cNombreGrilla.
El resultado de llamar a ese formulario, y hacer clic derecho sobre uno de los «Header» lo podemos ver a continuación:
Lo súper interesante de la Captura 3. es que nada de nada se tocó en la grilla. Se modificó su comportamiento sin agregarle nada al código fuente de sus métodos ni se cambió el valor de alguna de sus propiedades.
¿Te das cuenta de lo poderoso que eso es?
Significa que puedes cambiar la apariencia o la funcionalidad de cualquiera de tus formularios sin necesidad de cambiar algo en ellos, simplemente le agregas un objeto controlador, en el método INIT() de tu formulario llamas a un método de ese objeto controlador y listo, eso es todo.
Y si no te gusta el resultado obtenido, eliminas al objeto controlador que pusiste en tu formulario y quedó todo exactamente como estaba antes.
La cantidad de posibilidades es inmensa, ahora queda a tu cargo obtener buen provecho de esta técnica.
Conclusión
Poder controlar a un objeto (o a muchos objetos) sin tocarlo, sin cambiar nada en sus métodos ni en sus propiedades nos permite muchísimas posibilidades.
Por ejemplo, podríamos agregar funcionalidades personalizadas para cada usuario. En una tabla guardamos sus preferencias, nuestro objeto controlador lee y establece esas preferencias, y así cada usuario tiene lo que desea tener.
O podríamos agregar un módulo que solamente estará disponible para los clientes que nos paguen por ese módulo. Si pagan, se lo habilitamos, si no pagan no se lo habilitamos. El que no paga no verá cambios, todo continuará igual para él. En cambio el que sí pagó tendrá algo nuevo a su disposición. Y si debe pagar en cuotas y está atrasado con sus cuotas, le podremos fácilmente deshabilitar u ocultar ese módulo. Nuestro objeto controlador se encargará de esas tareas.
Descargas
Puedes descargar un archivo .ZIP que contiene dos archivos .PRG, dos formularios, y una biblioteca de clases desde:
https://www.mediafire.com/file/8g2vwyeuav9edob/CONTROLAR+A+UN+OBJETO+DESDE+OTRO+OBJETO.zip/file
Hay 2 archivos .PRG porque hay 2 ejemplos. Para probarlos, en la ventana de comandos del Visual FoxPro escribe:
DO EJEMPLO1
DO EJEMPLO2
Artículos relacionados