如何用线条排列拇指,以便在WPF自定义装饰器中移动线条

本文关键字:自定义 移动 WPF 排列 何用线 | 更新日期: 2023-09-27 18:21:52

我正在使用WPF在绘图程序中为Line编写AdornerLine是在代码后面绘制的,然后用我的自定义Adorner(称为LineAdorner)装饰。我已经设法使用Thumb作为Line的起点和终点。它可以很好地调整大小。我的问题是我不能移动(拖放)线,怎么做?

public class ResizingAdorner : Adorner
{
    // Resizing adorner uses Thumbs for visual elements.  
    // The Thumbs have built-in mouse input handling.
    //Thumb topLeft, topRight, bottomLeft, bottomRight;
    private Thumb startThumb;
    private Thumb endThumb;
    private Line selectedLine;
    private Point startPoint;
    private Point endPoint;
    // To store and manage the adorner's visual children.
    VisualCollection visualChildren;
    bool IsControlModeOn = false;
    // Override the VisualChildrenCount and GetVisualChild properties to interface with 
    // the adorner's visual collection.
    protected override int VisualChildrenCount { get { return visualChildren.Count; } }
    protected override Visual GetVisualChild(int index) { return visualChildren[index]; }
    // Initialize the ResizingAdorner.
    public ResizingAdorner(UIElement adornedElement)
        : base(adornedElement)
    {
        visualChildren = new VisualCollection(this);
        selectedLine = AdornedElement as Line;
        startThumb = new Thumb { Cursor = Cursors.Hand, Width = 8, Height = 8, Background = Brushes.Green };
        endThumb = new Thumb { Cursor = Cursors.Hand, Width = 8, Height = 8, Background = Brushes.BlueViolet };
        startThumb.DragDelta += StartDragDelta;
        endThumb.DragDelta += EndDragDelta;
        startThumb.DragCompleted += new DragCompletedEventHandler(startThumb_DragCompleted);
        endThumb.DragCompleted += new DragCompletedEventHandler(endThumb_DragCompleted);
        visualChildren.Add(startThumb);
        visualChildren.Add(endThumb);
    }

    public event EndDragDeltaEvent endDragDeltaEvent;
    public delegate void EndDragDeltaEvent(object obj, DragCompletedEventArgs e, bool isEnd);
    void startThumb_DragCompleted(object sender, DragCompletedEventArgs e)
    {
        if (endDragDeltaEvent != null)
            endDragDeltaEvent(selectedLine, e, false);
    }
    void endThumb_DragCompleted(object sender, DragCompletedEventArgs e)
    {
        if (endDragDeltaEvent != null)
            endDragDeltaEvent(selectedLine, e, true);
    }
    // Arrange the Adorners.
    protected override Size ArrangeOverride(Size finalSize)
    {
        selectedLine = AdornedElement as Line;
        double left = Math.Min(selectedLine.X1, selectedLine.X2);
        double top = Math.Min(selectedLine.Y1, selectedLine.Y2);
        var startRect = new Rect(selectedLine.X1 - (startThumb.Width / 2), selectedLine.Y1 - (startThumb.Width / 2), startThumb.Width, startThumb.Height);
        startThumb.Arrange(startRect);
        var endRect = new Rect(selectedLine.X2 - (endThumb.Width / 2), selectedLine.Y2 - (endThumb.Height / 2), endThumb.Width, endThumb.Height);
        endThumb.Arrange(endRect);
        return finalSize;
    }
    private void StartDragDelta(object sender, DragDeltaEventArgs e)
    {
        Point position = Mouse.GetPosition(this);
        selectedLine.X1 = position.X;
        selectedLine.Y1 = position.Y;
    }
    // Event for the Thumb End Point
    private void EndDragDelta(object sender, DragDeltaEventArgs e)
    {
        Point position = Mouse.GetPosition(this);
        selectedLine.X2 = position.X;
        selectedLine.Y2 = position.Y;
    }
    protected override void OnRender(DrawingContext drawingContext)
    {
        if (AdornedElement is Line)
        {
            selectedLine = AdornedElement as Line;
            startPoint = new Point(selectedLine.X1, selectedLine.Y1);
            endPoint = new Point(selectedLine.X2, selectedLine.Y2);
        }
    }
}

如何用线条排列拇指,以便在WPF自定义装饰器中移动线条

您需要处理线路上的MouseDown、MouseMove和MouseUp事件才能做到这一点:

在构造函数中为这些事件添加处理程序

selectedLine.MouseLeftButtonDown += SelectedLineOnMouseLeftButtonDown;
selectedLine.MouseMove += SelectedLineOnMouseMove;
selectedLine.MouseLeftButtonUp += SelectedLineOnMouseLeftButtonUp;

实现方式类似于

private Point origin;
private void SelectedLineOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{
    e.Handled = true;
    Line line = (Line) sender;
    line.CaptureMouse();
    startPoint = new Point(line.X1, line.Y1);
    endPoint = new Point(line.X2, line.Y2);
    origin = e.GetPosition(line);
    base.OnMouseLeftButtonDown(e);
}
private void SelectedLineOnMouseMove(object sender, MouseEventArgs e) 
{
    base.OnMouseMove(e);
    Line line = (Line) sender;
    if (e.MouseDevice.LeftButton == MouseButtonState.Pressed) 
    {
        Point position = e.GetPosition(this);
        e.Handled = true;
        double horizontalDelta = position.X - origin.X;
        double verticalDelta = position.Y - origin.Y;
        line.X1 = startPoint.X + horizontalDelta;
        line.X2 = endPoint.X + horizontalDelta;
        line.Y1 = startPoint.Y + verticalDelta;
        line.Y2 = endPoint.Y + verticalDelta;
        InvalidateArrange();
    }
    else 
    {
        line.ReleaseMouseCapture();
    }
}
private void SelectedLineOnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
{
    Line line = (Line) sender;
    line.ReleaseMouseCapture();
    e.Handled = true;
    base.OnMouseLeftButtonUp(e);
}

我还在StartDragDelta和EndDragDelta处理程序中添加了一些InvalidateArrange()调用,以确保拇指在拖动时移动。