Как изменить цвет progressbar в C#.NET 3.5?


Я хотел бы сделать две вещи на моем индикаторе прогресса.

  1. изменить зеленый цвет на красный.
  2. удалите блоки и сделать это в один цвет.

любая информация об этих двух вещах, которые я задаюсь вопросом, как это сделать, будет очень сильно оценена!

спасибо.

21 79

21 ответ:

поскольку предыдущие ответы не работают с визуальными стилями. Вероятно, вам нужно будет создать свой собственный класс или расширить индикатор выполнения:

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);
    }
}

изменить: обновленный код, чтобы сделать индикатор выполнения использовать визуальный стиль для фона

ОК, мне потребовалось некоторое время, чтобы прочитать все ответы и ссылки. Вот что я из них вытянул:

Пример Результатов

принятый ответ отключает визуальные стили, он позволяет вам установить цвет на все, что вы хотите, но результат выглядит просто:

enter image description here

используя следующий метод, вы можете сделать что-то вроде этого:

enter image description here

Как

первый, включите это, если у вас нет:using System.Runtime.InteropServices;

во-вторых, вы можете либо создать этот новый класс, либо поместить его код в существующий 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);
    }
}

теперь, чтобы использовать его, просто позвоните:

ModifyProgressBarColor.SetState(progressBar1, 2);

обратите внимание на второй параметр в SetState, 1 = нормальный (зеленый); 2 = ошибка (красный); 3 = предупреждение (желтый).

надеюсь, что это помогает!

это без мерцания версия наиболее принятого кода, который вы можете найти в качестве ответов на этот вопрос. Все заслуга плакатов с этими фатальными ответами. Спасибо Дасти, Крис, Мэтт и Джош!

Как запрос"Fueled" в одном из комментариев, мне также нужна была версия, которая вела себя немного больше... профессионально. Этот код поддерживает стили, как и в предыдущем коде, но добавляет отображение закадрового изображения и буферизацию графики (и размещает графический объект правильно.)

результат: все хорошо, и никакой фликер. :)

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

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
        // None... Helps control the flicker.
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        const int inset = 2; // A single inset value to control teh sizing of the inner rect.

        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)); // Deflate inner rect.
                rect.Width = (int)(rect.Width * ((double)this.Value / this.Maximum));
                if (rect.Width == 0) rect.Width = 1; // Can't draw rec with width of 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);
                offscreenImage.Dispose();
            }
        }
    }
}

в конструкторе вам просто нужно установить свойство ForeColor в любой цвет, который вы хотите. В случае с красным цветом для него есть предопределенный цвет.

чтобы сделать это в коде (C#) сделайте это:

pgs.ForeColor = Color.Red;

Edit: О да, также установите стиль в непрерывный. В коде, вот так:

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

Другой Редактировать: вам также нужно удалить строку, которая читает Application.EnableVisualStyles() из своего Program.cs (или похожие). Если вы не можете сделать это, потому что вы чтобы остальная часть приложения имела визуальные стили, я бы предложил нарисовать элемент управления самостоятельно или перейти к WPF, так как с WPF это легко. Вы можете найти учебник по рисованию владельцем индикатора выполнения на codeplex

модификация ответа дастибервелла. (У меня недостаточно репутации, чтобы редактировать его самостоятельно.) Как и его ответ, он работает с включенными "визуальными стилями". Вы можете просто установить свойство forecolor progressbar в любой форме конструктора.

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);
    }
}

используя ответы Мэтта Блейна и Криса Персикетти, я создал индикатор выполнения, который выглядит немного лучше, позволяя бесконечный выбор цвета (в основном я изменил одну строку в решении Мэтта):

ProgressBarEx:

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

namespace QuantumConcepts.Common.Forms.UI.Controls
{
    public class ProgressBarEx : ProgressBar
    {
        public ProgressBarEx()
        {
            this.SetStyle(ControlStyles.UserPaint, true);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            LinearGradientBrush brush = null;
            Rectangle rec = new Rectangle(0, 0, this.Width, this.Height);
            double scaleFactor = (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum));

            if (ProgressBarRenderer.IsSupported)
                ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rec);

            rec.Width = (int)((rec.Width * scaleFactor) - 4);
            rec.Height -= 4;
            brush = new LinearGradientBrush(rec, this.ForeColor, this.BackColor, LinearGradientMode.Vertical);
            e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);
        }
    }
}

использование:

progressBar.ForeColor = Color.FromArgb(255, 0, 0);
progressBar.BackColor = Color.FromArgb(150, 0, 0);

результаты

You can use any gradient you like!

скачать

https://skydrive.live.com/?cid=0EDE5D21BDC5F270&id=EDE5D21BDC5F270%21160&sc=documents#

