//Customize LineArrow
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows;
namespace WpfApp249
{
public sealed class LineArrow : Shape
{
public static readonly DependencyProperty X1Property =
DependencyProperty.Register("X1", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty Y1Property =
DependencyProperty.Register("Y1", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty X2Property =
DependencyProperty.Register("X2", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty Y2Property =
DependencyProperty.Register("Y2", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty HeadHeightProperty =
DependencyProperty.Register("HeadHeight", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty HeadWidthProperty =
DependencyProperty.Register("HeadWidth", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
[TypeConverter(typeof(LengthConverter))]
public double X1
{
get { return (double)base.GetValue(X1Property); }
set { base.SetValue(X1Property, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double X2
{
get { return (double)base.GetValue(X2Property); }
set { base.SetValue(X2Property, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double Y1
{
get { return (double)base.GetValue(Y1Property); }
set { base.SetValue(Y1Property, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double Y2
{
get { return (double)base.GetValue(Y2Property); }
set { base.SetValue(Y2Property, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double HeadHeight
{
get { return (double)base.GetValue(HeadHeightProperty); }
set { base.SetValue(HeadHeightProperty, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double HeadWidth
{
get { return (double)base.GetValue(HeadWidthProperty); }
set { base.SetValue(HeadWidthProperty, value); }
}
protected override Geometry DefiningGeometry
{
get
{
// Create a StreamGeometry for describing the shape
StreamGeometry geometry = new StreamGeometry();
geometry.FillRule = FillRule.EvenOdd;
using (StreamGeometryContext context = geometry.Open())
{
InternalDrawArrowGeometry(context);
}
// Freeze the geometry for performance benefits
geometry.Freeze();
return geometry;
}
}
/// <summary>
/// Draws an Arrow
/// </summary>
private void InternalDrawArrowGeometry(StreamGeometryContext context)
{
double theta = Math.Atan2(Y1 - Y2, X1 - X2);
double sint = Math.Sin(theta);
double cost = Math.Cos(theta);
Point pt1 = new Point(X1, this.Y1);
Point pt2 = new Point(X2, this.Y2);
Point pt3 = new Point(
X2 + (HeadWidth * cost - HeadHeight * sint),
Y2 + (HeadWidth * sint + HeadHeight * cost));
Point pt4 = new Point(
X2 + (HeadWidth * cost + HeadHeight * sint),
Y2 - (HeadHeight * cost - HeadWidth * sint));
context.BeginFigure(pt1, true, false);
context.LineTo(pt2, true, true);
context.LineTo(pt3, true, true);
context.LineTo(pt2, true, true);
context.LineTo(pt4, true, true);
}
}
}
![]()
//Customize control
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows;
namespace WpfApp249
{
public sealed class LineArrow : Shape
{
public static readonly DependencyProperty X1Property =
DependencyProperty.Register("X1", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty Y1Property =
DependencyProperty.Register("Y1", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty X2Property =
DependencyProperty.Register("X2", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty Y2Property =
DependencyProperty.Register("Y2", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty HeadHeightProperty =
DependencyProperty.Register("HeadHeight", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
public static readonly DependencyProperty HeadWidthProperty =
DependencyProperty.Register("HeadWidth", typeof(double), typeof(LineArrow), new PropertyMetadata(0.0));
[TypeConverter(typeof(LengthConverter))]
public double X1
{
get { return (double)base.GetValue(X1Property); }
set { base.SetValue(X1Property, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double X2
{
get { return (double)base.GetValue(X2Property); }
set { base.SetValue(X2Property, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double Y1
{
get { return (double)base.GetValue(Y1Property); }
set { base.SetValue(Y1Property, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double Y2
{
get { return (double)base.GetValue(Y2Property); }
set { base.SetValue(Y2Property, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double HeadHeight
{
get { return (double)base.GetValue(HeadHeightProperty); }
set { base.SetValue(HeadHeightProperty, value); }
}
[TypeConverter(typeof(LengthConverter))]
public double HeadWidth
{
get { return (double)base.GetValue(HeadWidthProperty); }
set { base.SetValue(HeadWidthProperty, value); }
}
protected override Geometry DefiningGeometry
{
get
{
// Create a StreamGeometry for describing the shape
StreamGeometry geometry = new StreamGeometry();
geometry.FillRule = FillRule.EvenOdd;
using (StreamGeometryContext context = geometry.Open())
{
InternalDrawArrowGeometry(context);
}
// Freeze the geometry for performance benefits
geometry.Freeze();
return geometry;
}
}
/// <summary>
/// Draws an Arrow
/// </summary>
private void InternalDrawArrowGeometry(StreamGeometryContext context)
{
double theta = Math.Atan2(Y1 - Y2, X1 - X2);
double sint = Math.Sin(theta);
double cost = Math.Cos(theta);
Point pt1 = new Point(X1, this.Y1);
Point pt2 = new Point(X2, this.Y2);
Point pt3 = new Point(
X2 + (HeadWidth * cost - HeadHeight * sint),
Y2 + (HeadWidth * sint + HeadHeight * cost));
Point pt4 = new Point(
X2 + (HeadWidth * cost + HeadHeight * sint),
Y2 - (HeadHeight * cost - HeadWidth * sint));
context.BeginFigure(pt1, true, false);
context.LineTo(pt2, true, true);
context.LineTo(pt3, true, true);
context.LineTo(pt2, true, true);
context.LineTo(pt4, true, true);
}
}
}
//mainwindow.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp249
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Random rnd { get; set; }
private double width { get; set; }
private double height { get; set; }
private int xDelta = 100;
private int yDelta = 50;
private Canvas cvs { get; set; }
private ScaleTransform cvsScaler { get; set; }
public MainWindow()
{
InitializeComponent();
this.MouseWheel += Window_MouseWheel;
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
rnd = new Random();
width = this.ActualWidth;
height = this.ActualHeight;
cvs = new Canvas();
TransformGroup tg = new TransformGroup();
cvsScaler = new ScaleTransform();
if(!tg.Children.Contains(cvsScaler))
{
tg.Children.Add(cvsScaler);
}
cvs.RenderTransform = tg;
DrawLineArrows();
}
private void DrawLineArrows()
{
for(int i=0;i<5;i++)
{
LineArrow la = new LineArrow();
la.X1=rnd.Next(0,(int)width);
la.Y1= rnd.Next(0, (int)height);
la.X2 = la.X1 + 100;
la.Y2 = la.Y1 + 100;
la.HeadHeight = 10;
la.HeadWidth = 10;
la.Stroke = new SolidColorBrush(Colors.Red);
la.StrokeThickness = 4;
if(!cvs.Children.Contains(la))
{
cvs.Children.Add(la);
}
}
for (int i = 0; i < 5; i++)
{
LineArrow la = new LineArrow();
la.X1 = rnd.Next(0, (int)width);
la.Y1 = rnd.Next(0, (int)height);
la.X2 = la.X1 - 100;
la.Y2 = la.Y1 - 100;
la.HeadHeight = 10;
la.HeadWidth = 10;
la.Stroke = new SolidColorBrush(Colors.Green);
la.StrokeThickness = 4;
if (!cvs.Children.Contains(la))
{
cvs.Children.Add(la);
}
}
for (int i = 0; i < 5; i++)
{
LineArrow la = new LineArrow();
la.X1 = rnd.Next(0, (int)width);
la.Y1 = rnd.Next(0, (int)height);
la.X2 = la.X1 + 100;
la.Y2 = la.Y1 - 100;
la.HeadHeight = 10;
la.HeadWidth = 10;
la.Stroke = new SolidColorBrush(Colors.Blue);
la.StrokeThickness = 4;
if (!cvs.Children.Contains(la))
{
cvs.Children.Add(la);
}
}
for (int i = 0; i < 5; i++)
{
LineArrow la = new LineArrow();
la.X1 = rnd.Next(0, (int)width);
la.Y1 = rnd.Next(0, (int)height);
la.X2 = la.X1 -100;
la.Y2 = la.Y1 + 100;
la.HeadHeight = 10;
la.HeadWidth = 10;
la.Stroke = new SolidColorBrush(Colors.Orange);
la.StrokeThickness = 4;
if (!cvs.Children.Contains(la))
{
cvs.Children.Add(la);
}
}
this.Content = cvs;
}
private void Window_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (e.Delta > 0)
{
cvsScaler.ScaleX *= 1.2;
cvsScaler.ScaleY *= 1.2;
}
else
{
cvsScaler.ScaleX /= 1.2;
cvsScaler.ScaleY /= 1.2;
}
cvsScaler.CenterX = 0;
cvsScaler.CenterY = 0;
}
}
}