Une visionneuse d'image en VB.NET

1. October 2010 by Jordan.BERTHELEMY

 

Introduction :

Cet article va vous apprendre comment créer une visionneuse d’image en VB.NET. Pour ceux qui ne sauraient pas ce qu’est une visionneuse d’image, voici celle de Windows. A la fin de ce TP nous devrions avoir un résultat similaire.

Objectifs de cet article :

-          Créer des contrôles et des évènements

-          Créer un menu

-          Lister les fichiers présents dans un dossier

-          Imprimer une image

-          Copier une image dans le presse-papier

-          Supprimer un fichier

-          Faire pivoter une image

 

Première étape : Création du projet

La première étape consiste à créer un nouveau projet Visual Basic - Windows Form Application. Donnez-lui le nom de votre choix, moi j’ai choisi ImageViewer. Ce projet a été réalisé à l’aide de Visual Studio 2010 Ultimate.

Vous devriez voir un onglet appelé Form1.vb [Design]. A l’intérieur se trouve une fenêtre nommée Form1. Dans ses propriétés changez les attributs Name et Text pour ImageViewer et mettez l’attribut Size à 800 ; 600.


Deuxième étape : Création des contrôles

Pour créer un menu, utilisez le MenuStrip de la boîte à outils et insérez le dans la fenêtre. Créez le sous-menu Fichier qui contient les options : Ouvrir,  Copier, Imprimer, Supprimer et Quitter.

Ensuite il faut ajouter des boutons. Il en faut six : Suivant, Précédent, Diaporama, Rotation Gauche, Rotation Droite et Supprimer. Tous les boutons sont placés dans un Panel. Mettez la propriété Visible du Panel à False pour éviter que les boutons soient visibles lorsqu’aucune image n’est affichée dans la PictureBox Il faut également ajouter une PictureBox au milieu de la fenêtre. La propriété SizeMode de la PictureBox doit être à StretchImage.

Pour mettre des images dans les boutons, rendez-vous dans les Propriétés du projet (Projet, Propriétés de ImageViewer) puis dans Ressources. Ajoutez-y les images que vous souhaitez utiliser. Celles qui apparaissent sur les captures d’écran proviennent d’IconFinder. Ensuite il suffit de modifier la propriété Image des boutons.

Pour afficher des informations sur les boutons il faut créer un ToolTip et modifier la propriété « Tooltip sur NomDeVotreTooltip » de chacun des boutons.


Troisième étape : Création d’une classe Viewer

Une fois tous les contrôles créés, ajoutez une Classe au projet. Pour cela, clic droit sur le projet, Ajouter, Classe. Appelez cette classe Viewer et ajoutez-y deux régions, une pour les attributs de la classe et l’autre pour les méthodes. Les régions ne sont en aucun cas nécessaires mais elles permettent de mieux organiser le code.

Vous devriez avoir quelque chose de ce type :

Public Class Viewer

#Region “Attributs”
#End Region

#Region “Méthodes”
#End Region

End Class

Cette classe contient deux attributs : tabImages qui est une liste contenant des liens absolus vers les images présentes dans le même dossier que l’image ouverte et current qui contient le numéro de l’image affichée.

#Region “Attributs”

Private tabImages As New ArrayList 'Liste contenant un lien absolu vers toutes les images présentes dans le dossier

                Private current As Integer 'Numéro de l'image affichée
#End Region

 

La fonction GetFiles :

Une fonction Getfiles existe déjà mais ne permet pas de lister les fichiers d’un répertoire en fonction de plusieurs extensions.

Public Function GetFiles(ByVal repertoire As String, ByVal extensions As String()) As String()

        Dim fichiers As List(Of String) = New List(Of String)()

        For Each extension As String In extensions

fichiers.AddRange(IO.Directory.GetFiles(repertoire, extension, IO.SearchOption.TopDirectoryOnly))

        Next

        Return fichiers.ToArray()

    End Function

 

 

Cette fonction accepte plusieurs paramètres : une chaine de caractères indiquant le chemin vers le répertoire dont veut lister les fichiers ainsi qu’un tableau de chaines de caractères. Ce tableau contient la liste des extensions qu’il faut prendre en compte. Elle renvoi un tableau de chaines de caractères qui sont les noms des fichiers dont les extensions correspondent à celles présentes dans le tableau. Pour chaque extension du tableau cette fonction va appeler la méthode GetFiles de la classe Directory.

