'EXPLORADOR DE IMÁGENES - perez987 (enero de 2019)

Imports System
Imports System.Windows.Forms
Imports System.Text
'Para manipular archivos gráficos
Imports System.Drawing
Imports System.Drawing.Imaging
'Para manipular directorios y ficheros
Imports System.IO
'Para iniciar y detener procesos del sistema local
Imports System.Diagnostics


Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Código generado por el Diseñador de Windows Forms "
#End Region

    '---------------------------------------------------------------------------------------
    'PROPIEDADES ESPECÍFICAS DEL LISTVIEW lvImg
    'necesarias para poder mostrar los elementos 
    'tal y como se muestran en esta aplicación:

    '1 - Añadir una columna
    'Me.lvImg.Columns.AddRange(New System.Windows.Forms.ColumnHeader()	{Me.ColumnHeader1})
    '2 - Asociar el control IMAGELIST iconImg a las propiedades LargeImageList, SmallImageList y StateImageList
    'Me.lvImg.LargeImageList = Me.iconImg
    'Me.lvImg.SmallImageList = Me.iconImg
    'Me.lvImg.StateImageList = Me.iconImg
    '3 - Propiedad view con el valor Details
    'Me.lvImg.View = System.Windows.Forms.View.Details
    '--------------------------------------------------------------------------------------

    'Para saber si la imagen está ajustada a la ventana o a tamaño real
    Dim ajustar As Boolean = False

    ' Variable para ser utilizada en el método btAbrir_Click
    Dim nombreImg As String = ""

    'Al cargar el formulario
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.CancelButton = Me.btSalir
        'rellenar el Combobox con las letras de unidad del sistema:
        'array de cadenas para contener los nombres de las unidades
        Dim drives() As String
        'rellenar el array con las unidades lógicas del sistema
        drives = System.Environment.GetLogicalDrives()
        'rellenar el Combobox dese el array
        Me.cbDrive.Items.AddRange(drives)
        'mostrar la letra de la primera unidad para que no arranque vacío el Combobox
        Me.cbDrive.SelectedItem = Me.cbDrive.Items(0)
        lbImg.Text = "No hay imagen en el PictureBox"
    End Sub

    'Al seleccionar un ítem del Combobox
    Private Sub CbDrive_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbDrive.SelectedIndexChanged
        Try
            'la clase DirectoryInfo expone métodos de instancia para _
            'crear, mover y enumerar archivos en directorios y subdirectorios;
            'se utiliza la clase DirectoryInfo para operaciones típicas como copiar, _
            'mover, cambiar de nombre, enumerar, crear y eliminar directorios.

            'obtener los directorios de la unidad seleccionada;
            Dim combo As New DirectoryInfo(Me.cbDrive.Text)
            Dim carpetas() As DirectoryInfo
            carpetas = combo.GetDirectories()
            'limpiar el Treeview
            tvDir.Nodes.Clear()
            'rellenar el Treeview con los nombres de los directorios;
            'TreeNode representa a los nodos del Treeview
            Dim carpetas2 As DirectoryInfo
            Dim nodo As TreeNode
            For Each carpetas2 In carpetas
                'el constructor de la clase Treenode inicializa una nueva instancia
                'aquí se usa con 1 solo parámetro pero se puede usar con 3:
                '1 - el texto de etiqueta especificado _
                '2 - la imagen que se ha de mostrar cuando el nodo de árbol esté
                'sin seleccionar (índice del Imagelist).
                '3 - la imagen que se ha de mostrar cuando el nodo de árbol esté
                'seleccionado (índice del Imagelist)
                nodo = New TreeNode(carpetas2.FullName)
                Me.tvDir.Nodes.Add(nodo)
            Next

            'Mostrar mensaje del error capturado
        Catch pollo As Exception
            MessageBox.Show("Mensaje de error: " & pollo.Message, "Error al leer la unidad " & cbDrive.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
            cbDrive.Text = "C:\"
        End Try

    End Sub

    'Al elegir un directorio en el Treeview
    Private Sub TvDir_AfterSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles tvDir.AfterSelect
        Try
            'si el nodo del árbol no está expandido
            If Not e.Node.IsExpanded Then
                'obtener los subdirectorios del nodo seleccionado
                Dim carpetas3 As DirectoryInfo
                carpetas3 = New DirectoryInfo(e.Node.FullPath)
                Dim carpetas4() As DirectoryInfo
                carpetas4 = carpetas3.GetDirectories()

                'rellenar el Treeview con los nombres de los subdirectorios;
                'TreeNode representa a los nodos del Treeview
                Dim subcarpetas As DirectoryInfo
                Dim nodo As TreeNode
                For Each subcarpetas In carpetas4
                    'el constructor de la clase Treenode inicializa una nueva instancia _
                    'aquí se usa con 1 solo parámetro pero se puede usar con 3: _
                    '1 - el texto de etiqueta especificado _
                    '2 - la imagen que se ha de mostrar cuando el nodo de árbol esté _
                    'sin seleccionar (índice del Imagelist).
                    '3 - la imagen que se ha de mostrar cuando el nodo de árbol esté _
                    'seleccionado (índice del Imagelist)
                    nodo = New TreeNode(subcarpetas.Name)
                    e.Node.Nodes.Add(nodo.Text)
                Next

                'obtener los archivos del subdirectorio
                Dim archivos() As FileInfo
                archivos = carpetas3.GetFiles()

                'limpiar el Listview
                Me.lvImg.Items.Clear()

                'rellenar el Listview con los nombres de los archivos
                'que cumplan la condición: terminar por las extensiones 
                'de archivos de imagen (se pueden cambiar las que aparecen aquí)
                Dim imagen As FileInfo
                For Each imagen In archivos
                    'a cada extensión se le puede asignar una imagen diferente eb el Imagelist
                    Select Case imagen.Extension
                        Case ".BMP", ".bmp", ".JPG", ".JPEG", ".jpg", ".jpeg", ".PNG", ".png", ".TIFF", ".tiff", ".TIF", ".tif"
                            Me.lvImg.Items.Add(imagen.Name)
                    End Select
                Next
            End If

            'si no hay elementos en el Listview, vaicar la caja de imagen
            If Me.lvImg.Items.Count = 0 Then
                Me.pbImg.Image = Nothing
                Me.lbImg.Text = "No hay imagen en el PictureBox"
            End If

            'Mostrar mensaje del error capturado
        Catch pollo As Exception
            MessageBox.Show("Mensaje de error: " & pollo.Message, "Error al leer imágenes ", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

    'al pulsar en un elemento del Listview (se produce el evento SelectedIndexChanged
    Private Sub LvImg_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lvImg.SelectedIndexChanged
        'procedimiento descrito más abajo
        Call RefrescarImg()
        'mostrar información sobre ancho y alto de la imagen seleccionada
        Me.lbImg.Text = "Ancho de imagen: " + pbImg.Image.Width.ToString +
          " px.  /  Alto de imagen: " + pbImg.Image.Height.ToString + " px"
    End Sub

    Private Sub RefrescarImg()
        Try
            'si hay algún elemento seleccionado en el Listview
            If Me.lvImg.SelectedItems.Count > 0 Then
                'invalidar la región gráfica del Picturebox para volver a rellenarla
                'con la imagen elegida en el control Listview
                Me.pbImg.Invalidate()
                Me.pbImg.Image = New Bitmap(Me.tvDir.SelectedNode.FullPath & "\" & Me.lvImg.SelectedItems(0).Text)
            End If

            'Mostrar mensaje del error capturado
        Catch pollo As Exception
            MessageBox.Show("Mensaje de error: " & pollo.Message, "Error al leer imágenes ", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    'Para copiar la imagen al protapapeles
    Private Sub BtCopiar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btCopiar.Click
        'para que solamente lo haga si hay imagen en la caja de imagen
        If Not pbImg.Image Is Nothing Then
            'función detallada en el siguiente bloque
            Call FnClipboard()
        End If
    End Sub

    'Función que devuelve un objeto desde el portapapeles.
    'La clase ClipBoard deriva de la clase Object y tiene 3 miembros:
    'constructor / GetDataObject / SetDataObject
    Private Function FnClipboard() As Object
        'Copiar imagen al portapeles
        'SetDataObject lleva 2 parámetros (objeto, booleano)
        'Si booleano es true, el objeto queda en el portapapeles
        'después de haber cerrado la aplicación
        Clipboard.SetDataObject(pbImg.Image, True)
        'Variable objClipboard para contener el portapeles
        Dim objClipboard As IDataObject = Clipboard.GetDataObject()
        'devuelve el portapapeles como mapa de bits
        Return objClipboard.GetData(DataFormats.Bitmap)
    End Function

    'Para mostrar la imagen a tamaño real o ajustado
    Private Sub BtAjustar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btAjustar.Click
        'para que solamente lo haga si hay imagen en la caja de imagen
        If Not pbImg.Image Is Nothing Then
            'si está a tamaño real centrada en el PictureBox, pasar a modo Ajustado
            If ajustar = False Then
                'pasar a modo Ajustada en el PictureBox
                pbImg.SizeMode = PictureBoxSizeMode.Zoom
                ajustar = True
            Else
                'pasar a modo Centrada en el PictureBox
                pbImg.SizeMode = PictureBoxSizeMode.CenterImage
                ajustar = False
            End If
        End If
    End Sub

    'Menú que voltea horizontalmente la imagen
    Private Sub BtFlip_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btFlip.Click
        'para que solamente lo haga si hay imagen en la caja de imagen
        If Not pbImg.Image Is Nothing Then
            pbImg.Image.RotateFlip(RotateFlipType.RotateNoneFlipX)
            pbImg.Refresh() 'Recarga la imagen
        End If
    End Sub

    'Para guardar el archivo en otro formato (BMP a JPG, JPG a BMP) o en otra carpeta
    Private Sub BtGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btGuardar.Click
        'para que solamente lo haga si hay imagen en la caja de imagen
        If Not pbImg.Image Is Nothing Then
            dlgSave = New SaveFileDialog
            dlgSave.Filter = "Mapas de bits (*.bmp)|*.bmp|Imágenes JPG (*.jpg)|*.jpg"
            dlgSave.Title = "Guarda la imagen como..."
            If dlgSave.ShowDialog() = Windows.Forms.DialogResult.OK Then
                nombreImg = dlgSave.FileName
                If (nombreImg.EndsWith("jpg")) Then
                    pbImg.Image.Save(nombreImg, ImageFormat.Jpeg)
                End If
                If (nombreImg.EndsWith("bmp")) Then
                    pbImg.Image.Save(nombreImg, ImageFormat.Bmp)
                End If
            End If
        End If
    End Sub

    'Salir de la aplicación
    Private Sub BtSalir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btSalir.Click
        Me.Close()
    End Sub

    'Para mostrar un cuadro de ayuda
    Private Sub BtAyuda_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btAyuda.Click
        'Información al usuario
        MessageBox.Show("Explorador de imágenes realizado en Visual Basic .NET." & vbCrLf & "Autor: perez987. Fecha: 09/01/2019.", "Acerca de...", MessageBoxButtons.OK)
    End Sub

    'Para mostrar el código vb del programa en una ventana del navegador web
    Private Sub BtCode_Click(sender As Object, e As EventArgs) Handles BtCode.Click
        'Obtener la ruta a la carpeta desde la que se ha iniciado la aplicación,
        Dim stRuta As String = Application.StartupPath

        Try ' para detectar y manipular excepciones (errores del programa)
            'ProcessStartInfo se utiliza para iniciar procesos
            Dim abrirDoc As ProcessStartInfo = New ProcessStartInfo
            'Añadir a la ruta "\Form1.txt" para abrir el archivo
            abrirDoc.FileName = stRuta + "\emiFotos 2.htm"
            'Información al usuario de la ruta obtenida en su sistema
            MessageBox.Show("El código del programa se muestra mediante una instancia del navegador. " +
                            "El archivo"" emiFotos 2.htm"" ha de estar junto al ejecutable del programa." +
                            vbCrLf + vbCrLf + "La ruta al archivo ""emiFotos 2.htm"" en tu sistema debería ser:" +
                            vbCrLf + abrirDoc.FileName, "Código Visual Basic", MessageBoxButtons.OK)

            'modo de apertura de archivo (también puede ser edit, print...)
            abrirDoc.Verb = "open"
            'abrir en ventana normal
            abrirDoc.WindowStyle = ProcessWindowStyle.Normal
            'Abrir el archivo mediante su programa asociado en Windows
            Process.Start(abrirDoc)

        Catch a As Exception 'Objeto Exception de nombre a
            'Mensaje relativo a la excepción lanzada
            MessageBox.Show("Se ha producido la siguiente excepción:" & vbCrLf & vbCrLf & a.Message, "Mensaje de error")
        End Try
    End Sub

End Class