带阴影和动画的标签






3.38/5 (15投票s)
一个具有阴影效果的标签,可以使用旋转、透明度和缩放进行动画处理。
引言
文章中解释的控件是一个带有阴影效果的标签,并添加了透明度、缩放和旋转的动画。 这是用 C# 和 .NET 2.0 完成的(在 .NET 3.5 中测试并且工作正常)。
背景
我需要一个具有炫酷效果的文本控件来完成一个项目,所以我决定制作一个独立的控件。
使用代码
您可以使用两种标准方法使用该控件
- 在您的解决方案中包含项目“dzzControls”,以便它自动出现在工具箱中(在 *dzzControls* 部分中),但它具有通用图标。
- 在工具箱中,右键单击“常规”,然后单击“选择项...”。 单击“浏览”并找到“*dzzControls.dll*”。 确保选中“EffectsLabel”旁边的复选框,然后单击“确定”。
现在,将其拖放到窗体上。 在“属性”中,选择“分类”视图,然后转到“效果”部分。 摆弄属性(更改立即在设计器中可见)。
该控件公开了一些属性
ShadowColor
,与ForeColor
和BackColor
结合使用,会影响控件的着色。- 仅当
ShadowOffset
与默认值0; 0
不同时,ShadowColor
才有意义。 X 和 Y 值可以为负! - 如果
MinZoom
低于 100,控件将使用 100% 和设置的最小百分比之间的渐变缩放进行动画处理。 - 如果
MinAlpha
小于MaxAlpha
,控件将使用给定值之间的逐渐变化的透明度进行动画处理。 - 如果
MinRotate
小于MaxRotate
,控件将使用指定角度(以度为单位)之间的逐渐旋转的文本进行动画处理。 注意:这些值限制为sbyte
(-128 到 +127),因此更改这些值以满足您自己的需求是一个简单的练习。 Letterwise
指定效果是应用于单个字母还是应用于整个字符串(从Control
继承的Text
属性)。
幕后花絮
继承的属性 Text
、Font
、ForeColor
和 Enabled
被重写以适应特定于控件的逻辑。
新的属性(如上所述)都使用私有变量实现,并且 setter 通常包含一些代码(用于刷新控件或类似操作)。 例如
private byte _MinZoom;
[Category("Effects"), DefaultValue((byte)100),
Description("Animate text zoom, in range MinZoom%-100%")]
public byte MinZoom
{
get { return _MinZoom; }
set
{
_MinZoom = value <= 100 ? value : (byte)100;
if (_MinZoom == 0)
_MinZoom = 1;
if (_CurrentZoom < _MinZoom)
_CurrentZoom = _MinZoom;
if (_MinZoom < 100)
{
aTimer.Start();
}
else
RecalculateTimer();
Refresh();
}
}
还有一些私有变量包含动画的当前状态,例如
private byte _CurrentZoom;
private sbyte _ZoomStep = 1;
动画是使用内部计时器(称为 aTimer
,超时时间为 20 毫秒 - 相当于 50fps)实现的。 当计时器滴答时,执行动画的一个步骤
private void aTimer_Tick(object sender, EventArgs e)//animation timer tick
{
...
if (_MinZoom < 100)//zoom animation enabled?
{
if (_CurrentZoom == 100)
_ZoomStep = (sbyte)-1;
if (_CurrentZoom == _MinZoom)
_ZoomStep = (sbyte)1;
_CurrentZoom = (byte)(_CurrentZoom + _ZoomStep);
}
Refresh();//redraw control
}
当文本、字体、最小或最大旋转更改时,内部过程 RecalculateSize
会重新调整控件的大小。 它还计算单个字符的大小,这些大小在 paint 事件处理程序中使用。
这个自定义控件的大脑是 OnPaint
事件处理程序,它太大了,无法在此处完全解释,但基本版本是
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
//rotation is not smooth without anti-aliasing
e.Graphics.TranslateTransform(Size.Width / 2, Size.Height / 2);
//set coordinate system origin to center of the control
if (_CurrentRotate != 0)
e.Graphics.RotateTransform(_CurrentRotate); //apply rotation ...
if (_CurrentZoom < 100)
e.Graphics.ScaleTransform(_CurrentZoom / 100.0f, _CurrentZoom / 100.0f);
//... and zoom
e.Graphics.DrawString(Text, Font, new SolidBrush(base.ForeColor),
-tsize.Width / 2, -tsize.Height / 2);
//draw text in coordinate system, so text's
//center matches coordinate system's center
注意:大多数属性都是整数类型(int
、byte
、sbyte
)。 这足以满足我当前的需求,将这些更改为 float
应该是读者的一项不错的练习。
一些问题
当使用超长字符串时(我在使用此控件时遇到),如果启用动画,该控件往往会对处理器造成很高的负载。
如果在窗体上启用动画或控件在窗体上移动(因此重复重绘),则这些控件中的多个也往往会产生很高的处理器使用率。
关注点
将 MeasureCharacterRanges
限制为仅 32 个测量范围使我不得不重写字母顺序情况的 OnPaint
(在花费一些时间进行调试后)。
由于这是我的第一个控件,我还花了很多时间使控件“对设计器友好”,例如
[Category("Effects"), DefaultValue(typeof(Point), "0, 0"),
Description("If differs from (0,0), creates shadow" +
" with specified offset from Left and Top")]
public Point ShadowOffset
{
get { ...
... 因此,如果未设置,则此属性在 Visual Studio 属性网格中不会加粗。
历史
- 本文的第一个版本写于 2008 年 3 月 11 日。
- 2008 年 3 月 12 日:对源代码进行了小幅修改 + 一些不需要的属性从 Visual Studio 设计器属性网格中隐藏(使用了 Bob Powell 提供的代码)。
- 2008 年 3 月 24 日:用新的演示应用程序替换了旧的演示应用程序(旧的演示应用程序需要带有控件的 DLL)。