Это может быть не очень полезно, но способ, которым мы достигли такого типа вещей в других проектах, с которыми я был связан, заключается в реализации пользовательского «пера», который принимает линию, которую нужно нарисовать, вычисляет фактические штрихи, а затем рисует каждый штрих как отдельную линию с «настоящим» пером. Если бы вы делали что-то подобное, то вы могли бы на самом деле применить StartCap и / или EndCap уровня «пера» к каждому штриху.
Пользовательское «перо» должно принимать массив или последовательность длин штрихов / разрывов (или, может быть, перечисление стандартных стилей перьев, которые внутренне будут интерпретироваться как конкретные длины штрихов / разрывов).
Мы сделали это много лет назад с помощью системы рисования на основе GDI, где нам нужно было поддерживать больше стилей линий, чем встроенных стилей линий, которые поддерживал GDI.
Это интересное упражнение, но оно также, вероятно, доставляет больше хлопот, чем оно того стоит, если только вы ДЕЙСТВИТЕЛЬНО не должны рисовать тире, как вы описываете.
[EDIT]
Вот пример кода, как вы можете это сделать, если вы так склонны.
Первый - это метод расширения объекта Graphics. Требуется ручка, длина тире, длина зазора, начальная точка и конечная точка. Он интерполируется вдоль линии p1-> p2, рисуя сегмент длины «тире», а затем пропуская сегмент длины «промежутка». Переданное перо должно быть сплошным с наконечником стрелки (для достижения желаемого эффекта).
Код довольно грубый, но поведение более или менее таково:
Если входная линия короче, чем общая длина тире + промежуток, тогда линия рисуется как есть с использованием входного пера.
Если входная линия длиннее, чем общая длина тире + промежуток, то линии длины «тире» рисуются до тех пор, пока «остаток» строки не станет меньше длины тире + промежутка, после чего остаток будет отображаться как есть с ручка ввода.
Если вы хотите реализовать рисование контуров, вам придется интерполировать вокруг промежуточных вершин (если только вы не хотите удешевлять и просто вычислять тире для каждого сегмента независимо).
public static void DrawDashedLine(this Graphics g, Pen p, float dash, float gap, PointF s, PointF e)
{
float dx = e.X - s.X;
float dy = e.Y - s.Y;
float len = (float)Math.Sqrt(dx * dx + dy * dy);
float remainder = len;
float vx = dx / len;
float vy = dy / len;
if (len <= dash + gap)
{
g.DrawLine(p, s, e);
return;
}
PointF last = s;
while (remainder > dash + gap)
{
PointF p1 = new PointF(last.X, last.Y);
PointF p2 = new PointF(p1.X + vx*dash, p1.Y + vy*dash);
g.DrawLine(p, p1, p2);
last = new PointF(p2.X + vx*gap, p2.X + vy*gap);
remainder = remainder - dash - gap;
}
if (remainder > 0)
{
g.DrawLine(p, last, e);
}
}
}
Вот как бы вы назвали это:
private void button1_Click(object sender, EventArgs e)
{
using (var p = new Pen(Color.FromArgb(190, Color.Green), 5))
{
p.StartCap = LineCap.Round;
p.EndCap = LineCap.ArrowAnchor;
p.CustomEndCap = new AdjustableArrowCap(3, 3);
p.DashStyle = DashStyle.Solid;
var graph = this.CreateGraphics();
graph.DrawDashedLine(p, 20, 10, new PointF(20, 20), new PointF(500, 500));
}
}
Я не утверждаю, что код отличный (или даже обязательно хороший ;-), но он должен дать вам хорошую отправную точку, если вы действительно заинтересованы в рисовании вашей направленной линии.
Удачи!