Как изменить цвет индикатора выполнения в C # .NET 3.5? - PullRequest
83 голосов
/ 22 апреля 2009

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

  1. Измените зеленый цвет на красный.
  2. Снимите блоки и сделайте их одним цветом.

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

Спасибо.

Ответы [ 22 ]

2 голосов
/ 18 декабря 2009

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

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

2 голосов
/ 22 апреля 2009

EDIT

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

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

Оригинал

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

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

ProgressBar.ForeColor

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

гуглит

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

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

2 голосов
/ 31 мая 2010

Предлагаю вам также взглянуть на эту статью о CodeProject: Progress-O-Doom . Это здорово!

1 голос
/ 26 сентября 2011

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

1 голос
/ 28 января 2011

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

0 голосов
/ 03 декабря 2016

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

Спасибо всем, кто внес свой вклад.

        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();
                        }
                    }
                }
            }
        }
0 голосов
/ 28 октября 2013

Цветной индикатор прогресса VB.Net, соответствующий стандарту WXP Visual Styles: ...

Я начал с ответа пользователя 'user1032613' от 17.03.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

И снова просто вызовите это в коде использования с этой строкой:

Call ModifyProgressBarColor.SetState(prb, 2)

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

0 голосов
/ 11 октября 2013

Вертикальная черта UP For Down в красном цвете:

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

    } 
}
0 голосов
/ 05 июня 2013

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

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

pBar.Style = ProgressBarStyle.Continuous;

ProgressBarStyle.Continuous против блоков бесполезен с включенными VistualStyles ...

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

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

0 голосов
/ 15 июля 2018

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

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