Sugerencias LISTBOX
Posted: Wed Jul 26, 2006 7:53 pm
Debido a mi peculiar forma de programar, me han surgido situaciones que me han obligado, como a muchos de vosotros supongo, a realizar moficiaciones en diversas Clases de FW, algunas de ellas al wBrowse, aunque al final optara por crear mis propios Browses. Me dispongo, por si a alguien le interesa, a exponer dos de tantas sugerencias que le van bien al WBrowse de FW. Son más largas de explicar que de comprender y llevar a cabo y constituyen una mejora razonable. Paciencia.
1) bPreChange
Para listados de personal me gusta desplegar un listbox con la ficha (Editable: con GET's) de la persona a su lado, de manera que a cada vez que cambio de línea en el listbox me cambian los datos en los Get's de la ficha correspondiente. Esto entraña varios problemas, el más importante es cuando cambio algún dato y después cambio de ficha pulsando alguna tecla o pinchando sobre otra línea del Listbox, todo ello sin haber guardado las modificaciones. Personalmente me gusta que el programa me pregunte si quiero guardar los datos antes de cambiar de ficha (lo típico "SI", "NO" "CANCELAR"). Se puede hacer si previamente has guardado el RECNO() de la ficha: preguntas si deseas volver y si le das a "CANCELAR" "Buscas" el RECNO(), y recuperas la ficha. Pero genaralmente el listbox parpadea de forma desagradable, el VSCroll se desplaza arriba y abajo y la línea en la que estaba el foco del Listbox cambia de lugar. Un efecto desagradable y poco profesional.
Lo solucioné con el CodeBlock ::bPreChange, más una variable lógica ::lContinue, La mecánica es bien simple:
hay que colocar ::lContinue := .T. al principio de los métodos 'KeyDown', 'LButtonDown' y 'VScroll' para que llegue como .T. a todos los métodos que implican movimiento del listbox. Después, en cada uno de esos métodos; GoUp(), GoDown(), GoTop(), Etc..., hay que hacer lo siguiente:
IF Se Puede Procesar Movimiento
IF bPrechange # NIL
EVAL(bPrechange, ... <VARIABLES A GUSTO DEL PROGRAMADOR> ...)
ENDIF
IF ::lContinue
...
PROCESAR MOVIMIENTO
...
IF bChange # NIL
EVAL(bChange,Self)
ENDIF
...
ENDIF
Ahora, cuando contestes "CANCELAR" con hacer oLbx:lContinue := .F. te quedas en la ficha pués el Listbox no se ha movido. Parece mucho, pero tan sólo supone una quincena de líneas (muchas repetidas) en el PRG (muy pocos minutos).
También sirve para cualquier otra acción que tengamos que realizar antes de cambiar de registro. Por ejemplo: oDBD:Save(), un repintado o refresco de pantalla, una consulta a tablas, pedidos, avisos, recordatorios, etc...
2) ::nMaxCol
La segunda propuesta, para quien haya aguantado el tostón, tiene que ver con la estética del Listbox. Es más accesoria. Se trata de especificar cuál va a ser la última columna visible más a la izquierda del listbox ¿?. Me explico. Normalmente, cuando pulsamos 'flecha derecha' o pinchamos sobre el HSCroll (en la parte derecha), las columnas del listbox se desplazan hacia la izquierda hasta llegar a la última. Amenudo esa ultima columna es la más estrecha y en esas condiciones ocupa todo el listbox (casi todo el listbox está en blanco). Con ::nMaxCol podemos hacer que esto no ocurra. Por ejemplo, supongamos que tengo 10 columnas para listar, pero se ven de tres en tres, me desplazo hacia la derecha hasta que la la octava columna está a la vista y pegada a la izquierda del listbox, aparecen así a la vista las columnas 8, 9 y 10. No necesito desplazarme más, para no perder la estética de pantalla. Si ::nMaxCol vale 8 (nº de la columna más a la izquierda del listbox), ya no se podría desplazar más. Esto me permitiría, además ocultar una posible onceava columna.
Solución:
Colocar ::nMaxCol := NUMERO MAXIMO DE COLUMAS. en los métodos NEW() y REDEFINE().
Por ejemplo en wBrowse ::nMaxCol := Len( GetColSizes() )
Después hay que establecer el rango del HSCroll: 'RANGE 1,::nMaxCol'
Finalmente en el Método GoRight() habrá que añadir, al principio del todo:
IF ::nColAct < ::nMaxCol // Significa que si la columna más a la izquierda no es menor que ::nMaxCol no se procesa GoRight()
...
RESTO DEL METODO TAL CUAL
...
ENDIF
Para aplicar duarante la programación, sencillamente:
REDEFINE oLbx ID .. OF oDlg ... FIELD ...
...
oLbx:nMaxCol := 8
Espero que sirva de algo.
Un saludo.
1) bPreChange
Para listados de personal me gusta desplegar un listbox con la ficha (Editable: con GET's) de la persona a su lado, de manera que a cada vez que cambio de línea en el listbox me cambian los datos en los Get's de la ficha correspondiente. Esto entraña varios problemas, el más importante es cuando cambio algún dato y después cambio de ficha pulsando alguna tecla o pinchando sobre otra línea del Listbox, todo ello sin haber guardado las modificaciones. Personalmente me gusta que el programa me pregunte si quiero guardar los datos antes de cambiar de ficha (lo típico "SI", "NO" "CANCELAR"). Se puede hacer si previamente has guardado el RECNO() de la ficha: preguntas si deseas volver y si le das a "CANCELAR" "Buscas" el RECNO(), y recuperas la ficha. Pero genaralmente el listbox parpadea de forma desagradable, el VSCroll se desplaza arriba y abajo y la línea en la que estaba el foco del Listbox cambia de lugar. Un efecto desagradable y poco profesional.
Lo solucioné con el CodeBlock ::bPreChange, más una variable lógica ::lContinue, La mecánica es bien simple:
hay que colocar ::lContinue := .T. al principio de los métodos 'KeyDown', 'LButtonDown' y 'VScroll' para que llegue como .T. a todos los métodos que implican movimiento del listbox. Después, en cada uno de esos métodos; GoUp(), GoDown(), GoTop(), Etc..., hay que hacer lo siguiente:
IF Se Puede Procesar Movimiento
IF bPrechange # NIL
EVAL(bPrechange, ... <VARIABLES A GUSTO DEL PROGRAMADOR> ...)
ENDIF
IF ::lContinue
...
PROCESAR MOVIMIENTO
...
IF bChange # NIL
EVAL(bChange,Self)
ENDIF
...
ENDIF
Ahora, cuando contestes "CANCELAR" con hacer oLbx:lContinue := .F. te quedas en la ficha pués el Listbox no se ha movido. Parece mucho, pero tan sólo supone una quincena de líneas (muchas repetidas) en el PRG (muy pocos minutos).
También sirve para cualquier otra acción que tengamos que realizar antes de cambiar de registro. Por ejemplo: oDBD:Save(), un repintado o refresco de pantalla, una consulta a tablas, pedidos, avisos, recordatorios, etc...
2) ::nMaxCol
La segunda propuesta, para quien haya aguantado el tostón, tiene que ver con la estética del Listbox. Es más accesoria. Se trata de especificar cuál va a ser la última columna visible más a la izquierda del listbox ¿?. Me explico. Normalmente, cuando pulsamos 'flecha derecha' o pinchamos sobre el HSCroll (en la parte derecha), las columnas del listbox se desplazan hacia la izquierda hasta llegar a la última. Amenudo esa ultima columna es la más estrecha y en esas condiciones ocupa todo el listbox (casi todo el listbox está en blanco). Con ::nMaxCol podemos hacer que esto no ocurra. Por ejemplo, supongamos que tengo 10 columnas para listar, pero se ven de tres en tres, me desplazo hacia la derecha hasta que la la octava columna está a la vista y pegada a la izquierda del listbox, aparecen así a la vista las columnas 8, 9 y 10. No necesito desplazarme más, para no perder la estética de pantalla. Si ::nMaxCol vale 8 (nº de la columna más a la izquierda del listbox), ya no se podría desplazar más. Esto me permitiría, además ocultar una posible onceava columna.
Solución:
Colocar ::nMaxCol := NUMERO MAXIMO DE COLUMAS. en los métodos NEW() y REDEFINE().
Por ejemplo en wBrowse ::nMaxCol := Len( GetColSizes() )
Después hay que establecer el rango del HSCroll: 'RANGE 1,::nMaxCol'
Finalmente en el Método GoRight() habrá que añadir, al principio del todo:
IF ::nColAct < ::nMaxCol // Significa que si la columna más a la izquierda no es menor que ::nMaxCol no se procesa GoRight()
...
RESTO DEL METODO TAL CUAL
...
ENDIF
Para aplicar duarante la programación, sencillamente:
REDEFINE oLbx ID .. OF oDlg ... FIELD ...
...
oLbx:nMaxCol := 8
Espero que sirva de algo.
Un saludo.