FoxPress – Septiembre 2000

 

Una Clase Grid sencilla y genérica para seleccionar registros con DBlClick

http://www.fpress.com/                                   miGrid.ZIP (N.R.: Tienes que cambiar un path del INICIO.PRG)

 

 

En cierta ocasión me propuse hacer una clase Grid que fuera genéico. Me explico, que le pasara una tabla o el resultado de una select en un cursor al Grid y me mostrara todos los campos o parte de ellos (los que en cada caso me interese) y que cuando el usuario hiciera doble click en la línea que le interesase el Grid se cerrara devolviendo el número o el contenido del registro seleccionado.

 

 

La principal dificultad la encontraba en el doble click pues parecía que el Grid no se enteraba de que estaba pulsando sobre uno de los Textbox.

 

En la KB (Q128075) vi que esa forma de comportarse según Microsoft era por diseño no es que se tratara de un error o de un fallo de programación.

 

Microsoft dice “Este comportamiento es por diseño. Un objeto Grid es un contenedor de columnas. Las columnas contienen controles. Los métodos definidos en un Container no inhieren en la jerarquí del container. Por ejemplo, el código que incluyas en el evento Click de un formulario no se ejecuta cuando haces click en un botón de comandos.

 

Cuando un Grid se llena con datos y haces click en una celda del Grid, el contro, un textbox, por defecto, recibe el evento click. El Grid recibe el evento Grid en lugares que no contienen datos”.

 

Microsoft también apunta dos formas de solucionarlo:

 

a.- Poner un Shape encima del Grid pero eso no me permite saber en qué celda se ha hecho click.

 

b.- Escribir el contenido del Click en el textBox base: ¡Este es el camino!

 

Vista la idea, me puse en marcha e hice lo siguiente:

 

1.- Creo una clase Formulario y la llamo MiForm

2.- Creo una clase TextBox y la llamo MiText

3.- Creo una clase Grid y la llamo MiGrid

 

¿Pero, cómo pongo mi clase MiText dentro de MiGrid pues aparentemente no hay forma? Después de dar muchas vueltas a la KB vi que la forma de hacerlo es por código: tengo que quitar el TextBox por defecto y poner MiText mediante código y eso hay que hacerlo en el INIT de la clase MiForm.

 

¿Pero cómo sé cuantas columnas va a tener el Grid? Si pones un Grid con el número de columnas columncount a –1 al abrirlo crea tantas columnas como campos tenga la tabla seleccionada.

 

Luego el proceso tendrías que ser:

 

a)                       Abrir una tabla

b)                       Cargar un formulario con un Grid con el ColumnCount puesto a –1

c)                       En el Init del Formulario (ten en cuenta que ya se ha cargado el Init del Grid) debo averiguar cuantas columnas tiene el Grid y quitarle el textbox standard y cargar el mio personalizado

 

¿Pero cómo sé cuantas columnas tiene un Grid?

 

Si escribes:

 

*- Tienes que tener una tabla seleccionada *- antes de

*- lanzar este código:

 

AMEMBERS(laTemp, THISFORM.miGrid, 2)

FOR EACH oColumn IN laTemp

  ? oColumn

ENDFOR

 

Puedes averiguar cuantas columnas tiene el Grid añadiendole un contador y su nombre que es lo que en este caso te devuelve.

 

De acuerdo, ya sé cómo contar las columnas de un Grid. ¿pero, como quito el textBox estándar y pongo mi clase TextBox personalizada?. Para eso el código anterior deberías modificarlo un poco y escribir:

 

AMEMBERS(laTemp, THISFORM.miGrid, 2)

FOR EACH oColumn IN laTemp

  WITH THISFORM.Grid1.&oColumn

              .RemoveObject('Text1')

                   .ADDOBJECT('NewText', 'miText')

              .NewText.VISIBLE = .T.

              .SPARSE = .F.

              .CURRENTCONTROL = 'NewText'

  ENDWITH

ENDFOR

 

Mmm... Esto empieza a estar interesante! ¿pero hasta ahora no hemos hecho nada del DblClick de la clase MiText y además me parece que no se pueden escribir métodos en tiempo de ejecución! Esto es un poco relativo, sí que se pueden, pero no es la materia de este artículo. En el método DblClick de la clase TextBox pondremos la acción que queremos que se ejecute y esa acción la pondremos en una propiedad:

 

Escribe en el método DblClick del TextBox el siguiente código:

 

LOCAL lcExp

 

lcExp = THIS.lcAccionEjecutar

 

IF NOT EMPTY(lcExp)

  *- Ejecuta la orden

  &lcExp

ENDIF

 

Y modifica el código del Init del Form por el siguiente:

 

FOR EACH oColumn IN laTemp

        WITH THISFORM.miGrid.&oColumn

                    lcVarUna = laTituloColum(contador)

              .ADDOBJECT('NewText', 'miText')

              .NewText.VISIBLE = .T.

              .SPARSE = .F.

              .CURRENTCONTROL = 'NewText'

              .NewText.lcAccionEjecutar = 'THISFORM.Release()'

  ENDWITH

ENDFOR

 

Y con esto ya casi tenemos todo. Como no es mucho voy a trascribir todo el código para lanzar la clase anterior para que se vea bien. De todos modos en los fuentes tienes el ejemplo completo y te bastará con ejecutar el programa de Inicio.prg  para ver su funcionamiento.

 

***** INICIO.PRG *********************

CLOSE ALL

CLEAR ALL

set defau to e:\foxpress\sep00\art1\

set classlib to selectora

 

*- Guarda en una variable el area

*- seleccionada actual para

*- cerrar volver a recuperarla

lcSelec = SELECT()

 

*- Nombre que le vamos a poner a las columnas

LOCAL ARRAY laCabecera(2)

              laCabecera(1) = 'Código'

              laCabecera(2) = 'Nombre 1'

 

*- Campos a mostrar      

Select * from tabla1 into cursor _TmpCursor

 

*- Activamos el Cursor

select _Tmpcursor

 

*- Instanciamos la clase miForm

frmMyForm = CREATEOBJECT("miform", @laCabecera)

 

frmMyForm.SHOW()

 

RELEASE frmMyForm

 

*- Mostramos el campo seleccionado

? _tmpCursor.campo1

 

USE IN _TmpCursor

USE IN tabla1

 

*- recupearamos tabla original seleccionada

SELECT(lcSelec)

 

  Y ya lo tienes. Mira los fuentes para ver el ejemplo en funcionamento.. El resto queda para tu imaginación.

 

  ¡Espera, espera...! ¿Y si el usuario pulsa Enter en vez de hacer DobleClik? Pues deberías codificar el KeyPress de la clase base del Textbox.

 

  ¿ Y si la Tabla o cursor tiene muchos registros y quiero seleccionar uno entre ellos? Para eso necesitaríamos otro artículo que quizás venga en el próximo número: de momento basta con esto.

         

 

 

 

FoxPress – Septiembre de 2000

© 2000 FoxPress. All rights reserved