DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

ProgressBarにパーセンテージなどの文字列を表示する

例えば「50%」のように、進行状況をパーセンテージでプログレスバー上に表示しているアプリケーションを見ることがあります。ここではこのように、ProgressBarコントロールの上に文字列を表示する方法を紹介します。

パーセント表示のあるプログレスバー

ただし、「Progress Bars」にあるガイドラインによると、プログレスバーの上にテキストを載せてはいけないことになっています。

WM_PAINTメッセージを受け取った時に描画する方法

この方法は、「c# - ProgressBar Paint Method? - Stack Overflow」などで紹介されている方法です。

ProgressBarコントロールがWM_PAINTメッセージを受け取った時、ProgressBarに直接文字列を描画します。それには、ProgressBarクラスの派生クラスを作成して、WndProcメソッドをオーバーライドします。

この方法でパーセント表示しているProgressBarコントロールの例を以下に示します。この自作コントロールの使い方は、通常のProgressBarと同じですので、通常のProgressBarの代わりに使用できます。もし使い方が分からないという場合は、こちらをご覧ください。

VB.NET
コードを隠すコードを選択
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Security.Permissions

''' <summary>
''' パーセント表示のあるプログレスバーコントロールを表します。
''' </summary>
Public Class PercentageProgressBar
    Inherits ProgressBar
    Private WM_PAINT As Integer = &HF

    <SecurityPermission(SecurityAction.Demand, _
        Flags:=SecurityPermissionFlag.UnmanagedCode)> _
    Protected Overrides Sub WndProc(ByRef m As Message)
        MyBase.WndProc(m)

        If m.Msg = WM_PAINT Then
            '表示する文字列を決定する
            Dim percent As Double = CDbl(Me.Value - Me.Minimum) / _
                CDbl(Me.Maximum - Me.Minimum)
            Dim displayText As String = _
                String.Format("{0}%", CInt(percent * 100.0))
            '文字列を描画する
            Dim tff As TextFormatFlags = TextFormatFlags.HorizontalCenter Or _
                TextFormatFlags.VerticalCenter Or TextFormatFlags.SingleLine
            Dim g As Graphics = Me.CreateGraphics()
            TextRenderer.DrawText(g, displayText, Me.Font, _
                Me.ClientRectangle, SystemColors.ControlText, tff)
            g.Dispose()
        End If
    End Sub
End Class
C#
コードを隠すコードを選択
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Security.Permissions;

/// <summary>
/// パーセント表示のあるプログレスバーコントロールを表します。
/// </summary>
public class PercentageProgressBar : ProgressBar
{
    private int WM_PAINT = 0x000F;

    [SecurityPermission(SecurityAction.Demand,
        Flags = SecurityPermissionFlag.UnmanagedCode)]
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        if (m.Msg == WM_PAINT)
        {
            //表示する文字列を決定する
            double percent = (double)(this.Value - this.Minimum)
                / (double)(this.Maximum - this.Minimum);
            string displayText = string.Format("{0}%", (int)(percent * 100.0));
            //文字列を描画する
            TextFormatFlags tff = TextFormatFlags.HorizontalCenter |
                TextFormatFlags.VerticalCenter |
                TextFormatFlags.SingleLine;
            Graphics g = this.CreateGraphics();
            TextRenderer.DrawText(g, displayText, this.Font,
                this.ClientRectangle, SystemColors.ControlText, tff);
            g.Dispose();
        }
    }
}

ProgressBarを自分で描画する方法

当たり前ですが、ProgressBarをすべて自分で描画すれば、文字列を表示させることも簡単です。ProgressBarを自分で描画する方法は「ProgressBarの色を変える」で説明していますので、詳しくはそちらをご覧ください。

以下に示すProgressBarクラスの派生クラスは、この方法でパーセント表示しています。この例ではプログレスバーをvisualスタイルで描画するために.NET Framework 2.0以降でしか使用できないクラスを使っています。もし.NET Framework 1.1以前で使用するならば、別の方法で描画してください。

VB.NET
コードを隠すコードを選択
Imports System.Drawing
Imports System.Windows.Forms

''' <summary>
''' パーセント表示のあるプログレスバーコントロールを表します。
''' </summary>
Public Class PercentProgressBar
    Inherits ProgressBar

    Public Sub New()
        'Paintイベントが発生するようにする
        'ダブルバッファリングを有効にする
        MyBase.SetStyle(ControlStyles.UserPaint Or _
                        ControlStyles.AllPaintingInWmPaint Or _
                        ControlStyles.OptimizedDoubleBuffer, True)
    End Sub

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        '背景を描画する
        ProgressBarRenderer.DrawHorizontalBar(e.Graphics, Me.ClientRectangle)

        'バーの幅を計算する
        '上下左右1ピクセルの枠の部分を除外して計算する
        Dim percent As Double = CDbl(Me.Value - Me.Minimum) / _
            CDbl(Me.Maximum - Me.Minimum)
        Dim chunksWidth As Integer = CInt( _
            CDbl(Me.ClientSize.Width - 2) * percent)
        Dim chunksRect As New Rectangle(1, 1, _
            chunksWidth, Me.ClientSize.Height - 2)
        'バーを描画する
        ProgressBarRenderer.DrawHorizontalChunks(e.Graphics, chunksRect)

        '表示する文字列を決定する
        Dim displayText As String = String.Format("{0}%", _
            CInt(Math.Truncate(percent * 100.0)))
        '文字列を描画する
        Dim tff As TextFormatFlags = TextFormatFlags.HorizontalCenter Or _
            TextFormatFlags.VerticalCenter Or _
            TextFormatFlags.SingleLine
        TextRenderer.DrawText(e.Graphics, displayText, Me.Font, _
            Me.ClientRectangle, SystemColors.ControlText, tff)
    End Sub
End Class
C#
コードを隠すコードを選択
using System;
using System.Drawing;
using System.Windows.Forms;

/// <summary>
/// パーセント表示のあるプログレスバーコントロールを表します。
/// </summary>
public class PercentProgressBar : ProgressBar
{
    public PercentProgressBar()
    {
        //Paintイベントが発生するようにする
        //ダブルバッファリングを有効にする
        base.SetStyle(ControlStyles.UserPaint |
            ControlStyles.AllPaintingInWmPaint |
            ControlStyles.OptimizedDoubleBuffer, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        //背景を描画する
        ProgressBarRenderer.DrawHorizontalBar(e.Graphics, this.ClientRectangle);

        //バーの幅を計算する
        //上下左右1ピクセルの枠の部分を除外して計算する
        double percent = (double)(this.Value - this.Minimum)
            / (double)(this.Maximum - this.Minimum);
        int chunksWidth = (int)((double)(this.ClientSize.Width - 2) * percent);
        Rectangle chunksRect = new Rectangle(1, 1,
            chunksWidth, this.ClientSize.Height - 2);
        //バーを描画する
        ProgressBarRenderer.DrawHorizontalChunks(e.Graphics, chunksRect);

        //表示する文字列を決定する
        string displayText = string.Format("{0}%", (int)(percent * 100.0));
        //文字列を描画する
        TextFormatFlags tff = TextFormatFlags.HorizontalCenter |
            TextFormatFlags.VerticalCenter |
            TextFormatFlags.SingleLine;
        TextRenderer.DrawText(e.Graphics, displayText, this.Font,
            this.ClientRectangle, SystemColors.ControlText, tff);
    }
}

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。