MediaSlider - Trackbar控件的替代品 - v1.3






4.94/5 (58投票s)
一个功能齐全的动画滑块控件

按钮的结构
与其直接给你一些无聊的代码(反正没人看...),我想分享一些关于我如何构建此控件中使用的视觉样式的见解。
我做的第一件事,也是过程中的第一步,就是充分了解用户对用户控件的需求,以及对最终控件外观的设想。我经常浏览wincustomize.com或专业的控件制作网站,以了解可能的功能和UI线索,还可以看看Windows/Mac,并尝试想象他们是如何创建那些图形的,甚至是如何改进它们的。
下一步是搭建控件的框架。创建用户控件,为其添加所有基本功能,并尝试创建一个简单无故障的框架来使用。我是这样开始这个滑块的,直到所有基本功能都正常工作后,我才开始编写图形代码。在此过程中,保持一切组织有序至关重要。我最喜欢.NET的一点是#region
指令。它允许您将大型类和方法分割成可管理的块。此外,我建议为内部测量使用private
属性或常量,因为随着代码变得越来越复杂,硬编码的数字需要更改的可能性就越来越大。这是我在编写此控件的Autosize功能时遇到的问题;因为一些数字被硬编码在一个方法中,一个错误导致我花了一个小时才找到问题。
绘制一个闪亮的按钮..
第一步是用纯色填充按钮。这是为了确保在使用透明颜色时,按钮保持不透明。如果您使用半透明颜色并想要发光效果,则使用白色,否则使用按钮的基础颜色。

从上面的图像中可以看到,按钮的比例不正确。我这样做是为了使渐变阴影的细微差别更加明显。您还可以看到这只是一个普通的黑色边框,带有白色填充,这只是在添加三个渐变之前的画布。

第一个渐变是一个垂直线性渐变,其混合因子在中心使用180个alpha值的半透明白色,渐变到按钮的基础颜色。这给人一种立体感,让按钮仿佛从平面上凸起。
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(buttonRect);
// fill with base color
using (Brush br = new SolidBrush(Color.FromArgb(255, this.ButtonColor)))
g.FillPath(br, gp);
// add top sheen
using (LinearGradientBrush fillBrush = new LinearGradientBrush(
buttonRect,
Color.FromArgb(180, Color.White),
this.ButtonColor,
LinearGradientMode.Vertical))
{
Blend blnd = new Blend();
blnd.Positions = new float[] { 0f, .1f, .2f, .3f, .6f, 1f };
blnd.Factors = new float[] { .2f, .3f, .4f, .5f, 1f, 1f };
fillBrush.Blend = blnd;
g.FillPath(fillBrush, gp);
}
我还想从下方添加一个类似MediaPlayer按钮的亮光效果,使用强调色。强调色是用户可定义的,这意味着您可以选择从微妙到非常明显的效果。尽管这些图像在白色背景上显示了按钮的属性颜色,但在设计它们时,我在黑色背景上使用了红色和白色。这让您对渐变如何相互作用有了更好的认识。底部发光是通过向graphics path添加一个新的椭圆,将其推到按钮底部,并使用PathGradientBrush
绘制来实现的。
// add the bottom glow
using (PathGradientBrush borderBrush = new PathGradientBrush(gp))
{
using (GraphicsPath ga = new GraphicsPath())
{
accentRect.Inflate(0, (int)-(accentRect.Height * .2f));
accentRect.Offset(0, (int)(ButtonSize.Width * .2f));
ga.AddEllipse(accentRect);
// center focus
fx = accentRect.Width * .5f;
fy = accentRect.Height * 1f;
borderBrush.CenterColor = this.ButtonColor;
borderBrush.SurroundColors = new Color[] { this.ButtonAccentColor };
borderBrush.FocusScales = new PointF(1f, 0f);
borderBrush.CenterPoint = new PointF(fx, fy);
g.FillPath(borderBrush, ga);
}
最后一个渐变在按钮顶部大约300度处添加了一个聚光灯效果,使其看起来像是光源位于按钮图像的左上方。
// spotight offsets
fx = buttonRect.Width * .2f;
fy = buttonRect.Height * .05f;
// draw the spotlight
borderBrush.CenterColor = Color.FromArgb(120, Color.White);
borderBrush.SurroundColors = new Color[] { Color.FromArgb(5, Color.Silver) };
borderBrush.FocusScales = new PointF(.2f, .2f);
borderBrush.CenterPoint = new PointF(fx, fy);
g.FillPath(borderBrush, gp);
这一切可能对于这样一个小的按钮来说似乎付出了很多努力,但我认为细节很重要,而且,按钮的图形甚至可以做得更加复杂。另外请注意,所有按钮样式实际上都渲染到Bitmap上,只创建一次,只需要一个DrawImage
命令即可渲染。否则就不会没有闪烁。

属性
我希望此控件的绝大多数方面都可以修改,因此保留了许多开放式属性以供自定义。
Animated
:在获得焦点时运行动画效果。AnimationSpeed
:动画周期速度 [快 中 慢]。AnimationSize
:精灵宽度占轨道宽度的百分比 [最小值 0.05 - 最大值 0.2]。BackGroundImage
:使用图像作为滑块背景。ButtonAccentColor
:修改按钮强调色。ButtonBorderColor
:修改按钮边框颜色。ButtonColor
:修改按钮基础颜色。ButtonCornerRadius
:调整滑块按钮的圆角半径。ButtonSize
:修改滑块按钮大小。ButtonStyle
:设置按钮样式 [Round RoundedRectOverlap RoundedRectInline Hybrid PointerUpLeft PointerDownRight GlassInline GlassOverlap
]。IsInited
:返回控件的初始化状态。LargeChange
:鼠标单击或PageUp/PageDown时滑块移动的点击次数。Maximum
:滑块位置的最大值。MaxSize
:控件的最大尺寸值 [私有设置]。Minimum
:滑块位置的最小值。MinSize
:控件的最小尺寸值 [私有设置]。Orientation
:控件的方向。PrecisionValue
:将滑块位置返回为浮点数,需要将SmoothScrolling
设置为true
。SmallChange
:按下箭头键时滑块移动的位置数。SmoothScrolling
:启用平滑滚动样式。Value
:滑块的位置。ShowButtonOnHover
:仅在控件获得焦点或鼠标悬停时显示滑块按钮。SliderFlyOut
:启用弹出式标题窗口 [无、获得焦点时、持续显示]。TickColor
:修改滑块刻度线颜色。TickStyle
:选择刻度线样式。TickType
:选择刻度线绘制样式。TrackBorderColor
:修改滑块边框颜色。TrackDepth
:调整滑块轨道的深度。TrackFillColor
:设置轨道背景色。TrackProgressColor
:设置轨道背景色。TrackShadow
:启用轨道阴影。TrackShadowColor
:修改轨道阴影颜色。TrackStyle
:轨道的显示样式 [进度、值]。
样式
一些亮点
精确模式

Round
圆角矩形
玻璃效果
WMC克隆带弹出式标题
WMP克隆带焦点动画
标题工具栏
如果您正在运行Aero,标题区域的工具栏可能引起了您的注意...这是一个如何使用此功能的绝佳示例(为什么要在演示窗体中弄得一团糟?)。
一切都是可移植的,只需复制ExtendFrame
区域的内容,更新您的指令,然后调用ExtendMargin
方法,就像示例中一样,或者查看我关于此主题的文章。