Page 1 of 1

Sugerencias LISTBOX

Posted: Wed Jul 26, 2006 7:53 pm
by manuramos
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.

Posted: Thu Jul 27, 2006 7:51 am
by StefanHaupt
Can please anyone translate this long text into english ?

Stefan

Posted: Thu Jul 27, 2006 11:17 am
by manuramos
Excuse me Stefan but my english is very bad. It's difficult to me to explain it.
they are two sugests for wBrowse or others owner browses.

1) ::bPreChange

Basically is a CodeBlock to be evaluate before any listbox movement (before changing database record). For example if I have a listbox with a personnel editable card next to it, if I make changes in the record and I click into the listbox withgout saving changes, with this codeblock I could ask user if he want to save them: typical "YES","NO","CANCEL" questions. If I click "CANCEL", with ::bPreChange listbox doesn't move and I could stay it.

To perform it, I need ::bPreChange and ::lContinue logical variable. We must place ::lContinue := .T. at top of 'KeyDown', 'LButtonDown' and 'VScroll' methods to enter all listbox movement methods with .T. value. After that, we'll change GoUp(), GoDown(), GoTop(), Etc..., methods in this way:

METHOD ....

IF I can process movement

IF bPrechange # NIL
EVAL(bPrechange, ... <ANY USEFFULL VARIABLES> ...)
ENDIF

IF ::lContinue
...
OLD METHOD CODE
...
IF bChange # NIL
EVAL(bChange,Self)
ENDIF
...
ENDIF

This is useffull for all actions we need to execut before changing the listbox focus row, like: oDBD:Save(), display refresh or repainting, consulting tables, indexes, warning, advertisments, etc...

2) ::nMaxCol

Imagine you want to list 10 columns with a listbox, but only three of them are visibles at time. If you right scorll the listbox you can consecutively see all the columns (three at each time). When you reach the last one, there is the only one displayed, it occupies all the listbox (nearly a blank listbox). However, when the 8, 9 and 10 columns are displayed (at time) you don't need to right scroll the listbaox yet. This woul be the ::nMaxCol := 8 performence (8 means: the most left visible column). With that, you also could hide a posible eleventh column.

To do it:

FIrst: put, in NEW .and. REDEFINE methods: ::nMaxCol := MAX NUMBER OF COLUMNS. in FW wBrowse: ::nMaxCol := Len( GetColSizes() )

Second: define the HSCroll range like this : 'RANGE 1,::nMaxCol'

Third: In GoRight method type:

IF ::nColAct < ::nMaxCol // It means if most left visible column is less than ::nMaxCol then GoRight() it doesn't process.
...
GORIGHT USUAL METHOD
...
ENDIF
I hope you coul understand it

Regards

Posted: Thu Jul 27, 2006 2:42 pm
by Detlef Hoefner
Manuramos,

your English is much, much better than the English of Babelfish translation service.

Sometimes, if i want to read some humorous text i give a Spanish message from the forum to babelfish.
Then i make a first translation into English and after again a translation from this English to German.

The result is always very funny and surrealistic :lol: .

So, many thanks for your translation work which allows me to understand your posting.

Best regards,
Detlef

Posted: Thu Jul 27, 2006 7:44 pm
by manuramos
A lot of thanks for your encourageous words Detlef. I have a goud dictonary...

Posted: Fri Jul 28, 2006 7:33 am
by StefanHaupt
Manuramos,

as Detlef said, your English is very good.

Thank you very much for your translation.

Have a nice weekend.

Stefan

Posted: Mon Aug 07, 2006 7:44 pm
by James Bott
Mauramos,

>Basically is a CodeBlock to be evaluate before any listbox movement

Have you tried using a bSkip codeblock? Example:

oLbx:bSkip:={|nRecs| myFunction(), oDBF:skipper( nRecs ) }

This way you can call myFunction() before the listbox skips to the next record.

James

Posted: Wed Aug 09, 2006 3:04 pm
by manuramos
You are right James. I know it. But WBrowe use ::bSkip in its SetFilter method, then you couldn't use it with filters and/or scopes.

However, if you want to use it, look that ::bSkip is evaluated in the Skip() method, then you should control all the skips mouvements of the browse, because all mouvements methods call ::Skip( x ) one or more times and continue without noticing a posible ::Skip's return value.

:bPreChange .and. ::lContinue would be exclusive to skipper events. I think.

Posted: Wed Aug 09, 2006 3:47 pm
by James Bott
Manuramos,

>You are right James. I know it. But WBrowe use ::bSkip in its SetFilter method, then you couldn't use it with filters and/or scopes.

I see. I don't use those, I use ordScope() and dbsetFilter() instead. I don't know if there is some advantage to using the ones in TWBrowse. I think those were originally developed because NTXs didn't have scopes, but now they do.

James