Navegador web en VB. NET (1)

Navegador Web usando la clase WebBrowser, configurando 2 idiomas diferentes (es-ES y en-US) que se guardan en My.Settings, cambiando de idioma sin reiniciar la aplicación, mostrando el código HTML de la página que se visita en un segundo formulario y almacenando el historial en un archivo de texto entre sesiones, en Visual Studio 2017

Resumen del ejercicio:

  • Aprender funcionalidades de Visual Basic .NET mostrando la clase WebBrowser que apareció por primera vez en .NET Framework 2, esta clase permite mostrar páginas web dentro de un formulario; ésto también era posible en .NET Framework 1 recurriendo al control OCX AxInterop.SHDocVw pero la facilidad de uso y la potencia de programación de la nueva clase es muy superior
  • Aprender a utilizar la función que permite configurar propiedades de aplicación (application settings) o de usuario (user settings) guardándolas en un archivo XML; aquí se emplea para guardar el tamaño y la posición que tiene la ventana principal al cerrarse para que, en el siguiente arranque, lo haga con idéntico aspecto
  • Leer (StreamReader) y escribir (StreamWriter) en un archivo de texto en el que se guarda el historial de páginas visitadas en la sesión para mostrarlas en un control ComboBox que hace la función de barra de direcciones.

Clase WebBrowser

La clase WebBrowser permite alojar páginas web y cualquier otro documento que pueda ser mostrado por un navegador web,en aplicaciones de Windows Forms. El control WebBrowser tiene propiedades, métodos y eventos que permiten la navegación como, por ejemplo:

  • Navigate
  • GoBack
  • GoForward
  • GoHome
  • Stop
  • Refresh
  • GoSearch

Los principales eventos que vamos a manejar son:

Navigating: ocurre cuando WebBrowser está navegando hacia el documento nuevo
Navigated: ocurre cuando WebBrowser ha navegado hasta el nuevo documento y ha comenzado a cargarlo, reemplazando al documento anterior
DocumentCompleted: ocurre cuando se ha completado la carga de la página.

Clase HtmlWindow

Representa la ventana lógica que contiene una o más instancias de HtmlDocument (WebBrowser.Document) y no se debe confundir con la ventana de Windows Form. HtmlWindow proporciona capacidades de alto nivel para conocer o manipular un documento web mostrado en un control WebBrowser.

HtmlWindow se puede usar para abrir ventanas nuevas que contienen documentos nuevos. El método Open() carga la URL especificada en la misma ventana mientras que el método OpenNew() abre la URL en una nueva ventana. La propiedad que contiene un objeto con las URL recientemente visitadas (historial) es HtmlWindow.History , contiene las URL por las que ha navegado el usuario desde la ventana actual y proporciona métodos para moverse entre esas páginas.

En este ejercico se ha preferido crear un historial propio en vez de mostrarlo desde History porque, a cambio de perder las funcionalidades de dicha propiedad, permite aprender a leer y escribir en un fichero de texto y a cargar ese fichero en un ComboBox.

Inicio del ejercicio

El control WebBrowser está incluido en la caja de herramientas en el apartado Controles Comunes. Para configurar datos de usuario hay que abrir las propiedades del proyecto y, en la pestaña Settings, añadir nombre, tipo, visibilidad (application o user) y valor asignado. Estos valores permanecen siempre como valores por defecto. En este ejercicio se han creado propiedades que guardan el valor en píxeles del tamaño y posición de la ventana además del idioma actual utilizado.

Esto se traduce en código XML que se guarda dentro del proyecto en el archivo app.config y más tarde, en tiempo de ejecución, en la configuración del usuario que corresponda, en la carpeta Documents and settings.

 <emi_Web.My.MySettings>
   <setting name="Anchura" serializeAs="String">
    <value>740</value>
   </setting>
   <setting name="Altura" serializeAs="String">
    <value>560</value>
   </setting>
   <setting name="Izquierda" serializeAs="String">
    <value>100</value>
   </setting>
   <setting name="Arriba" serializeAs="String">
    <value>100</value>
   </setting>
   <setting name="Ventana" serializeAs="String">
    <value>full_no</value>
   </setting>
   <setting name="Cultura" serializeAs="String">
    <value>es-ES</value>
   </setting>
   <setting name="urlIdioma" serializeAs="String">
    <value>about:blank</value>
   </setting>
   <setting name="cambioIdioma" serializeAs="String">
    <value>no</value>
   </setting>
  </emi_Web.My.MySettings>

Se accede a ellas mediante la clase MySettings usando la palabra clave My, es posible asignar su valor a la propiedad que se desea configurar:

