例えば「50%」のように、進行状況をパーセンテージでプログレスバー上に表示しているアプリケーションを見ることがあります。ここではこのように、ProgressBarコントロールの上に文字列を表示する方法を紹介します。
ただし、「Progress Bars」にあるガイドラインによると、プログレスバーの上にテキストを載せてはいけないことになっています。
この方法は、「c# - ProgressBar Paint Method? - Stack Overflow」などで紹介されている方法です。
ProgressBarコントロールがWM_PAINTメッセージを受け取った時、ProgressBarに直接文字列を描画します。それには、ProgressBarクラスの派生クラスを作成して、WndProcメソッドをオーバーライドします。
この方法でパーセント表示しているProgressBarコントロールの例を以下に示します。この自作コントロールの使い方は、通常のProgressBarと同じですので、通常のProgressBarの代わりに使用できます。もし使い方が分からないという場合は、こちらをご覧ください。
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
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クラスの派生クラスは、この方法でパーセント表示しています。この例ではプログレスバーをvisualスタイルで描画するために.NET Framework 2.0以降でしか使用できないクラスを使っています。もし.NET Framework 1.1以前で使用するならば、別の方法で描画してください。
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
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); } }