2

我正在尝试创建步骤指示器控件,该控件将显示当前用户所在的步骤。我在 dribble 上发现了一些我想创建的概念:

设计

使用非常简单的代码,我能够创建这样的结果: 我的结果

下面是我的代码:

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace StepIndicator
{
    public class StepIndicatorOne : Control
    {
        public StepIndicatorOne()
        {
            MinimumSize = new Size(300, 50);
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            var g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;

            int steps = 3;
            int radiusBig = 20;
            int radiusSmall = 15;
            int bgHeight = 10;

            var gradientRect = new Rectangle(ClientRectangle.X + (ClientRectangle.Width - radiusBig*2)/(steps - 1),
                                             ClientRectangle.Y + ClientRectangle.Height/2 - radiusBig - 1, radiusBig*2, radiusBig*2);

            var lightGrayBrush = new LinearGradientBrush(ClientRectangle, Color.FromArgb(224, 227, 214), Color.LightGray, LinearGradientMode.Vertical);
            var darkGrayBrush = new LinearGradientBrush(gradientRect, Color.DarkGray, Color.Gray, LinearGradientMode.Vertical);
            var lightGreenBrush = new LinearGradientBrush(ClientRectangle, Color.FromArgb(206, 217, 79), Color.FromArgb(191, 201, 82), LinearGradientMode.Vertical);
            var darkGreenBrush = new LinearGradientBrush(ClientRectangle, Color.YellowGreen, Color.ForestGreen, LinearGradientMode.Vertical);

            g.FillRectangle(darkGrayBrush, ClientRectangle.X + radiusBig, ClientRectangle.Y + ClientRectangle.Height/2 - bgHeight/2 - 1,
                            ClientRectangle.Width - radiusBig*2, bgHeight);

            g.FillRectangle(lightGrayBrush, ClientRectangle.X + radiusBig, ClientRectangle.Y + ClientRectangle.Height/2 - bgHeight/2,
                            ClientRectangle.Width - radiusBig*2, bgHeight);

            for (int i = 1; i <= steps; i++)
            {
                g.FillEllipse(darkGrayBrush, ClientRectangle.X + ((ClientRectangle.Width - radiusBig*2)/(steps - 1))*(i - 1),
                              ClientRectangle.Y + ClientRectangle.Height/2 - radiusBig - 1, radiusBig*2, radiusBig*2);
                g.FillEllipse(lightGrayBrush, ClientRectangle.X + ((ClientRectangle.Width - radiusBig*2)/(steps - 1))*(i - 1),
                              ClientRectangle.Y + ClientRectangle.Height/2 - radiusBig, radiusBig*2, radiusBig*2);
            }

            for (int i = 1; i <= steps - 1; i++)
            {
                g.FillEllipse(darkGreenBrush,
                              ClientRectangle.X + ((ClientRectangle.Width - radiusBig*2)/(steps - 1))*(i - 1) + radiusBig - radiusSmall,
                              ClientRectangle.Y + ClientRectangle.Height/2 - radiusSmall - 1, radiusSmall*2, radiusSmall*2);
                g.FillEllipse(lightGreenBrush,
                              ClientRectangle.X + ((ClientRectangle.Width - radiusBig*2)/(steps - 1))*(i - 1) + radiusBig - radiusSmall,
                              ClientRectangle.Y + ClientRectangle.Height/2 - radiusSmall, radiusSmall*2, radiusSmall*2);
            }

        }
    }
}

我的问题是:
是否可以像设计一样创建绿色形状(带有圆圈和一个孔的绿色条)但在它上面有边框?
我可以绘制带边框的矩形和带边框的椭圆,但是如何将这两个形状组合并在其周围设置边框(将这两个形状组合成一个)-创建复杂路径是我唯一的选择吗?

我知道 winforms gdi+ 不能使用内阴影,但是还有其他一些选项可以创建类似于内发光的漂亮效果吗?
现在我用 -1 偏移量和更深的颜色绘制相同的形状,但效果不是我想要的。

我知道最好的解决方案可能是切换到 WPF 并在那里绘制,我什至在 SO 上找到了示例控件 -在 WPF 中实现向导进度控件,但我必须留在 Winforms

4

1 回答 1

1

对复杂路径使用 GraphicsPath。对内部阴影使用路径渐变。

于 2013-06-18T21:04:34.903 回答