簡體   English   中英

用鼠標移動畫線

[英]Moving a drawn line with the mouse

我正在嘗試通過用鼠標抓住繪制的線來移動它。

該線已使用Graphics.DrawLine(Pen P, Point A, Point B)繪制。

創建Line並將其繪制在表單上絕對沒有問題。

我試過了:

  • 將線添加到GraphicsPath甚至不會畫線OnPaint

  • 檢查MouseEventArgs e.Location是否在一些基本代數的行上(到目前為止,我已經放棄了計算)

因此,總結一下:我想抓住這條線並將其拖動到某處,但我什至無法檢查e.Location是否在該行上,我該怎么做?

編輯:這就是我使用GraphicsPath時代碼的外觀。

當我不使用GraphicsPath時:

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

在drawingShapes方法中。

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

從Shape: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()中使用if語句表示,它可以完美繪制,但是我不能將其拖動到其他位置。

讓我們從基礎開始,在屏幕上顯示一行。 我創建了一個自定義類,以處理此過程中我想使用的一些功能:

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(),它帶有一個點和一個緩沖。 緩沖墊僅用於允許用戶單擊足夠靠近線的位置以使其返回true。

接下來,我將實例化該行並將其繪制在Form的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);     
}

現在,您應該能夠運行您的應用程序,並在屏幕上看到一行從20,20到40,40的行。

現在,我想處理鼠標與線條的交互,因此在MouseDown上,我們將查看單擊點是否與線條相交,以及是否設置了標記並保留端點的增量。 在MouseMove事件上,我們將查看是否已單擊該行但未釋放該行,並適當地重置了坐標。 在MouseUp事件中,我們簡單地重置標志:

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個像素內單擊,並用鼠標移動它。

請注意,代碼中有些地方需要額外的錯誤處理,尤其是要處理0錯誤。

我建議您創建一個矩形,即線的寬度和線的長度,然后可以使用

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

您還可以使矩形膨脹以使其更容易抓取:

rectangle.Inflate(1, 1);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM