2013-07-10 5 views
1

WPF를 사용하는 그리기 프로그램에서 Line에 대해 Adorner을 작업하고 있습니다. Line은 코드 숨김으로 그려지고 LineAdorner이라는 사용자 정의 Adorner으로 장식되었습니다. 나는 Line의 시작과 끝 지점에 Thumb을 사용했습니다. 크기 조정에 잘 작동합니다. 내 문제는 어떻게 할 수 있습니까? (& 드롭을 드래그) 선을 움직일 수 없습니까?WPF에서 선 이동을위한 줄이있는 정렬 방법 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 핸들러에서 드래그 할 때 엄지 손가락이 움직이는 지 확인하십시오.

+0

좋은 답변입니다.이 정보도 필요합니다. 그러나 이것을 시도하면 선이 너무 빨리 움직이고 캔버스에서 날아갑니다. 'SelectedLineOnMouseMove()'메서드로 뭔가 잘못되었습니다. 점심을 먹은 후 이것에 대해 자세히 살펴볼 것입니다. 다음은 작동하는 샘플입니다. https://www.dropbox.com/s/6oxjp46vuj443wl/ShapeConnectors%20%282%29.zip?dl=0 –

+0

아, 문제가 있습니다. 선을 이동 한 후에'origin'을 업데이트하지 않습니다; 사용자가 처음 마우스를 누를 때만 업데이트됩니다. 'SelectedLineOnMouseMove()'메소드의'InvalidateArrange()'줄 바로 앞에서'origin = e.GetPosition (line);'을 추가하면됩니다. 이 답변을 주셔서 감사합니다. –

+0

내가 겪고있는 문제를 재현하는 것처럼 보일 수는 없지만, 제안한 라인을 추가해도 내 편이 쉬지는 않습니다. 도움이 되셨다면 다행이라고 생각합니다. –