I tried to use a Label, this is the code:
public partial class Form1 : Form
{
private readonly HttpClient _httpClient;
private readonly ProgressBar _progressBar;
private readonly Label _labelProgress;
private readonly Timer downloadTimer;
private readonly Radar radar;
public Form1()
{
InitializeComponent();
_httpClient = new HttpClient();
_progressBar = new ProgressBar
{
Size = lblNextTimeDownload.Size,
Minimum = 0,
Maximum = 100,
Value = 0,
};
_labelProgress = new Label
{
AutoSize = false,
TextAlign = ContentAlignment.MiddleCenter,
Font = new Font("Arial", 12, FontStyle.Regular),
};
_progressBar.Controls.Add(_labelProgress);
Controls.Add(_progressBar);
}
}
The result is that the _labelProgress
is positioned at the top left on the ProgressBar
If in the Label’s instance I add the line:
Dock = DockStyle.Fill,
like this:
_labelProgress = new Label
{
AutoSize = false,
TextAlign = ContentAlignment.MiddleCenter,
Dock = DockStyle.Fill,
Font = new Font("Arial", 12, FontStyle.Regular),
};
then the text of the Label is positioned in the center middle of the ProgresBar, but it also overlaps the entire ProgressBar.
My suggestion is to avoid using a Label for this. Among other things, you may find out that it doesn’t scale the same way as the ProgressBar, when your Form is scaled in a DpiAware context.
You can directly paint the percentage onto the Control’s surface, using the ProgressBar’s DC. Override WndProc and handle WM_PAINT
for this.
Of course, you need to build a Custom Control, override it’s WndProc, trap WM_PAINT
, then use GetWindowDc() to get its device context.
Graphics.FromHdcInternal()
is then called to generate a Graphics object, which is then passed to TextRenderer.DrawText()
to render the percentage as text.
ReleaseDC() must be called after, to release the HDC.
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
[ToolboxItem(true), DesignerCategory("code")]
public class ProgressBarEx : ProgressBar {
Color percentageColor = Color.Black;
int percentageDecimals = 0;
public ProgressBarEx() { }
[DefaultValue(typeof(Color), "Black")]
public Color PercentageColor {
get => percentageColor;
set {
if (percentageColor != value) {
percentageColor = value;
Invalidate();
}
}
}
[DefaultValue(0), Description("Number of decimals (0-4)")]
public int PercentageDecimals {
get => percentageDecimals;
set {
if (percentageDecimals != value) {
percentageDecimals = Math.Max(Math.Min(value, 4), 0);
Invalidate();
}
}
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
switch (m.Msg) {
case WM_PAINT:
if (!IsHandleCreated) return;
float percentage = (float)Value / Maximum;
percentage = float.IsNaN(percentage) ? 0 : percentage;
var hDC = GetWindowDC(this.Handle);
try {
using (var g = Graphics.FromHdcInternal(hDC)) {
TextRenderer.DrawText(g, percentage.ToString($"P{percentageDecimals}"),
Font, ClientRectangle, percentageColor);
}
}
finally {
if (hDC != IntPtr.Zero) ReleaseDC(this.Handle, hDC);
}
m.Result = IntPtr.Zero;
break;
default:
break;
}
}
const int WM_PAINT = 0x000F;
[DllImport("user32.dll")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
}