IO.SearchOption.TopDirectoryOnly signifie que seuls les fichiers présents dans le répertoire actif sont listés et pas ceux des sous-répertoires.

Vous pouvez commenter les fonctions, pour cela ajoutez ''' (3 apostrophes) au dessus de la fonction. Vous devriez voir apparaitre les lignes ci-dessous.

    ''' <summary>

    '''

    ''' </summary>

    ''' <param name="parametre1"></param>

    ''' <param name="parametre2"></param>

    ''' <returns></returns>

    ''' <remarks></remarks>

Il suffit ensuite d’ajouter du texte entre les balises.

 

Le constructeur :

Le constructeur est une méthode qui est appelée au moment où un objet est créé, cette méthode a pour but d’initialiser les attributs de l’objet. Ici, le constructeur ne prendra aucun paramètre.

Sub New()

                For Each image As String In GetFiles(IO.Directory.GetParent(ImageViewer.OpenImage.FileName).FullName,{"*.jpg", "*.jpeg", "*.png", "*.gif", "*.bmp"})

                               tabImages.Add(image)

                Next

                               current = tabImages.IndexOf(ImageViewer.OpenImage.FileName)

                               Afficher_image(current)

End Sub

Le constructeur appelle la fonction GetFiles que vous avez créée plus tôt pour lister tous les fichiers ayant pour extension jpg, jpeg, png, gif ou bmp présents dans le même répertoire que l’image que l’utilisateur décide d’ouvrir. Chaque image du tableau renvoyé par la fonction GetFiles est ajoutée dans tabImages. Current prend pour valeur l’index de l’image ouverte par l’utilisateur.

 

La méthode Afficher_image :

    Public Sub Afficher_image(ByVal num_image As Integer)

        Try

            ImageViewer.PB_Image.Image = Image.FromFile(tabImages(num_image))

            Redim_image()

        Catch

            tabImages.RemoveAt(num_image)

            current += 1

            Afficher_image(current)

        End Try

    End Sub

 

Cette méthode prend un nombre en paramètre et permet d’afficher l’image ayant ce nombre pour index dans tabImages pour ensuite la redimensionner. Si l’application n’arrive pas à ouvrir une image (ce qui peut arriver si l’utilisateur l’a supprimée entre temps) alors elle est retirée de la liste et l’image suivante est affichée et la valeur de current est incrémentée.

ImageViewer est la classe qui contient tous les contrôles et les évènements qui y sont liés. PB_Image est le nom donné à la PictureBox, Image est la propriété qui a pour valeur l’image à afficher.

La méthode Redim_image :

    Public Sub Redim_image()

If ImageViewer.PB_Image.Image.Height <= ImageViewer.PB_Image.MaximumSize.Height And ImageViewer.PB_Image.Image.Width <= ImageViewer.PB_Image.MaximumSize.Width Then 'Si l'image a des dimensions plus petites que la taille maximum de la PictureBox

            ImageViewer.PB_Image.Size = ImageViewer.PB_Image.Image.Size

        Else

ImageViewer.PB_Image.Width = (ImageViewer.PB_Image.Image.Width * ImageViewer.PB_Image.MaximumSize.Height) / ImageViewer.PB_Image.Image.Height

 

ImageViewer.PB_Image.Height = (ImageViewer.PB_Image.Image.Height * ImageViewer.PB_Image.MaximumSize.Width) / ImageViewer.PB_Image.Image.Width

        End If 

ImageViewer.PB_Image.SetBounds(((ImageViewer.Width - ImageViewer.PB_Image.Width) / 2), ((ImageViewer.Height - ImageViewer.PB_Image.Height) / 2), ImageViewer.PB_Image.Width, ImageViewer.PB_Image.Height)

    End Sub

Si la hauteur et la largeur de l’image affichée sont inférieures à la hauteur et la largeur maximum de la PictureBox alors les dimensions de la PictureBox prennent celles de l’image pour valeur. Sinon elle est redimensionnée proportionnellement aux dimensions de l’image et aux dimensions maximums de la PictureBox. Une fois redimensionnée, elle est placée au centre de la fenêtre.

 

