Ofertas de alojamiento 



Donativo para el sitio de elGuille

Buscar en Google y en elGuille.info:
Búsqueda personalizada

Ir al índice de Visual Studio 2008 y .NET Framework 3.5 Utilidades .NET Framework 3.5

gsBuscarTexto.Form1.vb

El código para Visual Basic del formulario principal

 
Publicado el 09/Dic/2007
Actualizado el 09/Dic/2007
Autor: Guillermo 'guille' Som

gsBuscarTexto.Form1: El código para Visual Basic del formulario principal.



 

Introducción:

Este es el código de Visual Basic para el formulario principal de la utilidad gsBuscarTexto.

 

'------------------------------------------------------------------------------
' gsBuscarTexto                                                     (07/Dic/07)
' Buscar ficheros según la especificación indicada y buscar texto en esos ficheros
'
' Basado en gsBuscar
'
' ©Guillermo 'guille' Som, 2007
'------------------------------------------------------------------------------
Option Strict On
Option Infer Off

Imports Microsoft.VisualBasic
Imports System
Imports System.Windows.Forms
Imports System.Drawing

Imports System.IO
Imports System.Diagnostics
Imports System.Collections.Generic

Public Class Form1

    Private cancelar As Boolean = False
    Private fechaAsignada As String
    Private dirExaminados As New List(Of String)

    ''' <summary>
    ''' Asignar a los datos de configuración
    ''' los contenidos de los controles y demás preferencias.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub guardarConfig()
        With My.Settings
            ' Los elementos de los combos se guardan como una cadena
            ' en la que se separa cada elemento de los combos con una barra vertical,
            ' esas cadenas las devuelven las propiedades que tiene el control de usuario.
            .ultimosDirectorios = OpcionesBuscar1.Directorios
            .ultimosFiltros = OpcionesBuscar1.Filtros
            .ultimosBuscar1 = OpcionesBuscar1.Buscar1
            .ultimosBuscar2 = OpcionesBuscar1.Buscar2
            .ultimosPoner1 = OpcionesBuscar1.Poner1
            .ultimosPoner2 = OpcionesBuscar1.Poner2

            ' Los valores individuales de cada opción
            .Directorio = OpcionesBuscar1.cboDir.Text
            .Filtro = OpcionesBuscar1.cboFiltro.Text
            .conSubDir = OpcionesBuscar1.chkConSubDir.IsChecked.Value
            .IgnorarError = OpcionesBuscar1.chkIgnorarErrores.IsChecked.Value
            .textoBuscar1 = OpcionesBuscar1.cboBuscar1.Text
            .textoBuscar2 = OpcionesBuscar1.cboBuscar2.Text
            .textoPoner1 = OpcionesBuscar1.cboPoner1.Text
            .textoPoner2 = OpcionesBuscar1.cboPoner2.Text
            .opcionBuscar = OpcionesBuscar1.cboTipoBuca.Text
            .chkFecha = OpcionesBuscar1.chkFecha.IsChecked.Value
            .chkBuscarTexto = OpcionesBuscar1.chkBuscar.IsChecked.Value
            .chkPoner = OpcionesBuscar1.chkPoner.IsChecked.Value

            ' Solo asignar la fecha si se ha cambiado desde que se asignó al iniciar
            ' (cuando está vacio el valor, se usa la fecha actual)
            If String.IsNullOrEmpty(OpcionesBuscar1.txtFecha.Text) = False _
            AndAlso fechaAsignada.CompareTo(OpcionesBuscar1.txtFecha.Text) <> 0 Then
                .Fecha = OpcionesBuscar1.txtFecha.Text
            End If

            ' Guardar la visibilidad de los Expander
            .expanderBuscarExpanded = OpcionesBuscar1.expanderBuscar.IsExpanded
            .expanderFicheroExpanded = OpcionesBuscar1.expanderFichero.IsExpanded

            ' Guardar el tamaño y posición del formulario,
            ' si está maximizado se guarda el valor de RestoreBounds
            If Me.WindowState = FormWindowState.Normal Then
                .Location = Me.Location
                .Size = Me.Size
            Else
                .Location = Me.RestoreBounds.Location
                .Size = Me.RestoreBounds.Size
            End If
            ' En Visual Basic (de forma predeterminada) no hace falta guardar los datos de configuración,
            ' pero por si se cambia en las propiedades del proyecto
            .Save()
        End With
    End Sub

    ''' <summary>
    ''' Al cerrarse el formulario principal,
    ''' se guadan los valores de configuración.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub Form1_FormClosing(ByVal sender As Object, _
                                  ByVal e As FormClosingEventArgs) _
                                  Handles Me.FormClosing
        guardarConfig()

        Me.OpcionesBuscar1.EnEjecucion = False
    End Sub

    ''' <summary>
    ''' Al cargarse (mostrarse) el formulario principal,
    ''' asignamos los valores de la configuración e inicializamos
    ''' el control de usuario
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub Form1_Load(ByVal sender As Object, _
                           ByVal e As EventArgs) _
                           Handles MyBase.Load
        Me.OpcionesBuscar1.EnEjecucion = True

        ' Asignar el manejador del evento ExpanderExpandedChanged
        AddHandler OpcionesBuscar1.ExpanderExpandedChanged, _
                   AddressOf OpcionesBuscar1_ExpanderExpandedChanged

        With My.Settings
            ' Si es la primera vez, tendrá un valor -1
            ' por tanto, solo asignar la posición y tamaño si ya se ha ejecutado antes
            If .Location.X > -1 Then
                Me.Location = .Location
                Me.Size = .Size
            End If

            ' Asignar los elementos de los combos por medio de las propiedades
            ' definidas en el control de usuario
            OpcionesBuscar1.Directorios = .ultimosDirectorios
            OpcionesBuscar1.Filtros = .ultimosFiltros
            OpcionesBuscar1.Buscar1 = .ultimosBuscar1
            OpcionesBuscar1.Buscar2 = .ultimosBuscar2
            OpcionesBuscar1.Poner1 = .ultimosPoner1
            OpcionesBuscar1.Poner2 = .ultimosPoner2

            '----------------------------------------------------------
            ' Como aún no está toda la funcionalidad no implementada,
            ' ocultamos o deshabilitamos los controles que no se deben
            ' tener en cuenta.
            '----------------------------------------------------------

            ' Esta opción aún no está implementada
            .expanderBuscarExpanded = False
            .chkBuscarTexto = False
            OpcionesBuscar1.chkBuscar.IsEnabled = False
            .textoBuscar1 = ""
            .textoBuscar2 = ""

            ' Esta opción aún no está implementada
            .chkPoner = False
            OpcionesBuscar1.chkPoner.Tag = False
            OpcionesBuscar1.chkPoner.IsEnabled = False
            .textoPoner1 = ""
            .textoPoner2 = ""

            ' Esta opción aún no está implementada
            .chkFecha = False
            OpcionesBuscar1.chkFecha.IsEnabled = False

            ' Asignamos el resto de opciones
            OpcionesBuscar1.cboDir.Text = .Directorio
            OpcionesBuscar1.cboFiltro.Text = .Filtro
            OpcionesBuscar1.chkConSubDir.IsChecked = .conSubDir
            OpcionesBuscar1.chkIgnorarErrores.IsChecked = .IgnorarError
            OpcionesBuscar1.cboTipoBuca.Text = .opcionBuscar
            OpcionesBuscar1.cboBuscar1.Text = .textoBuscar1
            OpcionesBuscar1.cboBuscar2.Text = .textoBuscar2
            OpcionesBuscar1.cboPoner1.Text = .textoPoner1
            OpcionesBuscar1.cboPoner2.Text = .textoPoner2
            OpcionesBuscar1.chkBuscar.IsChecked = .chkBuscarTexto
            OpcionesBuscar1.chkPoner.IsChecked = .chkPoner

            OpcionesBuscar1.chkFecha.IsChecked = .chkFecha
            ' Si la fecha está vacía, usar la fecha actual
            If String.IsNullOrEmpty(.Fecha) Then
                OpcionesBuscar1.txtFecha.Text = DateTime.Now.ToShortDateString
            Else
                OpcionesBuscar1.txtFecha.Text = .Fecha
            End If

            ' para saber si inicialmente .Fecha estaba vacio
            fechaAsignada = OpcionesBuscar1.txtFecha.Text

            OpcionesBuscar1.expanderBuscar.IsExpanded = .expanderBuscarExpanded
            OpcionesBuscar1.expanderFichero.IsExpanded = .expanderFicheroExpanded
        End With

        With My.Application.Info
            Me.LabelInfo.Text = .Title & " v" & .Version.ToString & " - " & .Copyright
        End With

        ' Los dos botones de abrir fichero o directorio
        ' solo deben estar habilitados si hay datos en el ListView
        Me.btnAbrirDir.Enabled = False
        Me.btnAbrirFic.Enabled = False
        Me.mnuFicAbrirFichero.Enabled = btnAbrirFic.Enabled
        Me.mnuFicAbrirDir.Enabled = btnAbrirDir.Enabled
    End Sub

    ''' <summary>
    ''' Cuando se pulsa en el botón de buscar.
    ''' Si ya se está buscando, se muestra cancelar,
    ''' con idea de cancelar la búsqueda (además de evitar la reentrada).
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnBuscar_Click(ByVal sender As Object, _
                                ByVal e As EventArgs) _
                                Handles btnBuscar.Click, mnuFicBuscar.Click

        ' Buscar de forma recursiva (si es necesario)
        Static yaEstoy As Boolean

        If yaEstoy Then
            cancelar = True
            Me.btnBuscar.Text = "Cancelando..."
            Application.DoEvents()
            Exit Sub
        End If
        yaEstoy = True

        ' Actualizar los contenidos de los combos
        ' (esto es para que se compruebe si el texto de cada combo
        ' está o no en la lista de elementos, si no está, se añade)
        OpcionesBuscar1.ActualizarCombos()

        ' Guardar los datos de configuración y estado de la ventana
        guardarConfig()

        Me.lvFics.Items.Clear()

        Me.LabelInfo.Text = "Buscando los ficheros..."
        Me.Cursor = Cursors.AppStarting
        Me.btnBuscar.Text = "Cancelar"
        Me.Refresh()

        ' Esta colección se usará para saber los directorios examinados
        ' con idea de que no se comprueben más de una vez
        ' (por ejemplo si se indica el mismo directorio más de una vez)
        dirExaminados.Clear()

        ' Como se pueden indicar varios directorios,
        ' creamos un array con cada uno de los valores que haya
        ' (esos valores estarán separados por punto y coma)
        Dim dirs() As String
        dirs = My.Settings.Directorio.Split(";".ToCharArray, StringSplitOptions.RemoveEmptyEntries)
        For Each d As String In dirs
            ' Antes de hacer nada, comprobar si se ha cancelado
            Application.DoEvents()
            If cancelar Then Exit For

            Try
                ' No comprobar los directorios vacios
                ' (por si se pone más de un punto y coma)
                If String.IsNullOrEmpty(d.Trim()) Then Continue For

                ' Crear un objeto del tipo DirectoryInfo con el directorio a examinar
                Dim di As New DirectoryInfo(d.Trim())

                ' Si no existe el directorio, pues nada que hacer
                ' aunque puede que no exista porque se haya indicado un fichero
                ' en ese caso, el valor de di.Attribute será FileAttributes.Archive
                If di.Exists = False _
                AndAlso di.Attributes = FileAttributes.Archive Then
                    di = New DirectoryInfo(Path.GetDirectoryName(di.FullName))
                End If
                If di.Exists Then
                    ' ¡Empieza el espectáculo!
                    ' Recorrer cada uno de los directorios principales indicados
                    ' en este método se comprueba si se debe buscar en los subdirectorios.
                    recorrerDir(di)
                End If

            Catch ex As Exception
                ' Si se produce un error, mostrarlo
                ' y preguntar si se quiere cancelar.
                If MessageBox.Show("Error: " & ex.Message & vbCrLf & _
                                   "¿Quieres cancelar la búsqueda?", _
                                   "Buscar ficheros", _
                                   MessageBoxButtons.YesNo, _
                                   MessageBoxIcon.Exclamation _
                                   ) = System.Windows.Forms.DialogResult.Yes Then
                    Exit For
                End If
            End Try
        Next

        ' Mostrar el resultado de la búsqueda
        Me.Cursor = Cursors.Default
        Me.btnBuscar.Text = "Buscar"

        ' Los botones de abrir fichero o directorio
        ' solo habilitarlos si hay algo en el ListView
        ' La asignación de los ficheros hallados se hace en esta comprobación,
        ' para mostrar un mensaje más adecuado al no hallar ficheros
        If Me.lvFics.Items.Count > 0 Then
            Me.LabelInfo.Text = "Se han hallado " & Me.lvFics.Items.Count.ToString("#,###") & " ficheros"
            Me.btnAbrirDir.Enabled = True
            Me.btnAbrirFic.Enabled = True
            Me.mnuFicAbrirFichero.Enabled = btnAbrirFic.Enabled
            Me.mnuFicAbrirDir.Enabled = btnAbrirDir.Enabled
        Else
            Me.LabelInfo.Text = "No se han hallado ficheros."
        End If

        Me.Refresh()

        cancelar = False

        yaEstoy = False
    End Sub

    ''' <summary>
    ''' Método recursivo para buscar en cada directorio,
    ''' se añadirá al ListView los ficheros hallados.
    ''' Aquí se comprueba si se debe seguir buscando en los subdirectorios,
    ''' si es así, se vuelve a llamar a este método.
    ''' </summary>
    ''' <param name="di">
    ''' Un objeto DirectoryInfo con el directorio a comprobar
    ''' </param>
    ''' <remarks></remarks>
    Private Sub recorrerDir(ByVal di As DirectoryInfo)
        ' Antes de hacer nada, comprobar si se ha cancelado
        Application.DoEvents()
        If cancelar Then Exit Sub

        ' Añadir al directorio a comprobar a la lista de directorios
        ' pero solo si no estaba ya.
        If dirExaminados.Contains(di.FullName.ToLower()) Then
            Exit Sub
        End If
        dirExaminados.Add(di.FullName.ToLower())

        Me.LabelInfo.Text = di.FullName & "..."
        Me.LabelInfo.Refresh()

        ' Las especificaciones de los ficheros a buscar estarán separadas por puntos y comas,
        ' crear un array con cada una de esas especificaciones.
        Dim especs() As String
        especs = My.Settings.Filtro.Split(";".ToCharArray, StringSplitOptions.RemoveEmptyEntries)

        Dim listaFics As New List(Of FileInfo)

        Try
            For Each espec As String In especs
                ' Asignar al array los ficheros de este directorio
                ' que concurdan con el filtro (especificación) indicada
                Dim fics() As FileInfo = di.GetFiles(espec.Trim(), SearchOption.TopDirectoryOnly)

                ' Si hay ficheros coincidentes, 
                ' agregarlos a la colección.
                ' Esto es para después usar lo que haya en la colección,
                ' de esa forma, estarán todos los ficheros que coincidan
                ' con las especificaciones (filtros) indicados.
                If fics.Length > 0 Then
                    listaFics.AddRange(fics)
                End If
            Next

            ' Añadir al ListView los ficheros que se hayan encontrado
            With Me.lvFics
                For Each fi As FileInfo In listaFics
                    Dim lvi As ListViewItem = .Items.Add(fi.Name)
                    lvi.SubItems.Add(fi.DirectoryName)
                Next
            End With

            ' Si se deben comprobar los subdirectorios
            If My.Settings.conSubDir Then
                ' obtener todos los subdirectorios
                ' y examinarlos llamando recursivamente
                ' a este mismo método
                Dim dirs() As DirectoryInfo = di.GetDirectories()
                For Each dir As DirectoryInfo In dirs
                    recorrerDir(dir)
                Next
            End If

        Catch ex As DirectoryNotFoundException
            ' Si el error es que no existe el directorio,
            ' mostrar el mensaje, independientemente del valor de la opción de ignorar errores
            If MessageBox.Show("Error, el directorio '" & di.FullName & "' " & vbCrLf & _
                               "no existe." & vbCrLf & _
                               "¿Quieres continuar?" & vbCrLf & _
                               "(pulsa NO para cancelar)", _
                               "Buscar en directorios", _
                               MessageBoxButtons.YesNo, _
                               MessageBoxIcon.Exclamation _
                               ) = DialogResult.No Then
                cancelar = True
                Application.DoEvents()
            End If

            'Catch ex As IOException
            '    ' Este error se producirá si en lugar de un directorio
            '    ' se ha indicado un fichero

        Catch ex As Exception
            ' Si se produce cualquier otro error y se ha indicado
            ' que se ignoren los errores, pues... se sigue...
            ' Normalmente esto se produce porque se accede a un fichero
            ' que está bloqueado o al que no se tiene autorización para accederlo.
            If My.Settings.IgnorarError Then
                Exit Sub
            End If

            ' Si se llega aquí es porque no está marcada la opción de ignorar errores
            ' y se da la oportunidad de que el usuario decida lo que quiere hacer.
            If MessageBox.Show("Error: " & ex.Message & vbCrLf & _
                               "¿Quieres continuar?" & vbCrLf & _
                               "(pulsa NO para cancelar)", _
                               "Buscar en directorios", _
                               MessageBoxButtons.YesNo, _
                               MessageBoxIcon.Exclamation _
                               ) = DialogResult.No Then
                cancelar = True
                Application.DoEvents()
            End If
        End Try

    End Sub

    ''' <summary>
    ''' Cuando se hace doble clic en un elemento del ListView
    ''' se comprueba si se ha pulsado en el nombre del fichero
    ''' o en el directorio, y así se hará una cosa u otra.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub lvFics_MouseDoubleClick(ByVal sender As Object, _
                                        ByVal e As MouseEventArgs) _
                                        Handles lvFics.MouseDoubleClick

        With lvFics
            If .SelectedIndices.Count = 0 Then
                Exit Sub
            End If

            ' Comprobar en que columna se ha hecho doble clic
            ' El valor de e.X es relativo al control,
            ' por tanto, no hace falta añadir nada más.
            If e.X < .Columns(0).Width Then
                ' El nombre

                ' Abrir el fichero indicado
                ' Combinar los paths para que se agregue el separador de directorio
                ' si así hiciera falta
                Dim fic As String = Path.Combine(.SelectedItems(0).SubItems(1).Text, _
                                                 .SelectedItems(0).SubItems(0).Text)
                Process.Start(fic)
            Else
                ' El directorio

                ' Abrir la ventana con el directorio del fichero indicado
                Dim dir As String = .SelectedItems(0).SubItems(1).Text
                Process.Start("explorer.exe", dir)
            End If

        End With
    End Sub

    ''' <summary>
    ''' Al pulsar en el botón Abrir Fichero, 
    ''' abrir el fichero del elemento seleccionado en el ListView
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnAbrirFic_Click(ByVal sender As Object, _
                                  ByVal e As EventArgs) _
                                  Handles btnAbrirFic.Click, mnuFicAbrirFichero.Click

        With lvFics
            If .SelectedIndices.Count = 0 Then
                Exit Sub
            End If

            ' Abrir el fichero indicado
            ' Combinar los paths para que se agregue el separador de directorio
            ' si así hiciera falta
            Dim fic As String = Path.Combine(.SelectedItems(0).SubItems(1).Text, _
                                             .SelectedItems(0).SubItems(0).Text)
            Process.Start(fic)

        End With
    End Sub

    ''' <summary>
    ''' Al pulsar en el botón Abrir directorio, 
    ''' abrir el directorio del elemento seleccionado en el ListView
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnAbrirDir_Click(ByVal sender As Object, _
                                  ByVal e As EventArgs) _
                                  Handles btnAbrirDir.Click, mnuFicAbrirDir.Click

        With lvFics
            If .SelectedIndices.Count = 0 Then
                Exit Sub
            End If

            ' Abrir la ventana con el directorio del fichero indicado
            Dim dir As String = .SelectedItems(0).SubItems(1).Text
            Process.Start("explorer.exe", dir)

        End With
    End Sub


    ''' <summary>
    ''' Operaciones de arrastrar y soltar (drag &amp; drop)
    ''' Esto es por si se suelta en cualquier parte del formulario
    ''' (no solo en el control de usuario)
    ''' </summary>
    ''' <remarks>
    ''' </remarks>
    Private Sub txtDir_DragDrop(ByVal sender As Object, _
                                ByVal e As DragEventArgs) _
                                Handles MyBase.DragDrop
        If e.Data.GetDataPresent("FileDrop") Then
            ' Para asignar solo el fichero/directorio soltado
            OpcionesBuscar1.cboDir.Text = CType(e.Data.GetData("FileDrop", True), String())(0)
        End If
    End Sub

    Private Sub txtDir_DragEnter(ByVal sender As Object, _
                                 ByVal e As DragEventArgs) _
                                 Handles MyBase.DragEnter
        ' Drag & Drop, comprobar con DataFormats
        If e.Data.GetDataPresent(DataFormats.FileDrop) Then
            e.Effect = DragDropEffects.Copy
        End If
    End Sub

    ''' <summary>
    ''' Evento del control cuando se ocultan o muestran los expander
    ''' </summary>
    ''' <remarks>
    ''' Debido a que el diseñador de Windows.Forms algunas veces da error
    ''' al usar los controles WPF, la asignación del evento lo hago manualmente
    ''' </remarks>
    Private Sub OpcionesBuscar1_ExpanderExpandedChanged() 'Handles OpcionesBuscar1.ExpanderExpandedChanged
        ' Actualizar el tamaño y la posición de lvFics según como estén los expanders

        ' Esto no es necesario, pero lo puse a ver porqué no daba los valores correctos...
        'Me.OpcionesBuscar1.gridFichero.UpdateLayout()
        'Me.OpcionesBuscar1.gridTexto.UpdateLayout()

        ' Calcular el alto, según esté visible o no cada grid de los expanders
        Dim gH As Double = 0.0
        If Me.OpcionesBuscar1.gridTexto.Visibility = Windows.Visibility.Visible Then
            gH += Me.OpcionesBuscar1.gridTexto.ActualHeight
        End If
        If Me.OpcionesBuscar1.gridFichero.Visibility = Windows.Visibility.Visible Then
            gH += Me.OpcionesBuscar1.gridFichero.ActualHeight
        End If
        ' El valor 41 es porque el control tiene 215 de alto
        ' y he calculado el valor que habría que sumar...
        ' que algunas veces por la cuenta la vieja también funcionan las cosas, ;-)))
        Dim opH As Integer = CInt(gH) + 41

        ' Los valores constantes son porque según el alto de 215 del control
        ' el lvFics tengrá .Top = 248 y .Height = 109
        Me.lvFics.Top = 37 + opH
        Me.lvFics.Height = Me.Height - opH - 137
        lvFics.BringToFront()
    End Sub

    ''' <summary>
    ''' Si se pulsa en la opción Salir del menú
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub mnuFicSalir_Click(ByVal sender As Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles mnuFicSalir.Click
        Me.Close()
    End Sub

    ''' <summary>
    ''' La opción de examinar (elegir el directorio) se hace usando el código del control de usuario
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub mnuFicExaminar_Click(ByVal sender As Object, _
                                     ByVal e As System.EventArgs) _
                                     Handles mnuFicExaminar.Click
        Me.OpcionesBuscar1.btnExaminarClick()
    End Sub
End Class

 

 


 


Cosas que te pueden interesar



Mentor de
SolidQ
Most Valuable Professional
MVP de .NET (antes Visual Basic)
de octubre de 1997 a septiembre de 2015



Orador internacional de Ineta
Orador de Ineta Latam

ir al índice del Guille


Escribir un mensaje al Guille (mensaje EN elGuille.info)
Has entrado usando el host: www.mundoprogramacion.com
Puedes verlo también en: http://www.elguille.info/net/vs2008/utilidades/gsbuscartexto_form1_vb.aspx