【发布时间】:2013-06-19 05:04:34
【问题描述】:
我正在尝试创建步数指示器控件,该控件将显示用户当前所在的步数。 我在 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 - Implementing a wizard progress control in WPF 上找到了示例控件,但我必须留在 Winforms
【问题讨论】:
-
将这些创建为图像(至少是复杂部分)并绘制图像可能会更容易。
-
@LarsTech - 我正在考虑这个问题,但是对于图像,我将无法在不更改图像的情况下自定义控件的外观。我想创建一个带有一些配置选项的控件(渐变的颜色、圆的半径、水平条的高度),这些设置的图像毫无价值。我想尝试用代码创建整个控件,图像是我最后的选择。感谢您的建议,但现在我将继续使用代码绘图 :)
-
尝试使用具有透明背景的 png 并仅绘制带有边框的复选标记。您发布的那些复选标记示例似乎是大小不同的两张不同图像。
-
@LarsTech - 复选标记将是一个图像。我计划添加为每个步骤指定图标作为配置选项的功能,但我想用代码绘制其他所有内容。我现在最大的问题是如何将水平条和灰色圆圈组合在一起,以便将边框作为单个形状围绕它绘制,而不是围绕每个形状(希望我的描述有意义:))