Manipulando objetos en tiempo de diseño

Todos sabemos que si en la ventana de comandos del Visual FoxPro escribimos algo como:

MODIFY FORM MAIN

estaremos creando o modificando un formulario llamado MAIN.SCX, al cual podremos cambiar el valor de sus propiedades por defecto, agregar nuevas propiedades, escribir código en sus métodos, crear nuevos métodos, agregar controles, y cambiar el valor de las propiedades y el código de esos controles.

Lo que muy pocos saben es que podemos realizar esas mismas tareas desde afuera de nuestro formulario. Tanto desde la ventana de comandos del Visual FoxPro como desde un archivo .PRG podríamos, si quisiéramos, también manipular a nuestro formulario y a todo lo que contiene.

¿Y por qué haríamos algo así?

Por dos motivos:

  1. Para que nuestras propias clases visuales, las que nosotros hemos creado subclasando a las clases originales del Visual FoxPro cambien su comportamiento en modo de diseño, y
  2. Para rápidamente asignarles propiedades y métodos a nuestro formulario, y a sus controles, ahorrando así mucho tiempo en el diseño

¿Qué se debe hacer para manipular a un formulario en tiempo de diseño desde afuera del formulario?

  1. Abrir al formulario con el comando MODIFY FORM, como siempre
  2. Abrir la ventana de comandos del Visual FoxPro
  3. Usar la función ASELOBJ() para convertir al formulario en un objeto

Captura 1. Después de abrir al formulario con el comando MODIFY FORM debemos abrir la ventana de comandos del Visual FoxPro

En la Captura 1. vemos lo que debemos hacer para que la ventana de comandos vuelva a estar visible.

Captura 2. La ventana de comandos nuevamente está visible

En la Captura 2. vemos que la ventana de comandos está visible y por lo tanto podemos escribir comandos y funciones en ella, si lo deseamos.

Captura 3. La función ASELOBJ() crea un array que tiene un solo elemento, que es el formulario que está abierto

En la Captura 3. usamos la función ASELOBJ() para crear un array que tiene un solo elemento. Ese elemento es una referencia al formulario que tenemos abierto. Aunque no es obligatorio hacerlo, asignamos esa referencia al formulario a una variable llamada loForm, ¿por qué? solamente para escribir menos y más entendible. A partir de ahora, en lugar de escribir laObjetos[1] podemos simplemente escribir loForm.

Es decir que escribir:

laObjetos[1].Caption

es idéntico a escribir:

loForm.Caption

Al autor de este blog le gusta más la segunda forma, por eso es que la utiliza. Resulta más fácil de entender.

Ahora, con la variable loForm tenemos acceso a todas las propiedades, todos los métodos, y todos los controles de nuestro formulario MAIN.SCX. Por ejemplo:

Captura 4. El formulario y todo lo que contiene puede ser manipulado desde la ventana de comandos.

Si comparas el formulario de la Captura 3. con el formulario de la Captura 4. verás que varias cosas han cambiado, y todos esos cambios se realizaron desde la ventana de comandos.

¿Y para qué nos sirve todo esto, en la práctica?

La principal utilidad es que puedes tener un archivo .PRG donde estableces todas las características que deseas que posea tu formularo. Cuando ejecutas a ese archivo .PRG desde la ventana de comandos ¡¡¡PUFFF!!! todas esas características se le asignaron a tu formulario. Y te ahorraste un montón de tiempo.

Listado 1. Cambiando las propiedades de un formulario desde un archivo .PRG

LOCAL loForm

  =ASelObj(laObjetos, 1) 

  loForm = laObjetos[1] 

  WITH loForm 
    .BackColor = Rgb(128, 255, 255) 
    FOR EACH loControl IN .CONTROLS 
      IF loControl.BaseClass = "Label" THEN 
        loControl.Alignment = 1 && Alineado a la derecha 
        loControl.AutoSize  = .F. 
        loControl.Left      = 25 
        loControl.Width     = 80 
      ENDIF
    ENDFOR
  ENDWITH
RETURN
*
*

Si teniendo abierto al formulario MAIN.SCX desde la ventana de comandos ejecutamos al programa mostrado en el Listado 1., esto será lo que obtendremos:

Captura 5. Cambiando al formulario desde un archivo .PRG

Como puedes ver en la Captura 5., nuestro formulario está distinto al formulario que veíamos en la Captura 4. Y todos esos cambios fueron realizados ejecutando un archivo .PRG

Asignando valores a las propiedades de nuestras clases, en tiempo de diseño

Algo que también nos puede resultar muy útil es asignar automáticamente valores a las propiedades de nuestras propias clases visuales, o sea las clases visuales que hemos creado después de subclasar a una de las clases nativas del Visual FoxPro.

