109 votes

Comment changer la couleur de la barre de progression en C # .NET 3.5?

Je voudrais faire deux choses sur ma barre de progression.

  1. Changer la couleur verte en rouge.
  2. Supprimer les blocs et la rendre d'une seule couleur.

Toute information sur ces deux choses que je me demande comment accomplir sera grandement appréciée!

Merci.

138voto

user1032613 Points 2229

D'accord, ça m'a pris un certain temps pour lire toutes les réponses et les liens. Voici ce que j'en ai retiré :

Résultats d'échantillonnage

La réponse acceptée désactive les styles visuels, elle vous permet de définir la couleur à n'importe quoi, mais le résultat semble simple :

saisissez ici la description de l'image

En utilisant la méthode suivante, vous pouvez obtenir quelque chose comme ceci à la place :

saisissez ici la description de l'image

Comment faire

Tout d'abord, incluez ceci si ce n'est pas déjà fait : using System.Runtime.InteropServices;

Ensuite, vous pouvez soit créer cette nouvelle classe, soit mettre son code dans une classe non générique existante static :

public static class ModifyProgressBarColor
{
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
    public static void SetState(this ProgressBar pBar, int state)
    {
        SendMessage(pBar.Handle, 1040, (IntPtr)state, IntPtr.Zero);
    }
}

Maintenant, pour l'utiliser, appelez simplement :

progressBar1.SetState(2);

Notez le second paramètre dans SetState, 1 = normal (vert); 2 = erreur (rouge); 3 = avertissement (jaune).

19 votes

Vous avez créé une méthode d'extension, donc l'appel doit être progressBar1.SetState(2); en plus de cela, Excellente réponse!

5 votes

Il convient de noter que cela n'est disponible que sur Vista+. Vous pouvez consulter la documentation complète en recherchant PBM_SETSTATE.

0 votes

+1. Merci ! Astuce pour les autres qui m'ont été utile : Collez ceci à la fin de l'espace de noms plutôt qu'au début si vous rencontrez cette erreur à l'exécution : System.Resources.MissingManifestResourceException

92voto

Crispy Points 3341

Étant donné que les réponses précédentes ne semblent pas fonctionner avec les Styles visuels. Vous devrez probablement créer votre propre classe ou étendre la barre de progression :

public class NewProgressBar : ProgressBar
{
    public NewProgressBar()
    {
        this.SetStyle(ControlStyles.UserPaint, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Rectangle rec = e.ClipRectangle;

        rec.Width = (int)(rec.Width * ((double)Value / Maximum)) - 4;
        if(ProgressBarRenderer.IsSupported)
           ProgressBarRenderer.DrawHorizontalBar(e.Graphics, e.ClipRectangle);
        rec.Height = rec.Height - 4;
        e.Graphics.FillRectangle(Brushes.Red, 2, 2, rec.Width, rec.Height);
    }
}

MODIFICATION : Code mis à jour pour que la barre de progression utilise le style visuel pour l'arrière-plan

2 votes

Merci pour cela, c'était quelque chose avec lequel je pouvais travailler dans ma solution.

0 votes

C'est vraiment cool, merci. Cela m'a vraiment aidé pour quelque chose sur lequel je travaille en ce moment, bien que je l'ai modifié pour redessiner tout le contrôle à chaque fois au lieu de juste la zone spécifiée par e.ClipRectangle. Sinon, il ne se redessinait pas correctement après que seule une partie du contrôle ait été invalidée par une autre fenêtre ou par le bord de l'écran.

0 votes

@Matt Blaine: Pourriez-vous s'il vous plaît poster votre modification comme une modification à la réponse? Je crois qu'il y aura suffisamment de personnes intéressées par votre solution complète.

41voto

William Daniel Points 399

Ceci est une version sans scintillement du code le plus accepté que vous pouvez trouver en réponse à cette question. Tout le crédit revient aux auteurs de ces réponses fantastiques. Merci Dusty, Chris, Matt et Josh!

Comme la demande de "Fueled" dans l'un des commentaires, j'avais également besoin d'une version qui se comportait un peu plus... professionnellement. Ce code conserve les styles du code précédent, mais ajoute un rendu d'image hors écran et un tampon graphique (et supprime correctement l'objet graphique).

Résultat : tout le bon et pas de scintillement. :)

public class NewProgressBar : ProgressBar
{
    public NewProgressBar()
    {
        this.SetStyle(ControlStyles.UserPaint, true);
    }

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
        // Aucun... Aide à contrôler le scintillement.
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        const int inset = 2; // Une seule valeur de décalage pour contrôler la taille de la zone intérieure.

