web-dev-qa-db-ja.com

C#.NET 3.5でプログレスバーの色を変更するにはどうすればよいですか?

進行状況バーで2つのことを行いたいです。

  1. 緑色を赤に変更します。
  2. ブロックを取り外して、1色にします。

これらの2つのことに関する情報は、どうすれば達成できるのでしょうか。

ありがとう。

84
Ivan Prodanov

前の回答はVisual Stylesでは機能しないようです。おそらく、独自のクラスを作成するか、進行状況バーを拡張する必要があります。

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

編集:プログレスバーが背景の視覚スタイルを使用するようにコードを更新しました

76
Crispy

OK、すべての回答とリンクを読むのに時間がかかりました。私がそれらから得たものは次のとおりです。

サンプル結果

受け入れられた答えは視覚的なスタイルを無効にし、色をあなたが望むものに設定することはできますが、結果は明白に見えます:

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の2番目のパラメーター、1 =通常(緑)に注意してください。 2 =エラー(赤); 3 =警告(黄色)。

それが役に立てば幸い!

110
user1032613

これは、この質問に対する答えとして見つけることができる最も受け入れられているコードのちらつきのないバージョンです。これらの致命的な答えのポスターへのすべてのクレジット。ダスティ、クリス、マット、ジョシュに感謝します!

コメントの1つにある「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();
            }
        }
    }
}
33
William Daniel

デザイナでは、ForeColorプロパティを任意の色に設定するだけです。赤の場合、定義済みの色があります。

コード(C#)でこれを行うには、次のようにします。

pgs.ForeColor = Color.Red;

Edit:そうそう、スタイルも連続に設定します。次のようなコードで:

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

別の編集:Program.cs(または同様の)からApplication.EnableVisualStyles()を読み取る行も削除する必要があります。アプリケーションの残りの部分に視覚的なスタイルを持たせるためにこれができない場合は、コントロールを自分でペイントするか、WPFを使用することをお勧めします。進行状況バーを描画する所有者のチュートリアルを見つけることができます codeplexで

27
dustyburwell

Matt BlaineとChris Persichettiの回答を使用して、無限の色の選択を可能にしながら、少し見栄えの良いプログレスバーを作成しました(基本的に、Mattのソリューションの1行を変更しました)。

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#

15
Josh M.

Dustyburwellの答えへの修正。 (自分で編集するのに十分な担当者がいません。)彼の答えのように、「Visual Styles」を有効にして動作します。フォームのデザインビューでプログレスバーのForeColorプロパティを設定するだけです。

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);
    }
}
14
Matt Blaine

これを静的クラスに入れました。

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

それが役に立てば幸い、

マーク

5
Marc

通常、進行状況バーはテーマを設定するか、ユーザーの色設定を尊重します。そのため、色を変更するには、視覚スタイルをオフにしてForeColorを設定するか、自分でコントロールを描画する必要があります。

ブロックではなく連続スタイルについては、Styleプロパティを設定できます。

pBar.Style = ProgressBarStyle.Continuous;
3
Joey

CodeProjectのこの記事もご覧になることをお勧めします: Progress-O-Doom 。それは素晴らしい!

2
Drake

ColorおよびValueを変更します(即時変更)

using System.Runtime.InteropServices;を先頭に配置...

ColorBar.SetState(progressBar1, ColorBar.Color.Yellow, myValue);で呼び出します

バーの値(大きさ)を変更しても、デフォルトの緑以外の色であれば変更されないことに気付きました。 user1032613のコードを取得し、値オプションを追加しました。

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
    }

}
2
Sparfy

メッセージPBM_SETBARCOLORを使用してみてください。これはSendMessageでトリックを行う必要があります

例については、 http://www.vbforums.com/showthread.php?t=248721 を参照してください。

2
Aleksandar

編集

使用している物の音により、緑のブロックベースのプログラムバーを持つXPテーマを使用しています。 UIスタイルをWindowsクラシックに切り替えてもう一度テストしてみてください。ただし、すべてのUIスタイルで必要なことを実行するには、独自のOnPaintイベントを実装する必要がある場合があります。

または、他の誰かが指摘したように、アプリケーションのVisualStylesを無効にします。

オリジナル

私の知る限り、プログレスバーのレンダリングは、選択したWindowsテーマスタイル(win2K、xp、Vista)とインラインで行われます

プロパティを設定して色を変更できます

ProgressBar.ForeColor

しかし、あなたがもっともっとできるかどうかはわかりません...

グーグルを行います

「スムーズ」プログレスバーの作成に関するMS KBの記事があります。

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

2
Eoin Campbell

これらすべての方法は私にはうまくいきませんが、この方法では色文字列に変更できます。

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」という名前が使用されている場合は、独自のプログレスバー名に置き換えます。また、他の引数を使用してこのイベントをトリガーすることもできます。その場合は、その中括弧をどこかで確認してください。

2
EpicNinjaCheese

Visual Basic Solution Explorer(vbファイルがある場所)でプロジェクトを右クリックし、メニューからプロパティを選択します。ポップアップウィンドウで[Enable XP Visual Styles]の選択を解除し、前景色を設定すると、動作するはずです。

1
Randy

誰かが別のオプションを探している場合に備えて....パネルを拡張し、背景(白など)として使用し、その中に別のパネルを追加して前景(移動バー)にできます。次に、色の変更などを完全に制御できます。

1
Eduardo

WXP Visual Stylesの回答を尊重するVB.Net色付きプログレスバーは...

3/17/12の「user1032613」からの回答から始めました。これは、クラスではなくモジュールになっていることに注意してください。そこからコードを変換しましたが、さらに必要でした。特に、変換されたコードは、「状態」整数を機能しないIntPtr型に変換するDirectCast関数を示しました。

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
DanW52

すべての最も簡単な解決策は、簡単な修正であると思いますが、Program.csからApplication.EnableVisualStyles()を削除したり、コメントを付けたり、Main関数を含むパーツに名前を付けたりすることができます。その後、progressBar.ForeColor = Color.TheColorYouDesire;で進行状況バーの色を自由に変更できます。

static void Main()
        {
            //Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
         }
0
Mladen Tasevski

答え:引用:通常、進行状況バーはテーマを設定するか、ユーザーの色設定を尊重します。したがって、色を変更するには、ビジュアルスタイルをオフにしてForeColorを設定するか、自分でコントロールを描画する必要があります。

ブロックではなく連続スタイルについては、Styleプロパティを設定できます。

pBar.Style = ProgressBarStyle.Continuous;

ProgressBarStyle.Continuous対Blocksは、VistualStylesが有効になっていると役に立ちません...

ブロックは、視覚スタイルを無効にした場合にのみ機能します...これは、すべてを重要なポイントにレンダリングします(カスタムの進行色に関して)視覚スタイルを無効にすると...プログレスバーは前景色に基づいて色付けする必要があります。

ウィリアムダニエルの回答(視覚スタイルが有効になっているため、ForeColorはスタイルなしではフラットになりません)とバリーの回答(プログレスバーのカスタムテキストに対して)の組み合わせを使用しました: どのようにテキストを配置しますかProgressBar?

0
NeoH4x0r

赤い色の垂直バーUPダウン:

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
Mandrova

今では答えるにはあまりにも古い方法を知っています..それでも、ゼロ値のプログレスバーを表示しないという問題を修正するための@ 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
Divins Mathew

これは、進行状況バー内に四角形を描画し、進行状況の現在の値に応じて幅を設定することで実現できることがわかりました。また、右から左への進行状況のサポートも追加しました。この方法では、Imageを使用する必要がなく、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);
        }
    }
}
0
ZOK