'obtener los datos de la configuración guardada al cerrar el formulario por última vez
Select Case My.Settings.Ventana
	'si se configura para arrancar en ventana
	Case "full_no"
	    Me.Width = My.Settings.Anchura
	    Me.Height = My.Settings.Altura
	    Me.Left = My.Settings.Izquierda
	    Me.Top = My.Settings.Arriba
	    'si se configura para arrancar a pantalla completa
	Case "full"
	    Me.WindowState = FormWindowState.Maximized
End Select

Y también se puede modificar su valor y guardarlo al salir de la aplicación; el método específico que guarda la configuración es ChangeAndPersistSettings() pero también se puede utilizar en su lugar la opción Save My.Settings on shutdown de la pestaña Application en las propiedades del proyecto:

'método específico que guarda la configuración, también se puede utilizar en su lugar la opción
'<Save My.Settings on shutdown> de la pestaña Application en las propiedades del proyecto
Sub ChangeAndPersistSettings()
	'guardar las medidas de la ventana sólo si no está maximizada o minimizada
	'y si My.Settings.Ventana está configurado como "full_no"
	If (Me.WindowState = FormWindowState.Normal) AndAlso (My.Settings.Ventana = "full_no") Then
	    My.Settings.Altura = Me.Height
	    My.Settings.Anchura = Me.Width
	    My.Settings.Izquierda = Me.Left
	    My.Settings.Arriba = Me.Top
	End If
	'guardar la configuración
	My.Settings.Save()
End Sub

Rellenar el ComboBox desde un archivo de texto

Ya se ha dicho que, para mostrar las páginas visitadas, en vez de recurrir a la propiedad History el historial se guarda en un archivo de texto que se lee al arrancar la aplicación y desde allí se rellena el ComboBox que hace la función de barra de direcciones (si el archivo de texto no existe, la aplicación arranca con el ComboBox en blanco y, cuando se cierra, se crea el archivo de texto con el historial de las páginas visitadas en la sesión). Las distintas URL que van mostrándose en la barra de direcciones se van añadiendo al ComboBox sólo si no están ya incluidas en él; la dirección “about:blank” tampoco se añade a la lista.

'RELLENAR COMBOBOX DESDE EL ARCHIVO Historia.txt
'variable para cada línea del fichero de texto
Dim line As String
'si el fichero no existe -> no hacer nada (se creará uno al cerrar el programa)
If Not File.Exists(FILE_NAME) Then
	Return
Else
	'StreamReader representa un lector que puede leer una cadena secuencial
	'de caracteres desde un flujo de bytes, contiene al archivo de texto
	Dim sr As StreamReader
	sr = New StreamReader(FILE_NAME)
	'leer las líneas del archivo hasta el final
	Do
	    line = sr.ReadLine()
	    'si el texto de CbUrl no existe en el ComboBox, añadirlo a la lista
	    'pero sólo si la línea no está en blanco
	    Dim n As Integer
	    'FindString busca en ListBox y ComboBox sin distinguir mayúsculas y minúsculas,
	    'si encuentra el elemento buscado, devuelve el índice desde cero del elemento,
	    'si no lo encuentra devuelve -1
	    n = CbUrl.FindString(line)
	    'comprobación de que la línea no está en blanco,
	    'sin ella salta un error después de leer la última línea con texto
	    'porque la comprobación en el bucle Do...Loop Until está al final
	    If Not line Is Nothing Then
		If (n = -1) Then
		    CbUrl.Items.Add(line)
		End If
	    End If
	Loop Until line Is Nothing
	'cerrar StreamReader
	sr.Close()
End If

Guardar ComboBox en un archivo de texto

Al cerrar la aplicación se llama al método guardarArchivo() que vuelca el contenido del Combobox en un archivo de texto de manera que cada ítem de la lista sea una línea del texto:

'guardar el archivo de texto con el historial
Private Sub GuardarArchivo()
    Dim sw As StreamWriter
    '
    If File.Exists(FILE_NAME) Then
	'sobreescribir el texto (no añadirlo al existente)
	sw = New StreamWriter(FILE_NAME, False)
    Else
	'crear un archivo vacío
	sw = File.CreateText(FILE_NAME)
    End If
    'escribir los ítems de CbUrl al archivo de texto
    Dim i As Integer
    For i = 0 To (CbUrl.Items.Count - 1)
	sw.WriteLine(CbUrl.Items(i))
    Next
    sw.Close()
End Sub

Método Navegar()

Se crea un método Navegar que comprueba que la barra de direcciones no está en blanco ni contiene el texto “about:blank” y usa el método WebBrowser.Navigate para cargar el documento existente en la URL especificada, reemplazando al documento actual.

