在本文中,将探讨如何使用C#创建两个自定义控件,以模仿Photoshop中的效果,如阴影、斜面和浮雕效果。将从数学基础开始,然后逐步构建控件,并处理用户点击事件,最后创建自定义事件以提高控件的专业性。
为了创建这些控件,需要了解一些基本的数学知识,包括勾股定理、单位圆和三角函数。
勾股定理允许计算直角三角形的斜边(最长边)。公式如下:
a^2 + b^2 = c^2
因此,斜边c总是等于a^2 + b^2的平方根。
由于将处理角度和圆,熟悉单位圆的格式会很有帮助。单位圆是一个以(0, 0)为中心,半径为1的圆。角度0从点(1, 0)[右侧]开始,并逆时针增加。因此,角度90在(0, 1),角度180在(-1, 0),角度270在(0, -1),360回到0点。
只需要三个基本的三角函数:正弦(sin)、余弦(cos)和正切(tan)。记住soh cah toa,知道三角形中的正弦等于对边除以斜边,余弦等于邻边除以斜边,正切等于对边除以邻边。
两个自定义控件将共享两个重要函数:一个是根据角度和半径返回圆上相应点的位置,另一个是相反的操作,根据点(X, Y)找到最接近的角度。
将从绘制控件的背景开始,然后处理用户点击事件,并创建自定义事件。
两个控件的背景将相同:使用2点画笔绘制圆的轮廓,填充40%不透明度(大约100值)的白色,以及在控件中心的3x3像素正方形。
protected override void OnPaint(PaintEventArgs e)
{
// ...
Draw
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawEllipse(outline, drawRegion);
g.FillEllipse(fill, drawRegion);
// ...Marker
g.SmoothingMode = SmoothingMode.HighSpeed;
g.FillRectangle(Brushes.Black, originSquare);
// ...
}
重要的是要注意SmoothingMode属性。在绘制圆时将其设置为AntiAlias,使控件看起来平滑且专业。但是,如果用AntiAlias绘制正方形,边缘会变得模糊。解决方法是将SmoothingMode设置回HighSpeed,使边缘再次变得锐利。
由于XYToDegrees函数,处理用户点击非常简单。为了成功模仿Photoshop版本的控件行为,需要设置MouseDown和MouseMove事件。这样,值就可以实时更新。
private int findNearestAngle(Point mouseXY)
{
int thisAngle = (int)XYToDegrees(mouseXY, origin);
if (thisAngle != 0)
return thisAngle;
else
return -1;
}
高度控件需要一个额外的步骤,即计算自定义控件中心和鼠标点击点之间的距离。
private int findAltitude(Point mouseXY)
{
float distance = getDistance(mouseXY, origin);
int alt = 90 - (int)(90.0f * (distance / origin.X));
if (alt < 0) alt = 0;
return alt;
}
在Photoshop中测量的高度是90,当选定的点正好在原点上,当它在控件边缘时为0。因此,通过找到半径长度和点击点与原点之间长度的比率来计算高度。然后从90中减去它,基本上“翻转”值(0距离处为90)。
为了使自定义控件更加专业,它们需要能够在其值发生变化时通过程序发出警报。这就是自定义事件的用武之地。
public delegate void AngleChangedDelegate();
public event AngleChangedDelegate AngleChanged;
只需要在自定义控件内更改Angle属性时调用AngleChanged(确保它不是null),每当改变Angle属性时。
在构建这些控件时,可能会遇到一些限制和需要改进的地方。
没有!.NET Framework 2.0及以上版本带有DoubleBuffer属性,只需要在构建控件时将其设置为true。框架会确保控件被平滑重绘。
由于两个控件都依赖于假设半径始终相等的数学,因此控件的宽度和高度尺寸必须始终相等,以便控件看起来和工作正确。
没有包括控件背景和轮廓颜色的属性,因为追求的是Photoshop的外观。但是,查看代码,会发现更改颜色以满足个人喜好或甚至使其动态化并不困难。