        using (Image offscreenImage = new Bitmap(this.Width, this.Height))
        {
            using (Graphics offscreen = Graphics.FromImage(offscreenImage))
            {
                Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);

                if (ProgressBarRenderer.IsSupported)
                    ProgressBarRenderer.DrawHorizontalBar(offscreen, rect);

                rect.Inflate(new Size(-inset, -inset)); // Dégonfler la zone intérieure.
                rect.Width = (int)(rect.Width * ((double)this.Value / this.Maximum));
                if (rect.Width == 0) rect.Width = 1; // Impossible de dessiner un rectangle avec une largeur de 0.

                LinearGradientBrush brush = new LinearGradientBrush(rect, this.BackColor, this.ForeColor, LinearGradientMode.Vertical);
                offscreen.FillRectangle(brush, inset, inset, rect.Width, rect.Height);

                e.Graphics.DrawImage(offscreenImage, 0, 0);
            }
        }
    }
}

0 votes

Eh bien, c'est le plus proche de l'implémentation originale de Microsoft.

1 votes

Avoir un bloc using et appeler Dispose est en fait un peu redondant. Bonne réponse cependant.

1 votes

Je me rends compte que c'est vieux; et je me rends compte que c'est un détail (car Minimum est presque toujours zéro); mais le facteur d'échelle de largeur doit être (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum)) pour être correct avec une attention excessive aux détails. :)

31voto

dustyburwell Points 4501

Dans le designer, vous devez simplement définir la propriété ForeColor à la couleur de votre choix. Dans le cas du rouge, il existe une couleur prédéfinie pour cela.

Pour le faire en code (C#), faites ceci :

pgs.ForeColor = Color.Red;

Éditer : Oh oui, définissez également le Style sur continuous. En code, comme ceci :

pgs.Style = System.Windows.Forms.ProgressBarStyle.Continuous;

Autre modification : Vous devrez également supprimer la ligne qui contient Application.EnableVisualStyles() dans votre Program.cs (ou similaire). Si vous ne pouvez pas le faire car vous voulez que le reste de l'application ait des styles visuels, alors je vous suggère de peindre le contrôle vous-même ou de passer à WPF car ce genre de chose est facile avec WPF. Vous pouvez trouver un tutoriel sur le dessin personnalisé d'une barre de progression sur codeplex

3 votes

Forecolor=rouge ; Backcolor=bleu; Style = Continious. Rien n'a changé, cela reste comme si je n'y avais jamais touché

3 votes

Bah...d'accord, je vois le problème. Vous devez désactiver les styles visuels pour que cela fonctionne avec les propriétés. Il peint probablement en utilisant le thème que vous avez sélectionné. Dans Program.cs, il y a une ligne qui dit Application.EnableVisualStyles(). Supprimez cette ligne et cela fonctionnera. Sinon, vous devrez peindre le contrôle vous-même. L'autre option est d'utiliser WPF (si c'est possible), car cela vous permet de faire ce genre de choses très facilement.

0 votes

Veuillez me donner plus d'informations sur "Comment le peindre moi-même".

16voto

Matt Blaine Points 1729

Modification de la réponse de dustyburwell. (Je n'ai pas assez de réputation pour l'éditer moi-même.) Comme sa réponse, cela fonctionne avec les "Styles visuels" activés. Vous pouvez simplement définir la propriété ForeColor de la barre de progression dans la vue de conception du formulaire.

using System;
using System.Windows.Forms;
using System.Drawing;

public class ProgressBarEx : ProgressBar
{
    private SolidBrush brush = null;

    public ProgressBarEx()
    {
        this.SetStyle(ControlStyles.UserPaint, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        if (brush == null || brush.Color != this.ForeColor)
            brush = new SolidBrush(this.ForeColor);

        Rectangle rec = new Rectangle(0, 0, this.Width, this.Height);
        if (ProgressBarRenderer.IsSupported)
            ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rec);
        rec.Width = (int)(rec.Width * ((double)Value / Maximum)) - 4;
        rec.Height = rec.Height - 4;
        e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);
    }
}

0 votes

Cela fonctionne très bien pour changer la couleur du premier plan, mais cela clignote beaucoup, alors que le contrôle de ProgressBar par défaut ne le fait pas. Une idée de comment résoudre cela?

5 votes

J'ai trouvé comment résoudre le scintillement : ajoutez un double buffer à ControlStyles de la ProgressBar définie par l'utilisateur, comme ceci : SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, ...).

0 votes

Je me rends compte que c'est vieux; et je me rends compte que c'est un détail (car Minimum est presque toujours zéro); mais le facteur d'échelle de Largeur devrait être (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum)) pour être correct jusqu'au boutiste. :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X