2011-12-09 7 views
1

나는 그려진 선을 마우스로 움켜 잡으려고하고있다.마우스로 그려진 선을 옮기기

라인은 이미 Graphics.DrawLine(Pen P, Point A, Point B)으로 그려져 있습니다.

선 만들기 및 양식 그리기에 전혀 문제가 없습니다.

이 나는 ​​시도했다 :

  • GraphicsPath에 선을 추가 -이도 선 OnPaint을 그릴하지 않습니다. 내가 선을 잡고 어딘가를 드래그합니다 : MouseEventArgs e.Location가 (지금의 멀리 던져 계산) 몇 가지 기본적인 대수와 라인

    그래서

그것을 요약하는에있는 경우

  • 확인 e.Location이 라인에 있는지도 확인할 수 없습니다. 어떻게해야합니까?

    편집 : 이것은 GraphicsPath를 사용할 때 코드가 어떻게 표시되는지입니다. 나는 GraphicsPath를 사용하지 않는 경우

    나는이 다음 drawingShapes 방법

    if (s.thisShape == ShapeType.Line) { 
        g.DrawLine(pen, s.p1, s.p2); 
    } else { ... }` 
    

    . drawStuff에서

    : UserControl을 클래스 : 도형에서

    private void drawStuff_MouseDown(object sender, MouseEventArgs e) 
    { 
        pointRegion = e.Location; 
        for (int i = 0; i < Shapes.Count; i++) 
        { 
        if (Shapes[i].Region.IsVisible(pointRegion)) 
        { 
         isDragging = true; 
         count = i; 
         break; 
        } 
        } 
    } 
    
    private void drawStuff_MouseMove(object sender, MouseEventArgs e) 
    { 
        if (isDragging) 
        { 
        Shapes[count].moveWithDiff(pointRegion, e.Location); 
        pointRegion = e.Location; 
        Refresh(); 
        } 
    } 
    
    private void drawStuff_MouseUp(object sender, MouseEventArgs e) 
    { 
        isDragging = false; 
        Refresh(); 
    } 
    
    protected override void OnPaint(PaintEventArgs e) 
    { 
        base.OnPaint(e); 
        drawShapes(e.Graphics); 
    } 
    
    private void drawShapes(Graphics g) 
    { 
        temporaryPen = pennaLeft; 
        foreach (Shape s in Shapes) 
        { 
        g.FillRegion(temporaryPen, s.Region); 
        } 
    } 
    

    : UserControl을 클래스 :

    public void moveWithDiff(Point pr, Point mp) 
    { 
        Point p = new Point(); 
        if (this.thisShape == ShapeType.Line) 
        { 
        p.X = mp.X - pr.X; 
        p.Y = mp.Y - pr.Y; 
        this.p1.X += p.X; 
        this.p1.Y += p.Y; 
        this.p2.X += p.X; 
        this.p2.Y += p.Y; 
        } 
        RefreshPath(); 
    } 
    
    private void RefreshPath() 
    { 
        gPath = new GraphicsPath(); 
        switch (thisShape) 
        { 
        case ShapeType.Line: 
         gPath.AddLine(this.p1, this.p2); 
         break; 
        } 
        this.Region = new Region(gPath); 
    } 
    

    지금이조차 말했다 그러나 함께 선을 그어야하지 않는 경우 drawingShapes의 문 () 그것은 완벽하게 그으나 다른 곳으로 끌 수는 없습니다.

  • +0

    @HansPassant 나는 내가 희망하는 것을 충분히 편집하여 질문을 편집했다. 이제 직사각형 및 타원과 같은 다른 도형과 완벽하게 작동합니다. 단선 및 타원과 같이 선을 이동하지 않습니다. – NJS

    답변

    6

    기본 사항부터 시작하여 화면에 선을 표시해 보겠습니다.

    public class MyLine 
    { 
        public Pen pen { get; set; } 
        public Point Start { get; set; } 
        public Point End { get; set; } 
    
        public MyLine(Pen p, Point p1, Point p2) 
        { 
         pen = p; 
         Start = p1; 
         End = p2; 
        } 
    
        public float slope 
        { 
         get 
         { 
          return (((float)End.Y - (float)Start.Y)/((float)End.X - (float)Start.X)); 
         } 
        } 
        public float YIntercept 
        { 
         get 
         { 
          return Start.Y - slope*Start.X; 
         } 
        } 
    
        public bool IsPointOnLine(Point p, int cushion) 
        { 
         float temp = (slope * p.X + YIntercept); 
         if (temp >= (p.Y-cushion) && temp <=(p.Y+cushion)) 
         { 
          return true; 
         } 
         else 
         { 
          return false; 
         } 
        } 
    } 
    

    이 클래스는 우리의 인생을 더 쉽게 만드는 것입니다 몇 가지 도우미 기능을 제공 :이 프로세스 내가 나에게 제공하고자하는 기능의 일부를 처리 할 수있는 사용자 정의 클래스를 만들었습니다. 기울기와 Y 절편을 반환하는 속성이 있으므로 특정 점이 선 위에 있는지 확인할 수 있습니다. 그런 다음 점과 쿠션을 사용하는 도우미 함수 인 IsPointOnLine()을 제공합니다. 쿠션은 단순히 사용자가 실제로 돌아 가기 위해 줄 가까이에서 클릭하는 것을 허용하는 데 사용됩니다.

    다음으로는 폼의 Paint 이벤트에서 선을 인스턴스화하고 그것을 그릴려고하고있다 :

    이제
    MyLine m; 
    
    private void Form1_Load(object sender, EventArgs e) 
    { 
        m= new MyLine(Pens.Black, new Point(20, 20), new Point(40, 40)); 
    } 
    
    
    
    private void Form1_Paint(object sender, PaintEventArgs e) 
    { 
        e.Graphics.DrawLine(m.pen, m.Start, m.End);  
    } 
    

    응용 프로그램을 실행하고 40에 20, 20에서가는 선을 볼 수 있어야합니다, 40을 화면에 표시합니다.

    이제는 마우스와 마우스의 상호 작용을 처리하려고합니다. 따라서 MouseDown에서 클릭 지점이 선과 교차하는지 여부와 깃발을 설정하고 종점에서 델타를 유지하는지 확인합니다. MouseMove 이벤트에서 선이 클릭되었지만 해제되지 않았는지 확인하고 좌표를 적절히 재설정합니다.

    Point deltaStart; 
    Point deltaEnd; 
    bool dragging = false; 
    
    private void Form1_MouseDown(object sender, MouseEventArgs e) 
    { 
    
        if (e.Button == System.Windows.Forms.MouseButtons.Left && m.IsPointOnLine(e.Location, 5)) 
        { 
         dragging = true; 
         deltaStart = new Point(m.Start.X - e.Location.X, m.Start.Y - e.Location.Y); 
         deltaEnd = new Point(m.End.X - e.Location.X, m.End.Y - e.Location.Y); 
        } 
    } 
    
    private void Form1_MouseMove(object sender, MouseEventArgs e) 
    { 
        if (dragging && deltaStart != null && deltaEnd != null) 
        { 
         m.Start = new Point(deltaStart.X + e.Location.X, deltaStart.Y + e.Location.Y); 
         m.End = new Point(deltaEnd.X + e.Location.X, deltaEnd.Y + e.Location.Y); 
         this.Refresh(); 
        } 
    } 
    
    private void Form1_MouseUp(object sender, MouseEventArgs e) 
    { 
        dragging = false; 
    } 
    

    지금 당신이 라인의 5 개 픽셀 내에서 클릭 할 수 있어야하고 마우스로 이동이 있습니다 MouseUp 이벤트에서, 우리는 간단하게 우리의 깃발을 다시 설정합니다.

    코드에 추가 오류 처리가 필요한 부분이 있습니다 (특히 0 오류로 나누기 위해).

    +0

    내 프로그램에 맞지 않는 몇 가지 변경 사항이 있지만 완벽하게 작동합니다! 감사! :) – NJS

    +0

    아주 좋은 해결 방법이지만, 여러 줄을 그려야 할 경우 어떻게 그 각각을 끌겠습니까? –

    0

    는 당신이 쉽게로 잡아 할 수 있도록, 당신은 또한 사각형을 팽창 할 수

    if(rectangle.Contains(Point p)) 
    { 
        // do your move 
    } 
    

    를 사용할 수있는 라인의 폭과 라인의 길이 사각형을 만들 제안 :

    rectangle.Inflate(1, 1); 
    
    관련 문제