//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; } } }