Por ejemplo, todos los controles tienen las propiedades LEFT y WIDTH pero ninguno tiene la propiedad RIGHT. Eso, en tiempo de ejecución no es un problema porque RIGHT = LEFT + WIDTH, es muy sencillo de hallar. Pero ¿y si queremos conocer el RIGHT de un control en tiempo de diseño? Por supuesto que podríamos sumar su LEFT más su WIDTH pero perderíamos algo de tiempo haciendo esa suma (y si son muchos los controles, más tiempo desperdiciado). Una mejor alternativa es que el valor de la propiedad RIGHT sea asignado de forma automática. Por ejemplo:

CREATE CLASS BOTON_CON_RIGHT OF MISCLASES AS COMMANDBUTTON

Con el comando de arriba creamos una nueva clase, cuyo nombres será BOTON_CON_RIGHT, que se guardará en la biblioteca de clases llamada MISCLASES.VCX, y que estará basada en la clase COMMANDBUTTON.

A esta nueva clase le agregamos una propiedad llamada Right, para guardar en ella su posición a la derecha (la cual, como sabes, es la suma de Left + Width).

Luego, para que podamos usar a esta clase en nuestro formulario, escribimos:

SET CLASSLIB TO MISCLASES

A continuación, agregamos a nuestro formulario varios botones de la clase BOTON_CON_RIGHT, que acabamos de crear.

Captura 6. Le agregamos a nuestro formulario varios botones de la clase BOTON_CON_RIGHT, con distinto ancho cada botón

Y ahora queremos, en tiempo de diseño, alinear correctamente a todos esos botones de comando que acabamos de agregar, fijándonos que los anchos son distintos, pero queremos que la separación entre ellos sea siempre la misma. Para ello:

Listado 2. Alineando los botones en tiempo de diseño

LOCAL loForm, loControl, lnNumero, lcPropiedad, lnLeft, lnWidth, lnRight

  =ASelObj(laObjetos, 1)

  loForm = laObjetos[1]

  WITH loForm
    FOR EACH loControl IN .CONTROLS
      IF Upper(loControl.CLASS) == "BOTON_CON_RIGHT" THEN
        loControl.Top = 180
        .BOTON_CON_RIGHT1.Left  = 0
        .BOTON_CON_RIGHT1.Right = .BOTON_CON_RIGHT1.Left  + .BOTON_CON_RIGHT1.Width
        .BOTON_CON_RIGHT2.Left  = .BOTON_CON_RIGHT1.Right + 10
        .BOTON_CON_RIGHT2.Right = .BOTON_CON_RIGHT2.Left  + .BOTON_CON_RIGHT2.Width
        .BOTON_CON_RIGHT3.Left  = .BOTON_CON_RIGHT2.Right + 10
        .BOTON_CON_RIGHT3.Right = .BOTON_CON_RIGHT3.Left  + .BOTON_CON_RIGHT3.Width
        .BOTON_CON_RIGHT4.Left  = .BOTON_CON_RIGHT3.Right + 10
        .BOTON_CON_RIGHT4.Right = .BOTON_CON_RIGHT4.Left  + .BOTON_CON_RIGHT4.Width
        .BOTON_CON_RIGHT5.Left  = .BOTON_CON_RIGHT4.Right + 10
        .BOTON_CON_RIGHT5.Right = .BOTON_CON_RIGHT5.Left  + .BOTON_CON_RIGHT5.Width
      ENDIF
    ENDFOR
  ENDWITH

RETURN
*
*

Y si ejecutamos el código mostrado en el Listado 2. obtendremos:

Captura 7. Todos los botones quedaron separados la misma distancia y en tiempo de diseño.

Lo interesante de todo esto es que los botones quedaron alineados en tiempo de diseño. Hacer eso en tiempo de ejecución es muy fácil, casi cualquiera puede hacerlo, también es muy fácil si cambiamos los valores de las propiedades en la ventanita Properties. Pero aquí esos cambios los hicimos mediante un archivo .PRG y si comparas la Captura 6. con la Captura 7. notarás los cambios.

Conclusión:

Algo muy poco conocido pero muy útil es manipular a los formularios (y a todo lo que contienen) en tiempo de diseño desde la ventana de comandos o desde un archivo .PRG porque nos abre un sinfín de posibilidades, en este artículo se dio una pincelada.

Por ejemplo, podrías tener un archivo .PRG que tome como parámetro el nombre de una tabla y coloque a todas las columnas (campos) de esa tabla en un formulario, con la ubicación, el tipo de letras, y los colores que prefieras. Hacer todo eso manipulando controles en un formulario normalmente te tomaría varios minutos, en cambio si ya lo tienes codificado en un archivo .PRG sería cuestión de segundos.

Artículos relacionados:

El índice del blog VFPAvanzado