Création d'une barre de progression personnalisée

Arnaud Lemercier

Vous avez déjà eu besoin d'utiliser la barre de progression par défaut pour un développement ? Permettez-moi de vous dire qu'elle n'est pas vraiment très esthétique et est assez limitée au niveau des options. C'est pourquoi je me suis lancé dans la création d'un progressBar amélioré et personnalisable, selon les besoins du projet.

télécharger la source et les images sources

- Titre : Création d'une barre de progression personnalisée

- Auteur : Arnaud Lemercier

- Parution : 8 mars 2006

- Mise à jour : 4 janvier 2013

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Arnaud Lemercier. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Présentation

- II. Principe de fonctionnement

- III. Timer utilisé pour l'exemple

- IV. Un peu de design

- V. Insérer les images à l'aide de PictureBox

- VI. La fonction

- VII. Utilisation de la fonction pBarre()

- VIII. Conclusion

- IX. Remerciements

I - Présentation

La barre de progression est un des moyens permettant de faire patienter l'utilisateur durant un traitement assez long. Un composant intégré au Dotnet permet d'en utiliser une mais elle comporte des limites, notamment graphiques.

II - Principe de fonctionnement

Le fonctionnement est assez simple, la barre par défaut comme les autres barres de progression ne sont pas dynamiques, dans le sens ou elles ne fonctionnent pas juste en les positionnant sur la scène, il faut aller un peu plus loin.
Le principe est de définir une unité de référence, par exemple, pour un traitement avec une base de données, l'unité pourra être le nombre de requête ou alors le nombre d'enregistrements d'une table. Il faut ensuite un nombre incrémenté représentant l'état actuel, par exemple, pour le même traitement avec la base de données, on prendra l'ID automatique de la table.

Le but est d'obtenir, à un instant donné, le pourcentage d'avancement du traitement. Dans notre exemple, nous allons travailler avec un Timer. L'unité de référence sera donc la seconde et le nombre incrémenté sera la somme des secondes qui se sont passées jusqu'à maintenant.

III - Timer utilisé pour l'exemple

Nous allons écrire la fonction représentant un traitement lourd en utilisant un Timer.

Pour commencer, déposer le composant Timer sur la scène, dans mon exemple, j'ai laissé le nom par défaut qui est "Timer1". J'écris ensuite la procédure qui permettra de simuler un traitement :

Dim time As Interger = 0
Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
time = time + 1
If time > 1000 Then
Timer1.Stop()
End If
End Sub

Ce bout de code permet d'incrémenter le valeur de "time" de 1 en 1 jusqu'à se qu'il atteigne 1000. Cette action est exécutée toutes les 100 millisecondes par défaut mais vous pouvez faire varier ce paramètre grâce à la propriété Interval.

Ce code ne fonctionne pas encore, comme vous l'avez remarqué, le timer n'est pas encore démarré, il faut donc utiliser la méthode Start() afin de lancer le Timer1. Pour cela, nous ajoutons un bouton sur le formulaire que nous appelons Bouton1. Nous plaçons ensuite le code suivant sur l'événement Click :

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Timer1.Start()
End Sub

Vous avez maintenant une petite application qui exécute un compteur de 1 à 1000 toutes les 100ms. Afin de vérifier si ce code fonctionne, vous pouvez toujours créer une TextBox et afficher la valeur de "time".

IV - Un peu de design

Passons aux choses sérieuses avec la partie design. Eh oui, eh oui ! Il n'y a pas que le code dans la vie. Dans le dossier de l'application, vous trouverez un dossier img qui stocke les sources de cet exemple. J'ai fait compliqué en utilisant six images mais vous pouvez le faire avec beaucoup moins.

Dans mon cas, il y a une barre de progression découpée en trois, ainsi qu'un fond aussi découpé en trois. Le but va être de faire une barre qui augmente progressivement. Pour cela, nous allons placer les extrémités de la barre puis faire varier la taille de celui du milieu.
Le fond sera de taille fixe et permettra de voir la taille maximum du chargement.

Vous avez maintenant une petite application qui exécute un compte de 1 à 1000 toutes les 100ms, afin de vérifier si ce code fonctionne, vous pouvez toujours créer une TextBox et afficher la valeur de "time".

V - Insérer les images à l'aide de PictureBox

Voyons comment insérer les images dans votre application. Vous devez créer six instances de PictureBox que vous nommez et leur attribuez une image, suivant le tableau ci-dessous :

Name

Image

BackgroundImage

SizeMode

barre_L

leftBarre.png

AutoSize

barre_C

centerBarre.png

centerBarre.png

Normal

barre_R

rightBarre.png

AutoSize

barre_bg_L

leftBg.png

AutoSize

barre_bg_C

centerBg.png

centerBg.png

Normal

barre_bg_R

rightBg.png

AutoSize

Nous venons de définir six PictureBox avec six images, les images center* utilisées au centre de la barre vont être redimensionnées, c'est pour cela qu'il ont des propriétés différentes comme le SizeMode en "normal".

Pour que la PictureBox est la bonne dimension, je vous conseille de configurer les images et de les passer en AutoSize (même les center*) puis ensuite, repasser les deux autres en normal.

VI - La fonction