Я просто поместил это в статический класс.

  const int WM_USER = 0x400;
  const int PBM_SETSTATE = WM_USER + 16;
  const int PBM_GETSTATE = WM_USER + 17;

  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
  static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

  public enum ProgressBarStateEnum : int
  {
   Normal = 1,
   Error = 2,
   Paused = 3,
  }

  public static ProgressBarStateEnum GetState(this ProgressBar pBar)
  {
   return (ProgressBarStateEnum)(int)SendMessage(pBar.Handle, PBM_GETSTATE, IntPtr.Zero, IntPtr.Zero);
  }

  public static void SetState(this ProgressBar pBar, ProgressBarStateEnum state)
  {
   SendMessage(pBar.Handle, PBM_SETSTATE, (IntPtr)state, IntPtr.Zero);
  } 

надеюсь, это поможет,

Марк

обычно индикатор выполнения либо тематический, либо соответствует цветовым предпочтениям пользователя. Поэтому для изменения цвета вам либо нужно отключить визуальные стили и установить ForeColor или нарисовать себя контролировать.

что касается непрерывного стиля вместо блоков вы можете установить Style свойства:

pBar.Style = ProgressBarStyle.Continuous;

редактировать

по звукам вещей вы используете тему XP, которая имеет зеленый блок на основе prog-bar. Попробуйте перевернуть свой стиль пользовательского интерфейса в Windows Classic и снова протестировать, но вам может потребоваться реализовать свое собственное событие OnPaint, чтобы заставить его делать то, что вы хотите во всех стилях пользовательского интерфейса

или, как кто-то еще указал, отключите визуальные стили для вашего приложения.

Оригинал

насколько я знаю, рендеринг индикатор выполнения выполняется в соответствии с выбранным вами стилем темы windows (win2K, xp, vista)

вы можете изменить цвет, установив свойство

ProgressBar.ForeColor

Я не уверен, что вы можете сделать, однако гораздо больше...

некоторые погуглить

здесь есть статья из MS KB о создании "гладкого" индикатора выполнения

http://support.microsoft.com/kb/323116

Я предлагаю вам также взглянуть на эту статью о CodeProject:Прогресс-О-Дум. Это здорово!

попробуйте использовать messsage PBM_SETBARCOLOR, что должно сделать трюк с SendMessage

см.http://www.vbforums.com/showthread.php?t=248721 для примера.

все эти методы не работают для меня, но этот метод позволяет изменить цвет строки.

обратите внимание, что я нашел этот код откуда-то еще на StackOverflow и немного изменил его. С тех пор я забыл, где я нашел этот код и я не могу связать его из-за этого так жаль.

но в любом случае я надеюсь, что этот код помогает кому-то это действительно помогло мне.

private void ProgressBar_MouseDown(object sender, MouseButtonEventArgs e)
    {
        var converter = new System.Windows.Media.BrushConverter();
        var brush = (Brush)converter.ConvertFromString("#FFB6D301");
        ProgressBar.Foreground = brush;
    }

где используется имя "ProgressBar" заменить на свой собственный прогресс название бара. Вы также можете вызвать это событие с другими аргументами просто убедитесь, что в скобках где-то.

изменить Color и Value ( мгновенные изменения )

поставить using System.Runtime.InteropServices; в верхней части...

вызов с ColorBar.SetState(progressBar1, ColorBar.Color.Yellow, myValue);

я заметил, что если вы измените значение бара ( насколько он большой), то он не изменится, если он находится в цвете, отличном от зеленого по умолчанию. Я взял код user1032613 и добавил опцию Value.

public static class ColorBar
{
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
    public enum Color { None, Green, Red, Yellow }

    public static void SetState(this ProgressBar pBar, Color newColor, int newValue)
    {
        if (pBar.Value == pBar.Minimum)  // If it has not been painted yet, paint the whole thing using defualt color...
        {                                // Max move is instant and this keeps the initial move from going out slowly 
            pBar.Value = pBar.Maximum;   // in wrong color on first painting
            SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);
        }
        pBar.Value = newValue;
        SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);     // run it out to the correct spot in default
        SendMessage(pBar.Handle, 1040, (IntPtr)(int)newColor, IntPtr.Zero);        // now turn it the correct color
    }

}

на всякий случай кто-нибудь ищет другой вариант.... вы можете расширить панель, использовать ее в качестве фона (белого или любого другого), добавить другую панель внутри нее для переднего плана (движущаяся панель). Тогда у вас есть полный контроль изменение цвета и т. д.

просто щелкните правой кнопкой мыши на вашем проекте в обозревателе решений Visual Basic (где находятся ваши файлы vb) и выберите Свойства из меню. В появившемся окне снимите флажок "Включить визуальные стили XP" и теперь, когда вы устанавливаете forecolor, он должен работать сейчас.

Јοеу: Цитата: Обычно индикатор выполнения либо тематический, либо соответствует цветовым предпочтениям пользователя. Поэтому для изменения цвета вам либо нужно отключить визуальные стили и установить ForeColor или нарисовать себя контролировать.

