2013-07-10 2 views
1

Я работаю над Adorner для Line в программе рисования с использованием WPF. Line рисуется в коде, а затем украшен моим обычным Adorner под названием LineAdorner. Мне удалось использовать Thumb для начальной и конечной точки Line. Он отлично работает для изменения размера. Моя проблема в том, что я не могу двигаться (перетащите &), как это сделать?Как улаживать большие пальцы с линией для перемещения строки в WPF custom Adorner

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

ответ

1

Вам нужно обрабатывать события 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); 
} 

Я также добавил некоторые вызовы InvalidateArrange() в обработчиках StartDragDelta и EndDragDelta, чтобы убедиться, что Thumbs перемещаются при перетаскивании.

+0

Хороший ответ, мне тоже нужно это. Но когда я пытаюсь это сделать, линия движется слишком быстро и улетает с холста. Что-то не так с методом 'SelectedLineOnMouseMove()'. Я позабочусь об этом после обеда. Вот рабочий пример: https://www.dropbox.com/s/6oxjp46vuj443wl/ShapeConnectors%20%282%29.zip?dl=0 –

+0

А, я вижу проблему. Вы не обновляете 'origin' после перемещения строки; он обновляется только тогда, когда пользователь сначала нажимает на мышь. Добавьте 'origin = e.GetPosition (строка);' прямо перед строкой 'InvalidateArrange()' в методе 'SelectedLineOnMouseMove()', и вы хороши. Спасибо за этот ответ. –

+0

Я не могу воспроизвести проблему, с которой вы столкнулись, но добавление строки, которую вы предлагаете, не делает ее ломающейся на моей стороне. Рад, что вы нашли ответ полезным. –