using System;
using System.Drawing;
using System.Windows.Forms;
namespace MyCustom.Controls
{
public class ShadowLabel : Label
{
#region Properties
protected int _xOffset = 5;
protected int _yOffset = 5;
#endregion
#region Constructor
public ShadowLabel() : base() => InitializeComponent();
#endregion
#region Accessors
/// <summary>Specifies the solid-colour value of the shadow. No alpha information from this setting is used.</summary>
/// <remarks>Alpha blending is handled programmatically via the <i>Alpha</i> accessor value.</remarks>
/// <seealso cref="Alpha"/>
public Color ShadowColor { get; set; } = Color.Black;
/// <summary>Specifies the vertical translation of the shadow (up/down). Range: -25 to +25.</summary>
/// <remarks>Using a negative value shifts the shadow up, while a positive value shifts downwards.</remarks>
public int xOffset
{
get => this._xOffset;
set => this._xOffset = (value < 0) ? Math.Max(value,-25) : Math.Min( 25, value );
}
/// <summary>Specifies the horizontal translation of the shadow (left/right). Range: -25 to +25.</summary>
/// <remarks>Using a negative value shifts the shadow left, while a positive value goes right.</remarks>
public int yOffset
{
get => this._yOffset;
set => this._yOffset = (value < 0) ? Math.Max( value, -25 ) : Math.Min( 25, value );
}
/// <summary>Specifies the starting Alpha value of the shadow (how solid is it).</summary>
/// <remarks>The shadow is made more transparent as it deepens, from this value to zero.</remarks>
public byte Alpha { get; set; } = 255;
#endregion
#region Methods
protected override void OnPaint( PaintEventArgs e )
{
Graphics g = e.Graphics;
int xStart = Math.Min( this.Location.X, this.Location.X + xOffset ),
xEnd = Math.Max( this.Location.X, this.Location.X + xOffset ),
yStart = Math.Min( this.Location.Y, this.Location.Y + yOffset ),
yEnd = Math.Max( this.Location.Y, this.Location.Y + yOffset ),
steps, xIncrement, yIncrement, alphaIncrement;
steps = Math.Max( xEnd - xStart, yEnd - yStart );
xIncrement = ( xOffset < 0 ? -1 : 1 ) * (int)Math.Floor( (xEnd - xStart) / (float)steps );
yIncrement = ( yOffset < 0 ? -1 : 1 ) * (int)Math.Floor( (yEnd - yStart) / (float)steps );
alphaIncrement = (int)Math.Floor( Alpha / (float)steps );
if ( steps > 0 )
{
for ( int i = steps; i > 0; i-- )
g.DrawString(
this.Text,
this.Font,
new SolidBrush(
Color.FromArgb(
this.Alpha - (alphaIncrement * i),
ShadowColor.R,
ShadowColor.G,
ShadowColor.B
)
),
new PointF()
{
X = (xIncrement * i), // this.Location.X + (xIncrement * i),
Y = (yIncrement * i) // this.Location.Y + (yIncrement * i)
}
);
g.DrawString( this.Text, this.Font, new SolidBrush( this.ForeColor ), new PointF( 0f, 0f ) );
}
else base.OnPaint( e );
}
#endregion
/// <summary>Required designer variable.</summary>
private System.ComponentModel.IContainer components = null;
/// <summary>Clean up any resources being used.</summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose( bool disposing )
{
if ( disposing && (components != null) )
components.Dispose();
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() =>
components = new System.ComponentModel.Container();
#endregion
}
}
4条答案
按热度按时间ezykj2lf1#
作为渲染模糊阴影的替代方法,一个性能更友好的选项可能是渲染阴影稍微向右下方偏移(如您最初建议的那样),但使用 * alpha透明度 *,以便阴影看起来不那么“实心”:
要给予如何从代码(如
OnPaint
方法)中调用它的示例,请执行以下操作:为了让事情变得更整洁,并获得更令人信服的阴影效果,我们可以修改上面的函数,通过稍微增加alpha透明度来绘制文本,一次在阴影的左边,一次稍微在阴影的右边,来模拟模糊效果:
下面是生成的输出的屏幕截图:
dy2hfwbg2#
可以尝试使用
Path
(如果可以从文本中生成路径?)和PathGradientBrush
或者你可以尝试对叠加图像做一些事情(这只是一个想法,这里有一个由
path
定义的发光物体的例子):vjrehmav3#
下面是创建阴影的WinForms Label控件的一个非常简化的实现:
1tu0hz3e4#
我知道这个答案可能一点帮助都没有,但是如果它只是静态文本,就用图像代替