Mostrar los elementos de
un ListBox
mientras se escribe
Fecha: 31/Ago/97
Autor: Raúl Martinez
From: Raúl_Martínez_Castellanos [email protected]
Date sent: Fri, 29 Aug 1997 14:29:59 -0600
Hola chamacos :)
Estoy mejorando una aplicación y se me ocurrió cooperar un poco
con la
lista, y aprovechar de una vez para que Don Guille pueda tener
una
colaboración mía en su página. So, ahí les va.
Supongo que muchos de ustedes han visto o usado el API Text
Viewer (Visor
de Texto API) que viene con VB. A los que no lo han visto, está
entre las
opciones del menú que crea VB al instalarse, desde la versión
4.0. Bueno,
pues si lo han notado, en ese visor hay una lista que te muestra
las
declaraciones, constantes y tipos de datos del API de Windows. En
la lista
ésa, si empiezas a teclear "GetWi" por ejemplo, solita
se selecciona la
entrada "GetWindow" y la verdad, esa funcionalidad para
un usuario es SUPER
práctica, en especial si la lista es muy grande. La
funcionalidad estándar
de un ListBox estándar en Windows, sin embargo, no es así, sino
que cuando
tecleas la letra "G" se va al primer elemento que
inicie con "G", al
presionar la "E" se va al que empieza con
"E", y así... Y si quieres
moverte a través de los diferentes elementos que empiezan con
"G", debes
teclear la misma letra un chorro de veces. Es la funcionalidad
estándar y
bueno, pos así funciona, pero cuando tienes 150 elementos que
empiezan con
"G", y el que tu buscas es de los últimos, pos la
verdad te da hasta
flojera mantener la letra "G" presionada. Y eso la
verdad no es muy
práctico. So, componiendo la aplicación que les digo, preparé
una rutina
con la cual se puede puede implementar muy fácilmente la misma
funcionalidad. Todo lo que hay que hacer es llamarla desde el
evento
KeyPress y listo. :)
Pues bien. Modestia aparte, la rutina funciona super padre, por
lo que se
me ocurrió compartirla con ustedes para que la usen también en
sus
aplicaciones. La incluyo en un attach aparte como un documento de
texto, y
después de la rutina viene un ejemplo de cómo la uso yo en los
listbox de
mi aplicación. Si alguien tiene dudas, con gusto se las
resuelvo. La rutina
FUNCIONA COMPLETAMENTE tal y como está a partir de VB4-16Bits.
No la he
probado con VB3, pero creo que debería funcionar sin problema,
pues no hago
cosas muy complejas con ella en realidad. La mejor manera de
usarla y
sacarle jugo es llamándola desde un listbox que tenga la
propiedad .Sorted
= TRUE, porque así el tiempo de respuesta se optimiza
muchísimo, aunque
realmente no es muy lenta, pues todo lo hace sobre memoria. Ojo:
yo sé que
todavía se puede optimizar un poco más, pero como punto de
partida no tiene
ningún problema. Si alguien requiere que la optimizemos más, me
avisa y lo
hacemos con gusto
' ===================================================== ' Esta rutina se llama desde el keypress de un listbox, ' y se encarga de localizar el texto que va tecleando ' el usuario entre los elementos de la lista. ' ' Autor: Raúl Martínez Castellanos (yopi) ' [email protected] ' D.R. 1997, México, D.F. ' ' Se autoriza la reproducción libre de este código con ' cualquier fin, siempre que se incluya el presente ' comentario. ' ===================================================== Public Sub BuscaCadenaListBox(lstListBoxControl As ListBox, KeyAscii As Integer) ' Con esta constante defino el tiempo de espera ' (segundos) antes de vaciar la cadena de búsqueda Const TIEMPO_ESPERA As Single = 1 ' Estas variables estáticas almacenan la última vez ' que entré a la rutina y la cadena que ha tecleado ' el usuario Static ssngLastTime As Single Static sstrSearchString As String ' Variables locales Dim sngCurrentTime As Single Dim numListItem As Integer Dim numChars As Integer Dim lLastPosition As Long ' Determino cuánto tiempo ha pasado desde el último ' acceso a la rutina. Si es más que el predefinido, ' reinicializo la cadena de búsqueda. sngCurrentTime = Timer If Timer - ssngLastTime > TIEMPO_ESPERA Then sstrSearchString = "" ' Agregamos el caracter que se tecleó al string que ' se está buscando... sstrSearchString = sstrSearchString & UCase(Chr$(KeyAscii)) ' Determino cuántos caracteres estoy buscando numChars = Len(sstrSearchString) ' Procesamos el listbox usando WITH para agilizar el ' código y optimizar recursos With lstListBoxControl ' Guardamos la posición actual del listbox. ' Sólo es para evitar 'sorpresas' :) lLastPosition = .ListIndex ' Recoremos cada elemento del listbox en busca de ' la cadena que el usuario está tecleando... For numListItem = 0 To .ListCount - 1 ' Si el elemento de la lista inicia con la ' cadena que busco, cambio la posición del ' listbox y salgo del ciclo... If UCase(Left(.List(numListItem), numChars)) = sstrSearchString Then lLastPosition = numListItem Exit For End If ' Si la lista está ordenada (.Sorted = true), ' validamos que el elemento actual no sea mayor ' que el string que busco. De este modo, evito ' recorrer todos los elementos cuando ya no es ' posible encontrarlo If .Sorted Then If UCase(Left(.List(numListItem), 1)) > sstrSearchString Then ' Forzo el contador para salir del ciclo numListItem = .ListCount End If End If Next ' Si el contador es menor a .ListCount, es porque ' el elemento SÍ existe If numListItem < .ListCount Then ' Me coloco sobre el elemento encontrado .ListIndex = lLastPosition ' Antes de salir, muevo KeyAscii a cero, de ' modo que el proceso estándar del listbox ' no cambie de lugar la selección que hice KeyAscii = 0 Else ' Si no lo encontré, vacíamos el string de ' búsqueda. Al dejar KeyAscii como está, el ' proceso normal del listbox se va a encargar ' de desplazar mi cursor para seleccionar ' elementos... sstrSearchString = "" End If End With ' Antes de salir, actualizo mi hora de entrada a la ' rutina, de modo que siga usando la misma cadena ssngLastTime = sngCurrentTime End Sub ' ************************************************* ' EJEMPLO DE LA LLAMADA A LA RUTINA. Como verán, ' no tiene mayor chiste :) ' ************************************************* Private Sub List1_KeyPress(KeyAscii As Integer) ' Según lo que teclea es lo que hacemos Select Case KeyAscii Case 13 ' Enter ' Cuando presiona <Enter> en la lista, ' simulo un doble-click KeyAscii = 0 List1_DblClick Case 0 - 31 ' Caracteres de Control ' Los ignoro, pues no tienen mucho ' sentido en un list box Case Else ' Ajá!!! Anda buscando un texto... ' Vamos a ayudarlo :) BuscaCadenaListBox lstUsuarios, KeyAscii End Select End Sub