'método creado para el programa (no pertenece a la clase WebBrowser)
'usa el método WebBrowser.Navigate para cargar el documento
'existente en la URL especificada, reemplazando al documento actual
Private Sub Navegar(ByVal cadenaUrl As String)
	'comprobaciones sobre la cadena de URL
	If String.IsNullOrEmpty(cadenaUrl) Then Return
	If cadenaUrl.Equals("about:blank") Then Return
	If Not cadenaUrl.StartsWith("http://") And Not cadenaUrl.StartsWith("https://") Then
	    If cadenaUrl.StartsWith("www.") Then
		cadenaUrl = "http://" &amp; cadenaUrl
	    End If
	End If
	    'ir a la URL especificada
	    WbHtml.Navigate(New Uri(cadenaUrl))
End Sub

De manera que para ir a una URL determinada sólo que hay que llamar a ese método, pasando como parámetro el texto del ComboBox o una cadena con una URL válida.

'navegar a Google
Private Sub IrAGoogleToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles IrAGoogleToolStripMenuItem.Click
     Navegar("http://www.google.com")
End Sub

Métodos de navegación

Para ir a la página anterior: GoBack
Para ir a la página siguiente: GoForward
Para ir a la página de inicio: GoHome
Para detener la carga de la página: Stop
Para volver a cargar la página. Refresh
Para saber si se puede ir a página anterior o siguiente: CanGoBack y CanGoForward
Para obtener el texto de la barra de estado: StatusText
Para obtener el título del documento: DocumentTitle.ToString

Acerca de…

Visual Studio 2005 permitía añadir al proyecto (como un nuevo Windows Form) un cuadro de diálogo “Acerca de…” cuyo código ya prefabricado ahorraba mucho trabajo al programador. Esta función no aparece en Visual Studio 2017 pero he reciclado código de un diálogo antiguo de este tipo para usarlo en este ejercicio. El código obtiene algunos datos desde la información del ensamblado con Application.Info del objeto My. El campo largo Descripción se rellena desde 2 cadenas diferentes, una para cada idioma.

'al cargar el formulario, se rellenan los textos
Private Sub About_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' título del formulario
Dim ApplicationTitle As String
If My.Application.Info.Title <> "" Then
    ApplicationTitle = My.Application.Info.Title
Else
    ApplicationTitle = System.IO.Path.GetFileNameWithoutExtension(My.Application.Info.AssemblyName)
End If
Me.Text = String.Format(ApplicationTitle)
'Me.Text = String.Format("Acerca de... {0}", ApplicationTitle)
' Rellenar cuadros de texto desde la información del ensamblado
Me.LabelProductName.Text = My.Application.Info.ProductName
Me.LabelVersion.Text = String.Format("Version {0}", My.Application.Info.Version.ToString)
Me.LabelCopyright.Text = My.Application.Info.Copyright
Me.LabelCompanyName.Text = My.Application.Info.Trademark
'
'texto para substituir al campo Description del ensamblado
'es diferente según la cultura (idioma)
Dim s As String = "Application made with Visual Basic 2005 Express Edition, " &amp;
"using a control of the WebBrowser class, new in .NET Framework 2. The WebBrowser control " &amp;
"lets you host Web pages and other browser-enabled documents in your Windows Forms." &amp; vbCrLf &amp;
"The window size and location and other settings are saved as ""user-scoped settings"". " &amp;
"You can read a user setting by accessing the setting's property on the My.Settings object." &amp; vbCrLf &amp;
"The application can be added to the applications's list and the webbrowser's list " &amp;
"writing some keys in the Windows registry."
Select Case Form1.lengua.Substring(0, 2).ToLower()
    Case "es"
	Me.TextBoxDescription.Text = "Aplicación realizada con Visual Studio 2017, " &amp;
"utilizando un control de la clase WebBrowser. El control WebBrowser " &amp;
"permite incluir páginas web en formularios de Windows." &amp; vbCrLf &amp;
"El tamaño y la posición cuando se cierra la ventana, así como algunas otras opciones de " &amp;
"configuración, se guardan como configuraciones " &amp;
" de usuario (""user-scoped settings"")." &amp; vbCrLf &amp;
"Estos datos se leen desde un archivo de configuración al cargar el formulario." &amp; vbCrLf &amp;
"La aplicación se puede añadir a la lista de aplicaciones y de navegadores del sistema " &amp;
"escribiendo en el registro de Windows."
    Case Else
	Me.TextBoxDescription.Text = s
End Select
End Sub

Segunda parte >>