La méthode Image_suivante :

                Public Sub Image_suivante()

                               If current = (tabImages.Count - 1) Then

                                               Afficher_image(0)

                                               current = 0

                               Else

                                               Afficher_image(current + 1)

                                               current += 1

                               End If

                End Sub


Cette méthode affiche l’image qui se situe après l’image actuelle. Si l’index de l’image actuelle est égal au nombre d’éléments présents dans la liste – 1 (car une liste commence à 0) alors current prend 0 pour valeur sinon sa valeur est augmentée de 1.

 

La méthode Image_precedente :

Public Sub Image_precedente()

                If current = 0 Then

                               Afficher_image(tabImages.Count - 1)

                               current = tabImages.Count - 1

                Else

                               Afficher_image(current - 1)

                               current -= 1

                End If

End Sub


Cette méthode fonctionne sur le même principe que Image_suivante. Si l’index de l’image courante est 0  alors current vaut la taille de la liste - 1, dans le cas contraire il y a décrémentation de la valeur de current.

La méthode Rotation_image :

Public Sub Rotation_image(ByVal sensHoraire As Boolean)

If sensHoraire = False Then

ImageViewer.PB_Image.Image.RotateFlip(RotateFlipType.Rotate270FlipNone) 'Rotation de 90° dans le sens anti-horaire

ElseIf sensHoraire = True Then

ImageViewer.PB_Image.Image.RotateFlip(RotateFlipType.Rotate90FlipNone) ' Rotation de 90° dans le sens horaire

                End If

                Redim_image()

End Sub


Cette méthode prend un Booléen en paramètre. Ce booléen vaut True si la rotation se fait sans le sens horaire et False dans le sens anti-horaire. Après la rotation, l’image est redimensionnée pour qu’elle s’affiche correctement. Si elle n’était pas redimensionnée les proportions ne seraient pas conservées et l’affichage serait donc incorrect.

 

La méthode Supprimer_image :

Public Sub Supprimer_image()

ImageViewer.PB_Image.Image.Dispose()

Try ' Si une image est supprimée on l'enlève de la liste et on affiche la suivante

My.Computer.FileSystem.DeleteFile(tabImages(current), FileIO.UIOption.AllDialogs, FileIO.RecycleOption.SendToRecycleBin)

tabImages.RemoveAt(current)

current += 1

Afficher_image(current)

Catch 'Si l'utilisateur clique sur Annuler cela lève une exception

End Try

End Sub


Cette méthode envoi l’image courante à la corbeille. La boite de dialogue demandant confirmation est affichée. Si l’utilisateur clique sur Non ou ferme la boite de dialogue, une exception est levée, dans ce cas aucune instruction n’est exécutée. Si l’utilisateur clique sur Oui l’image est retirée de la liste et l’image suivante est affichée.

Qutrième étape : Création des évènements

Dans la classe ImageViewer, donc celle qui correspond à notre fenêtre, déclarez un objet de type viewer.

Dim viewer As Viewer


Evènements liés aux éléments du menu :


Ouverture d’une image :

Private Sub Ouvrir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Ouvrir.Click

OpenImage.Filter = "Images| *.jpg; *.jpeg; *.gif; *.png; *.bmp"

If OpenImage.ShowDialog() = DialogResult.OK Then

viewer = New Viewer()

P_Boutons.Visible = True

End If

End Sub


Un filtre est créé pour qu’on ne puisse ouvrir que des images. Si une image est choisie alors le constructeur de la classe Viewer est appelé et les boutons sont affichés.

Copier une image dans le presse-papier :

Private Sub Copier_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Copier.Click

        If PB_Image.Image IsNot Nothing Then

            Clipboard.SetDataObject(PB_Image.Image)

        End If

End Sub


Si une image est affichée alors elle est placée dans le presse-papier. Elle pourra ensuite être collée dans un autre document.

 

Imprimer une image :

Private Sub Imprimer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Imprimer.Click

        If PB_Image.Image IsNot Nothing Then

            PrintOptions.Document = Me.PrintImage

            If PrintOptions.ShowDialog() = DialogResult.OK Then

                Try

                    PrintImage.Print()

                Catch

                End Try

            End If

        End If

End Sub

 

Private Sub PrintImage_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintImage.PrintPage

        e.Graphics.DrawImage(PB_Image.Image, PB_Image.Bounds)

End Sub

 


