Création d'une barre de progression personalisée.
08/03/2006
Par arnolem (Autres articles)
Vous avez déja eu besoin d'utiliser la barre de progression par défaut pour un developpement ? 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ée et personalisable, selon les besoins du projet.
Dernière correction le : 08/03/2006 par arnolem
Présentation
La barre de progressions 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, notament graphiques.
Principe de fonctionnement
Le fonctionnement est assez simple, la barre par défaut comme les autres barre de progression ne sont pas dynamique, dans le sens ou elle ne fonctionne 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ée, l'unité pourra être le nombre de requête ou alors le nombre d'enregistrement d'une table. Il faut ensuite une nombre incrémenté représentant l'état actuel, par exemple, pour le même traitement avec la base de donneés, 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'a maintenant.
Timer utilisé pour l'exemple
Nous allons écrire la fonction représentant un traitement lourd en utilisant un Timer.
Pour commencer, déposé 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'a 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'évenement 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 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".
Un peu de design
Passons aux choses sérieuses avec la partie design, et oui et 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 fais compliqué en utilisant 6 images mais vous pouvez le faire avec beaucoup moins.
Dans mon cas, il y a une barre de progression découpée en 3, ainsi qu'un fond aussi découpé en 3. Le but va être de faire une barre qui augmente progressivement, pour cela, nous allons placer les extrêmitées 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".
Insérer les images à l'aide de PictureBox
Voyons comment insérer les images dans votre application. Vous devez créer 6 instance de PictureBox que vous nommez et leur attribez 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 6 PictureBox avec 6 images, les images center* utilisé 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 conseil de configurer les images et de les passer en AutoSize (même les center*) puis ensuite, repasser les 2 autres en normal.

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 3 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 élements 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 transmisses à 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 surement 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 mantenant prêt à être appelée, revenons donc à notre traitement.
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'évenement 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
Conclusion
Même si c'est exemple n'a pas trop de sens, il vous apprend au moin à réfléchir sur la manière d'enrichir votre application avec des petites astuces comme la personnalisation d'un barre de progression. Faites 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 à servi, un petit mail me ferais un grand plaisir.
Concluons sur l'utilisation, il peut être judicieux d'utiliser une barre de chargement pour le chargement d'un fichier (à chaque lignes, on ogmente 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
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, ...
|