что касается непрерывного стиля вместо блоков вы можете установить Style свойства:

pBar.Style = ProgressBarStyle.Continuous;

ProgressBarStyle.Непрерывный по сравнению с блоками бесполезен с включенными VistualStyles...

блок(ов) будет работать только с визуальными стилями нетрудоспособный... что делает все это спорным моментом (в отношении пользовательского цвета прогресса) С отключенными стилями vistual ... индикатор выполнения должен быть окрашен на основе forecolor.

я использовал комбинацию ответа Уильяма Даниэля (с включенными визуальными стилями, поэтому ForeColor не будет просто плоским без стиля) и Ответ Барри (на пользовательский текст на панели выполнения) от:как поместить текст на ProgressBar?

вертикальная полоса вверх для вниз в красном цвете:

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



public class VerticalProgressBar : ProgressBar
{


    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.Style |= 0x04;
            return cp;

        }
    }
    private SolidBrush brush = null;

    public VerticalProgressBar()
    {
        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.DrawVerticalBar(e.Graphics, rec);
        rec.Height = (int)(rec.Height * ((double)Value / Maximum)) - 4;
        rec.Width = rec.Width - 4;
        e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);

    } 
}

VB.Net цветной прогрессбар, который уважает визуальные стили WXP, отвечает ...

Я начал с ответа от 'user1032613' на 3/17/12. Обратите внимание, что это модуль, а не класс. Оттуда я преобразовал код, но нужно было больше. В частности, преобразованный код показал функцию DirectCast для преобразования целого числа "state" В Тип IntPtr, который не работал.

Imports System.Runtime.InteropServices

Public Module ModifyProgressBarColor

    Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _
    Private Function SendMessage(hWnd As IntPtr, Msg As UInteger, w As IntPtr, l As IntPtr) As IntPtr
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Sub SetState(pBar As ProgressBar, state As Integer)

        '-- Convert state as integer to type IntPtr
        Dim s As IntPtr
        Dim y As Integer = state
        s = IntPtr.op_Explicit(y)

        '-- Modify bar color
        SendMessage(pBar.Handle, 1040, s, IntPtr.Zero)

    End Sub

End Module

и снова просто вызовите это в коде using с этим линия:

Call ModifyProgressBarColor.SetState(prb, 2)

кстати-я пробовал другие цвета-0, 4, 5 - все они просто отображаются зеленым цветом.

Я знаю его путь слишком стар, чтобы ответить сейчас.. но все же, небольшая настройка на @Даниилответ на исправление проблемы не показывать нулевой индикатор выполнения. Просто нарисуйте прогресс, только если ширина внутреннего прямоугольника окажется ненулевой.

спасибо всем вкладчикам.

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

            protected override void OnPaintBackground(PaintEventArgs pevent){}
                // None... Helps control the flicker.                

            protected override void OnPaint(PaintEventArgs e)
            {
                const int inset = 2; // A single inset value to control teh sizing of the inner rect.

                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)); // Deflate inner rect.
                        rect.Width = (int)(rect.Width * ((double)this.Value / this.Maximum));

                        if (rect.Width != 0)
                        {
                            LinearGradientBrush brush = new LinearGradientBrush(rect, this.ForeColor, this.BackColor, LinearGradientMode.Vertical);
                            offscreen.FillRectangle(brush, inset, inset, rect.Width, rect.Height);
                            e.Graphics.DrawImage(offscreenImage, 0, 0);
                            offscreenImage.Dispose();
                        }
                    }
                }
            }
        }

Я обнаружил, что это можно сделать, нарисовав прямоугольник внутри индикатора выполнения и установив его ширину в соответствии с текущим значением прогресса. Я также добавил поддержку прогресса справа налево. Таким образом, вам не нужно использовать изображение, а так как Rectnalge.Надувать не называется нарисованный прямоугольник меньше.

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

    protected override void OnPaintBackground(PaintEventArgs pevent) { }

    protected override void OnPaint(PaintEventArgs e)
    {
        double scaleFactor = (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum));
        int currentWidth = (int)((double)Width * scaleFactor);
        Rectangle rect;
        if (this.RightToLeftLayout)
        {
            int currentX = Width - currentWidth;
            rect = new Rectangle(currentX, 0, this.Width, this.Height);
        }
        else
            rect = new Rectangle(0, 0, currentWidth, this.Height);

        if (rect.Width != 0)
        {
            SolidBrush sBrush = new SolidBrush(ForeColor);
            e.Graphics.FillRectangle(sBrush, rect);
        }
    }
}

Edit: в двух минутах мне потребовалось запустить vs и проверить синтаксис, который я был избит до него с гораздо лучшими ответами. я люблю этот сайт.

        progressBar1 = new ProgressBar();
        progressBar1.ForeColor = Color.Red;