图形绘制 - 操纵绘制的形状

时间:2014-12-01 02:57:15

标签: c# winforms graphics

我使用Graphics对象在表单上绘制矩形或椭圆(取决于所选内容)。在绘制这些图形对象后,有没有办法操纵这些图形对象?我指的是诸如调整大小,删除,拖动等操作。另外,值得一提的是,在同一个表单上绘制的多个形状可以重叠。

绘图本身看起来像这样,由ScrollableControl的OnPaint()事件触发 - 只需将这些方法传递给PaintEventArgs的Graphics对象。

protected override void Fill(System.Drawing.Graphics g, Brush b)
{
    g.FillEllipse(b, m_topLeft.X, m_topLeft.Y, m_width, m_height);
}

protected override void Draw(System.Drawing.Graphics g, Pen p)
{
    g.DrawEllipse(p, m_topLeft.X, m_topLeft.Y, m_width, m_height);
}

我希望能够点击一个形状,选择如何处理它并采取相应的行动。 我想也许我可以检查光标的位置是否在形状的边界内(m_topLeft,m_width和m_height数据成员)并从那里开始。尽管它确实有效,但它并没有处理潜在的重叠。选择的点可能属于两个(或更多)形状。

这是使用用户定义的参数绘制的两个重叠形状(矩形和椭圆形)的示例:

Example

1 个答案:

答案 0 :(得分:0)

不,在绘制完对象后,无法对屏幕上的对象进行微缩处理。您需要做的是拥有需要在屏幕上绘制的所有对象的列表,每当您想要添加,删除或操作该列表中的对象时,您需要重新绘制整个列表。您通常通过调用控件上的Invalidate()来执行此操作,这将调用Draw以再次调用,这通常会在foreach循环中对您想要绘制的对象集合进行迭代。

public YourControl : Control
{
    List<IDrawableObject> _itemsToDraw = new List<IDrawableObject>();

    protected override void Draw(System.Drawing.Graphics g, Pen p)
    {
        foreach(var item in _itemsToDraw)
        {
            item.Draw(g, p);
        }
    }

    protected override void OnMouseClick(MouseEventArgs e)
    {
         base.OnMouseClick(e);

         IDrawableObject clickedItem = _itemsToDraw.FirstOrDefault(x=> x.WasClicked(e.Location));

         if(clickedItem != null)
         {
             //Do something with the clicked item.
         }
    }
}

interface IDrawableObject
{
    void Draw(System.Drawing.Graphics g, Pen p);

    bool WasClicked(Point p)
}

private class Ellipse : IDrawableObject
{    
    Point m_topleft;
    int m_width;
    int m_height;

    //Snip stuff like constructors assigning the values to the private fields.

    public void Draw(System.Drawing.Graphics g, Pen p)
    {
        g.DrawEllipse(p, m_topLeft.X, m_topLeft.Y, m_width, m_height);
    }

    public bool WasClicked(Point p)
    {
         return p.X >= m_topLeft.X && p.X < m_topLeft.X + m_width 
             && p.Y >= m_topLeft.Y && p.Y < m_topLeft.Y + m_height;
    }
}

为了找到单击了哪个控件,您可以创建一个像WasClicked这样的方法,在单击时接收鼠标的XY并返回true或false。然后,您可以在从WasClicked函数返回true的集合中操作该对象。