I need to draw an arrow in WPF programatically. I remember that Windows Forms had primitives to draw an arrow, setting the Cap
to the Pen
.
mMyPen.CustomEndCap =
new AdjustableArrowCap(arrowSize, arrowSize, true);
Is it possible with WPF?
我以前用过 Charles Petzold 的 ArrowLine。
我创建了以下方法,为带箭头的线创建 PointCollection:
private const double _maxArrowLengthPercent = 0.3; // factor that determines how the arrow is shortened for very short lines
private const double _lineArrowLengthFactor = 3.73205081; // 15 degrees arrow: = 1 / Math.Tan(15 * Math.PI / 180);
public static PointCollection CreateLineWithArrowPointCollection(Point startPoint, Point endPoint, double lineWidth)
{
Vector direction = endPoint - startPoint;
Vector normalizedDirection = direction;
normalizedDirection.Normalize();
Vector normalizedlineWidenVector = new Vector(-normalizedDirection.Y, normalizedDirection.X); // Rotate by 90 degrees
Vector lineWidenVector = normalizedlineWidenVector * lineWidth * 0.5;
double lineLength = direction.Length;
double defaultArrowLength = lineWidth * _lineArrowLengthFactor;
// Prepare usedArrowLength
// if the length is bigger than 1/3 (_maxArrowLengthPercent) of the line length adjust the arrow length to 1/3 of line length
double usedArrowLength;
if (lineLength * _maxArrowLengthPercent < defaultArrowLength)
usedArrowLength = lineLength * _maxArrowLengthPercent;
else
usedArrowLength = defaultArrowLength;
// Adjust arrow thickness for very thick lines
double arrowWidthFactor;
if (lineWidth <= 1.5)
arrowWidthFactor = 3;
else if (lineWidth <= 2.66)
arrowWidthFactor = 4;
else
arrowWidthFactor = 1.5 * lineWidth;
Vector arrowWidthVector = normalizedlineWidenVector * arrowWidthFactor;
// Now we have all the vectors so we can create the arrow shape positions
var pointCollection = new PointCollection(7);
Point endArrowCenterPosition = endPoint - (normalizedDirection * usedArrowLength);
pointCollection.Add(endPoint); // Start with tip of the arrow
pointCollection.Add(endArrowCenterPosition + arrowWidthVector);
pointCollection.Add(endArrowCenterPosition + lineWidenVector);
pointCollection.Add(startPoint + lineWidenVector);
pointCollection.Add(startPoint - lineWidenVector);
pointCollection.Add(endArrowCenterPosition - lineWidenVector);
pointCollection.Add(endArrowCenterPosition - arrowWidthVector);
return pointCollection;
}
您可以使用以下代码轻松创建线条形状:
var points = CreateLineWithArrowPointCollection(new Point(0, 0), new Point(200, 100), 5);
var polygon = new Polygon();
polygon.Points = points;
polygon.Fill = Brushes.Red;
RootCanvas.Children.Add(polygon);
该代码还支持缩短短线的箭头。