如何在C#中拖动和移动形状

如何在C#中拖动和移动形状,第1张

如何在C#中拖动和移动形状

要达到测试形状,您不需要线性代数。您可以

GraphicsPath
为您的形状创建,然后使用
GraphicsPath.IsVisible
GraphicsPath.IsOutlineVisible
方法执行命中测试。

  • 要检查路径中是否有点,例如填充的形状,请使用

    IsVisible

  • 要测试线条,曲线或空的形状,可以使用

    IsOutlineVisible

例如,您可以创建一个基本

IShape
接口,其中包含用于命中测试,绘图和移动的方法。然后在类中实现这些方法。您还可以创建一个
DrawingSurface
控件,该控件可以处理命中测试,绘图和移动
IShape
对象。

在下面的示例中,我们创建

IShape
接口
Line
Circle
类。我们也创建一个
DrawingSurface
控件。为了测试该示例,它足以将
DrawingSurface
控件放在a上
Form
并处理
Load
表单事件并添加一些形状,然后运行应用程序并尝试移动形状。

形状

该接口包含一些有用的方法,如果有任何类可以实现这些方法,则可以将它们用于绘图,命中测试和移动。在本示例的最后,您可以看到一个

DrawingSurface
可以
IShape
简单地与实现一起使用的控件:

public interface IShape{    GraphicsPath GetPath();    bool HitTest(Point p);    void Draw(Graphics g);    void Move(Point d);}

线

这是实现

IShape
接口的线类。在点击测试时,如果您单击行,则
HitTest
返回true。另外,为了让您更简单地选择行,我为命中测试添加了2分:

public class Line : IShape{    public Line() { LineWidth = 2; LineColor = Color.Black; }    public int LineWidth { get; set; }    public Color LineColor { get; set; }    public Point Point1 { get; set; }    public Point Point2 { get; set; }    public GraphicsPath GetPath()    {        var path = new GraphicsPath();        path.AddLine(Point1, Point2);        return path;    }    public bool HitTest(Point p)    {        var result = false;        using (var path = GetPath())        using (var pen = new Pen(LineColor, LineWidth + 2)) result = path.IsOutlineVisible(p, pen);        return result;    }    public void Draw(Graphics g)    {        using (var path = GetPath())        using (var pen = new Pen(LineColor, LineWidth)) g.DrawPath(pen, path);    }    public void Move(Point d)    {        Point1 = new Point(Point1.X + d.X, Point1.Y + d.Y);        Point2 = new Point(Point2.X + d.X, Point2.Y + d.Y);    }}

这是一个实现

IShape
接口的圈子类。如果您单击圆圈,则进行命中测试时,
HitTest
返回true:

public class Circle : IShape{    public Circle() { FillColor = Color.Black; }    public Color FillColor { get; set; }    public Point Center { get; set; }    public int Radious { get; set; }    public GraphicsPath GetPath()    {        var path = new GraphicsPath();        var p = Center;        p.Offset(-Radious, -Radious);        path.AddEllipse(p.X, p.Y, 2 * Radious, 2 * Radious);        return path;    }    public bool HitTest(Point p)    {        var result = false;        using (var path = GetPath()) result = path.IsVisible(p);        return result;    }    public void Draw(Graphics g)    {        using (var path = GetPath())        using (var brush = new SolidBrush(FillColor)) g.FillPath(brush, path);    }    public void Move(Point d)    {        Center = new Point(Center.X + d.X, Center.Y + d.Y);    }}

图纸表面

该控件绘制形状列表。此外,它还会执行命中测试,

MouseDown
并在拖动时移动形状。您应该添加一些形状,例如
Line
或添加
Circle
Shapes
控件集合中。

public class DrawingSurface : Control{    public List<IShape> Shapes { get; private set; }    IShape selectedShape;    bool moving;    Point previousPoint = Point.Empty;    public DrawingSurface() { DoubleBuffered = true; Shapes = new List<IShape>(); }    protected override void onMouseDown(MouseEventArgs e)    {        for (var i = Shapes.Count - 1; i >= 0; i--) if (Shapes[i].HitTest(e.Location)) { selectedShape = Shapes[i]; break; }        if (selectedShape != null) { moving = true; previousPoint = e.Location; }        base.onMouseDown(e);    }    protected override void onMouseMove(MouseEventArgs e)    {        if (moving) { var d = new Point(e.X - previousPoint.X, e.Y - previousPoint.Y); selectedShape.Move(d); previousPoint = e.Location; this.Invalidate();        }        base.onMouseMove(e);    }    protected override void onMouseUp(MouseEventArgs e)    {        if (moving) { selectedShape = null; moving = false; }        base.onMouseUp(e);    }    protected override void onPaint(PaintEventArgs e)    {        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;        foreach (var shape in Shapes) shape.Draw(e.Graphics);    }}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5567275.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-14
下一篇 2022-12-14

发表评论

登录后才能评论

评论列表(0条)

保存