Ces évènements sont appelés lorsque l’utilisateur veut imprimer une image. Créez deux autres contrôles dans le projet : un PrintDocument, appelé PrintImage et un PrintDialog, appelé PrintOptions. Si une image est affichée, alors le document à imprimer est cette image. Si l’impression est annulée ou ne fonctionne pas, une exception est levée.

Supprimer une image :

Private Sub Supprimer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Supprimer.Click

        If PB_Image.Image IsNot Nothing Then

            viewer.Supprimer_image()

        End If

End Sub


Si une image est affichée alors on appelle la méthode Supprimer_image.

Quitter :

Private Sub Quitter_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Quitter.Click

        End

End Sub


Cet évènement arrête l’exécution de l’application et ferme la fenêtre.

Evènements liés aux boutons :

Le bouton Précédent :

Private Sub BT_Precedent_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_Precedent.Click

        viewer.Image_precedente()

End Sub


Lorsqu’il y a un clic sur ce bouton, la méthode Image_precedente est appelée.

 

Le bouton Diaporama :

Private Sub BT_Diaporama_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_Diaporama.Click

        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None

        Me.TopMost = True

        Me.WindowState = FormWindowState.Maximized

        P_Boutons.Hide()

        M_Menu.Hide()

        Cursor.Hide()

        Me.Focus()

        timer.Enabled = True

End Sub

 

Private Sub timer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timer.Tick

        viewer.Image_suivante()

End Sub

 

Shadows Sub KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown

        If Me.WindowState = FormWindowState.Maximized Then

            If e.KeyCode = Keys.Escape Then

                Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Sizable

                Me.WindowState = FormWindowState.Normal

                Me.TopMost = False

                P_Boutons.Show()

                M_Menu.Show()

                Cursor.Show()

                timer.Enabled = False

            End If

        End If

End Sub


Pour gérer le diaporama, créez un nouveau contrôle de type Timer. Mettez ses propriété Enabled à false et Interval à 5000ms. Une fois le timer déclenché il va appeler la méthode Image_suivante toutes les cinq secondes.

Lorsqu’il y a un clic sur le bouton Diaporama, les bordures de la fenêtre sont masquées, la fenêtre est affichée au premier plan et en plein écran. Les boutons, le curseur et le menu sont cachés et le timer est déclenché.

Pour arrêter le diaporama, ajoutez un évènement de type KeyDown sur la fenêtre. Si la fenêtre est en plein écran et qu’’il y a un appuie sur la touche Echap alors la fenêtre est remise dans son état précédent ; c’est-à-dire mode fenêtré avec bordures,  réaffichage des boutons, du curseur et du menu puis on arrêt du timer.

Le bouton Suivant :

Private Sub BT_Suivant_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_Suivant.Click

        viewer.Image_suivante()

End Sub


Lorsqu’on clique sur ce bouton, la méthode Image_suivante est appelée.

 

Le bouton Rotation Gauche :

Private Sub BT_Gauche_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_Gauche.Click

        viewer.Rotation_image(False)

End Sub


Un clic sur ce bouton appelle la méthode Rotation_image avec False en paramètre, ce qui veut dire que la rotation se fera dans le sens anti-horaire.

Le bouton Rotation Droite :

Private Sub BT_Droite_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_Droite.Click

        viewer.Rotation_image(True)

End Sub


Un clic sur ce bouton appelle la méthode Rotation_image avec True en paramètre, ce qui veut dire que la rotation se fera dans le sens horaire.

Le bouton Supprimer :

Private Sub BT_Supprimer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_Supprimer.Click

        viewer.Supprimer_image()

End Sub


Ce bouton appelle la méthode Supprimer_Image.

Redimensionnement de la fenêtre :

Private Sub ImageViewer_SizeChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.SizeChanged

        PB_Image.MaximumSize = New Size((Me.Width), (Me.Height - 80))

        If PB_Image.Image IsNot Nothing Then

            viewer.Redim_image()

        End If

End Sub


Ajoutez un évènement SizeChanged sur la fenêtre. Lorsque la taille de la fenêtre change, les dimensions maximum de la PictureBox changent et si une image est affichée elle est redimensionnée.

Me.Height – 80 Permet de ne pas afficher une image au dessus des boutons ou du menu.

vb.net, Visual Studio 2010