On déclare une fonction permettant d'initialiser la progressbar, c'est-à-dire de la masquer avant le traitement, puis d'augmenter la tailler de la progressbar à chaque nouvelle incrémentation de la valeur de référence. Nous allons passer trois paramètres à cette fonction, la valeur courante du chiffre incrémenté, la valeur totale ou maxi, et la taille en pixel de la barre lorsque le chargement est complet.

Sub pBarre(ByVal i As Integer, ByVal imax As Integer, ByVal Wmax As Integer)

Nous allons ensuite faire un premier traitement, afin de masquer les éléments de la progressbar au chargement du formulaire. Pour cela, nous définissons que si la valeur est égale à 0, la fonction est uniquement appelée pour initialiser la barre. Sinon, il faut l'afficher.

If i = 0 Then 'initialisation
barre_L.Visible = False
barre_C.Visible = False
barre_R.Visible = False
barre_bg_L.Visible = False
barre_bg_C.Visible = False
barre_bg_R.Visible = False
barre_lbl.Visible = False
Exit Sub ' fin du traitement
Else
barre_L.Visible = True
barre_C.Visible = True
barre_R.Visible = True
barre_bg_L.Visible = True
barre_bg_C.Visible = True
barre_bg_R.Visible = True
End If

Dans le cas où i vaut autre chose que 0, nous allons afficher les images en fonction des valeurs transmises à la fonction :

Dim w As Integer 'width : correspond à la taille actuelle du centre de la barre
Dim p As Integer 'pourcentage : correspond à l'état d'avancement du traitement
w = Wmax * (i / imax)
p = 100 * (i / imax)

Maintenant que nous disposons d'une fonction qui détermine le pourcentage d'avancement ainsi que la taille actuelle de la barre, il ne reste plus qu'à placer les images de celle ci en fonction des valeurs calculées :

'on va déterminer la position des images en fonction de l'image barre_L
'on va ensuite définir la taille de l'image du milieu et placer l'image de droite en fonction d'elle
Dim barreY As Integer = barre_L.Location.Y 'alignement horizontal des images
barre_L.Location = New Point(barre_L.Location.X, barreY)
barre_C.Location = New Point(barre_L.Location.X + barre_L.Width, barreY)
barre_C.Width = w 'l'image du centre à la largeur w
barre_R.Location = New Point(barre_C.Location.X + barre_C.Width, barreY)
barre_bg_L.Location = New Point(barre_L.Location.X, barreY)
barre_bg_C.Location = New Point(barre_bg_L.Location.X + barre_bg_L.Width, barreY)
barre_bg_C.Width = Wmax + 10 'le fond prend la taille maxi avec une marge
barre_bg_R.Location = New Point(barre_bg_C.Location.X + barre_bg_C.Width, barreY)
'on va placer un label avec le pourcentage qui se placera sur la barre de chargement barre_lbl.Location = New Point(barre_R.Location.X - 15, barreY + 11)
barre_lbl.Text = p & " %"

'N'oublions pas de fermer cette procédure :

End Sub

Vous avez sûrement remarqué que le label était toujours masqué. J'ai choisi de l'afficher uniquement lorsque la barre est assez grande pour ne pas chevaucher le label. Il faut donc le rendre visible à condition que la valeur de w soit assez grande, introduisez le code suivant après avoir défini la valeur de w :

If w > 15 Then
barre_lbl.Visible = True
End If

Notre fonction est maintenant prêt à être appelée, revenons donc à notre traitement.

VII - Utilisation de la fonction pBarre()

Le traitement lourd simulé par notre Timer va permettre d'appeler notre fonction à chaque incrémentation. Mais avant tout, il faut l'initialiser, pour cela, nous allons nous placer sur l'événement Load du formulaire :

Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
pBarre(0, 0, 0) 'Initialise la barre
End Sub

Nous pouvons maintenant utiliser la fonction pour notre traitement :

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

pBarre(time, 1000, 200) 'valeurCourante , valeurMaxi , TailleMaxi

time = time + 1
If time > 1000 Then
Timer1.Stop() 'traitement terminé
End If
End Sub

VIII - Conclusion

Même si cet exemple n'a pas trop de sens, il vous apprend au moins à réfléchir sur la manière d'enrichir votre application avec de petites astuces comme la personnalisation d'un barre de progression. Faite preuve d'originalité dans vos logiciels et n'hésitez pas à créer vos propres 'composants'.

Vous pouvez utiliser cette barre dans vos programmes, n'hésitez pas à me le faire savoir si ce composant vous a servi, un petit mail me ferait un grand plaisir.

Concluons sur l'utilisation, il peut être judicieux d'utiliser une barre de progression pour le chargement d'un fichier (à chaque lignes, on augmente la barre, attention cela nécessite un comptage préalable du nombre de lignes), pour une requête SQL (une première requête envoie le nombre d'enregistrements, la suivante incrémentera la barre ligne par ligne), pour la création d'un treeview ou une dataTable (à chaque enregistrement, on incrémente) ou bien aussi pour la création ou lecture d'un fichier XML (à chaque Node, on incrémente).
Bref, à vous de l'adapter selon le traitement

IX - Remerciements

Je remercie tout particulièrement Alexandra, pour comprendre mon travail et pour me soutenir dans tout ce que je fais. Je t'aime.
Je remercie developpez.com pour donner aux développeurs la chance de s'exprimer, de s'entraider et de s'épanouir.
Je remercie les relecteurs qui ont travaillés sur cette page, tout particulièrement moi.