在矩形中心绘制带有叠加层的文本(ProgressBar)

时间:2015-12-02 19:53:09

标签: c# .net gdi+

我正在扩展内置进度条,能够以百分比显示进度,如下所示:

enter image description here

我试图在显示的文字中添加叠加层,因此它更具可读性。我已设法添加它,但现在我的文字未对齐:

enter image description here

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);
    if (m.Msg == 0x000F)
    {
        using (Graphics graphics = CreateGraphics())
        using (var brush = new SolidBrush(ForeColor))
        {
            var newText = Math.Floor(((float) Value/Maximum)*100).ToString(CultureInfo.InvariantCulture) + '%';
            SizeF textSize = graphics.MeasureString(newText, Font);

            graphics.InterpolationMode = InterpolationMode.High;
            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
            graphics.CompositingQuality = CompositingQuality.HighQuality;

            if (Overlay)
            {
                var p = new GraphicsPath();
                p.AddString(
                    newText,
                    Font.FontFamily,
                    (int) Font.Style,
                    Font.SizeInPoints,
                    new Point((int) ((Width - textSize.Width)/2), (int) ((Height - textSize.Height)/2)),
                    StringFormat.GenericDefault);

                graphics.FillPath(brush, p);
                graphics.DrawPath(new Pen(Brushes.Black, 1), p);
            }
            else
            {
                graphics.DrawString(newText, Font, brush, (Width - textSize.Width) / 2, (Height - textSize.Height) / 2);
            }
        }
    }
}

使用g.DrawPath代替g.DrawString时,如何修复文字大小和对齐方式 理想情况下,我想从第一个屏幕获取文本,但是有覆盖。

以下是我控制的完整代码:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Globalization;
using System.Windows.Forms;

namespace Misiu.Controls
{
    public sealed class ProgressBarWithText : ProgressBar
    {

        public ProgressBarWithText()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            ForeColor = Color.White;
            BackColor = Color.Black;
        }

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams result = base.CreateParams;
                if (Environment.OSVersion.Platform == PlatformID.Win32NT
                    && Environment.OSVersion.Version.Major >= 6)
                {
                    result.ExStyle |= 0x02000000; // WS_EX_COMPOSITED 
                }

                return result;
            }
        }

        public bool Overlay { get; set; }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == 0x000F)
            {
                using (Graphics graphics = CreateGraphics())
                using (var brush = new SolidBrush(ForeColor))
                {
                    var newText = string.Empty;

                    switch (DisplayStyle)
                    {
                        case ProgressBarDisplayStyle.ValueAndMax:
                            newText = string.Format("{0}/{1}", Value, Maximum);
                            break;
                        case ProgressBarDisplayStyle.Text:
                            newText = Text;
                            break;
                        case ProgressBarDisplayStyle.Percentage:
                            newText = Math.Floor(((float) Value/Maximum)*100).ToString(CultureInfo.InvariantCulture) + '%';
                            break;
                    }
                    //var newText1 = DisplayStyle == ProgressBarDisplayStyle.Percentage ? Value == 0 ? "0%" : Math.Floor(((float)Value / Maximum) * 100).ToString(CultureInfo.InvariantCulture) + '%' : DisplayStyle == ProgressBarDisplayStyle.ValueAndMax ? string.Format("{0}/{1}", Value,Maximum) : Text;
                    SizeF textSize = graphics.MeasureString(newText, Font);

                    graphics.InterpolationMode = InterpolationMode.High;
                    graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
                    graphics.CompositingQuality = CompositingQuality.HighQuality;
                    //graphics.SmoothingMode = SmoothingMode.AntiAlias;

                    if (Overlay)
                    {
                        var p = new GraphicsPath();
                        p.AddString(
                            newText,
                            Font.FontFamily,
                            (int) Font.Style,
                            Font.SizeInPoints,
                            new Point((int) ((Width - textSize.Width)/2), (int) ((Height - textSize.Height)/2)),
                            StringFormat.GenericDefault);

                        graphics.FillPath(brush, p);
                        graphics.DrawPath(new Pen(Brushes.Black, 1), p);
                    }
                    else
                    {
                        graphics.DrawString(newText, Font, brush, (Width - textSize.Width)/2, (Height - textSize.Height)/2);
                    }
                }
            }
        }

        private ProgressBarDisplayStyle _displayStyle = ProgressBarDisplayStyle.Percentage;

        //Property to set to decide whether to print a % or Text
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)]
        public ProgressBarDisplayStyle DisplayStyle
        {
            get { return _displayStyle; }
            set
            {
                if (_displayStyle == value) return;
                _displayStyle = value;
                Refresh();
            }
        }

        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)]
        public override string Text
        {
            get { return base.Text; }
            set
            {
                base.Text = value;
                Refresh();
            }
        }

        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)]
        public override Font Font
        {
            get { return base.Font; }
            set
            {
                base.Font = value;
                Refresh();
            }
        }
    }

    public enum ProgressBarDisplayStyle
    {
        Percentage,
        ValueAndMax,
        Text
    }
}

修改
由于@Hans Passant,大部分问题都得到解决,但文字仍然未对齐,如下所示:

enter image description here

左进度条使用Lucida Handwriting, 30pt, style=Bold和右'Microsoft Sans Serif,20pt。 文本稍微移动到右下角。

下面是我和我的对照的比较:

enter image description here

1 个答案:

答案 0 :(得分:2)

我建议你通过StringFormat在控件的客户端矩形中对齐整个文本:

StringFormat format = new StringFormat()
{
    Alignment = StringAlignment.Center,
    LineAlignment = StringAlignment.Center
};
float emSize = graphics.DpiY * Font.Size / 72;
var p = new GraphicsPath();
p.AddString(
    newText,
    Font.FontFamily,
    (int)Font.Style,
    emSize ,
    ClientRectangle, // !!!
    format); // !!!

这种方法可以摆脱任何测量和位置计算,它总是使事情正确地与我对齐。

相关问题