Mostrar los elementos de un ListBox
mientras se escribe

Fecha: 31/Ago/97
Autor: Raúl Martinez


From: Raúl_Martínez_Castellanos yopi@hermes.uninet.net.mx
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)
'        yopi@mex1.uninet.net.mx
'        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

 

ir al índice