Windows窗体绘制的椭圆选择和删除特别选择

时间:2013-11-29 06:01:29

标签: c# winforms drawing

我在Windows窗体上绘制了一些省略号。

'c#Window Form'可以在椭圆上'鼠标点击'并将其删除吗?..


评论代码

public void DrawCircle_Paint(object sender, PaintEventArgs e) 
{ 
    Pen pen = new Pen(Color.Black, 3); 
    Graphics gr = this.CreateGraphics(); 
    gr.DrawEllipse(pen, 40, 45, 20, 20); 
    Pen pen2 = new Pen(Color.Black, 3);  
    Graphics gr1 = this.CreateGraphics(); 
    gr.DrawEllipse(pen2, 30, 25, 38, 20); 
    Pen pen3 = new Pen(Color.Black, 3); 
    Graphics gr2 = this.CreateGraphics(); 
    gr.DrawEllipse(pen3, 35, 36, 68, 15); 
    Pen pen4 = new Pen(Color.Black, 3); 
    Graphics gr3 = this.CreateGraphics(); 
    gr.DrawEllipse(pen4, 50, 60, 67, 35); 
} 

3 个答案:

答案 0 :(得分:1)

是的,可能。

我假设您知道省略号的位置和尺寸,并将它们存储在列表中。然后你可以使用MouseDown并迭代省略号。例如,如果点在椭圆中,如何检查here

如果您发现点击的椭圆将其从列表中删除并重新绘制所有内容。

更新: 给你的代码。你不需要一直调用CreateGraphics。图形对象在PaintEventArgs(e.Graphics)中给出。此外,您不需要每次都创建一支笔。

public void DrawCircle_Paint(object sender, PaintEventArgs e) 
{ 
    Graphics gr = e.Graphics;
    using(Pen p = new Pen(Color.Black, 3))
    {
        gr.DrawEllipse(pen, 40, 45, 20, 20);
        gr.DrawEllipse(pen2, 30, 25, 38, 20); 
        gr.DrawEllipse(pen3, 35, 36, 68, 15); 
        gr.DrawEllipse(pen4, 50, 60, 67, 35); 
     }
}

答案 1 :(得分:1)

我刚试过这个演示,但还有很多工作要做。这只是一个演示,因为仍然缺少许多功能,并且不能确保内存泄漏问题不会发生。使用Graphics对象的某些方法直接绘制一些东西不会帮助你支持某些交互(比如hittesting)。您必须使用方法GraphicsPathRegion绘制FillPathFillRegion。在本演示中,我使用了GraphicsPath,有两种有趣的方法可以帮助我们实现IsVisibleIsOutlineVisible的测试,在这种情况下我们只使用IsVisible。现在是你的代码:

public class Ellipse : IDisposable
{
    GraphicsPath gp = new GraphicsPath();
    RectangleF rect;
    public Ellipse(Point center, float rx, float ry)
    {
        Center = center;
        RadiusX = rx;
        RadiusY = ry;
        Visible = true;
        rect = new RectangleF(Center.X - RadiusX, Center.Y - RadiusY, RadiusX * 2, RadiusY * 2);
        gp.AddEllipse(rect);
        BackColor = Color.Green;
        SelectedBackColor = Color.LimeGreen;
        BorderColor = Color.Transparent;
    }
    public event EventHandler Click;
    public event EventHandler MouseEnter;
    public event EventHandler MouseLeave;
    Point center;
    float rx, ry;
    Control canvas;
    bool entered;
    bool visible;
    Color backColor;
    Color borderColor;
    Color selectedColor;
    bool selected;
    public bool Selected
    {
        get { return selected; }
        set
        {
            if (selected != value)
            {
                selected = value;
                if (canvas != null) canvas.Invalidate(Rectangle.Ceiling(rect));
            }
        }
    }
    public bool Visible
    {
        get { return visible; }
        set
        {
            if (visible != value)
            {
                visible = value;
                if(canvas != null) canvas.Invalidate(Rectangle.Ceiling(rect));
            }
        }
    }
    public Control Canvas
    {
        get { return canvas; }
        set
        {
            if (canvas != value)
            {
                if(canvas != null) DetachCanvas(canvas);
                if (value != null)
                {
                    AttachCanvas(value);
                    value.Invalidate(Rectangle.Ceiling(rect));
                }                    
                canvas = value;
            }
        }
    }
    public Point Center
    {
        get { return center; }
        set
        {
            if (center != value)
            {
                int dx = value.X - center.X;
                int dy = value.Y - center.Y;
                rect.Offset(dx, dy);
                center = value;
                gp.Reset();
                gp.AddEllipse(rect);
                if (canvas != null) canvas.Invalidate(Rectangle.Ceiling(rect));
            }
        }
    }
    public float RadiusX
    {
        get { return rx; }
        set
        {
            if (rx != value)
            {
                rect.Width = rx * 2;
                rx = value;
                gp.Reset();
                gp.AddEllipse(rect);
                if (canvas != null) canvas.Invalidate(Rectangle.Ceiling(rect));
            }
        }
    }
    public float RadiusY
    {
        get { return ry; }
        set
        {
            if (ry != value)
            {
                rect.Height = ry * 2;
                ry = value;
                gp.Reset();
                gp.AddEllipse(rect);
                if (canvas != null) canvas.Invalidate(Rectangle.Ceiling(rect));
            }
        }
    }
    public Color BorderColor
    {
        get { return borderColor; }
        set
        {
            if (borderColor != value)
            {
                borderColor = value;
                if (canvas != null) canvas.Invalidate(Rectangle.Ceiling(rect));
            }
        }
    }
    public Color SelectedBackColor
    {
        get { return selectedColor; }
        set
        {
            if (selectedColor != value)
            {
                selectedColor = value;
                if (canvas != null) canvas.Invalidate(Rectangle.Ceiling(rect));
            }
        }
    }
    public Color BackColor
    {
        get { return backColor; }
        set
        {
            if (backColor != value)
            {
                backColor = value;
                if (canvas != null) canvas.Invalidate(Rectangle.Ceiling(rect));
            }
        }
    }
    private void Render(Graphics g)
    {            
        using(Pen p = new Pen(BorderColor))
        using (Brush b = new SolidBrush(selected ? SelectedBackColor : BackColor))
        {
            SmoothingMode sm = g.SmoothingMode;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillPath(b, gp);
            g.DrawPath(p, gp);
            g.SmoothingMode = sm;
        }
    }
    private void CanvasPaint(object sender, PaintEventArgs e)
    {
        if (Visible) Render(e.Graphics);
    }
    private void CanvasMouseMove(object sender, MouseEventArgs e)
    {
        var cv = sender as Control;
        if (gp.IsVisible(e.Location))
        {
            var handler = MouseEnter;
            if (handler != null && Visible)
            {
                handler(this, EventArgs.Empty);
            }
            entered = true;
        }
        else if (entered)
        {
            var handler = MouseLeave;
            if (handler != null && Visible)
            {
                handler(this, EventArgs.Empty);
            }
            entered = false;
        }
    }
    private void CanvasMouseClick(object sender, MouseEventArgs e){
        var cv = sender as Control;
        if (gp.IsVisible(e.Location))
        {
            var handler = Click;                
            if (handler != null && Visible) handler(this, EventArgs.Empty);
        }
    }
    private void AttachCanvas(Control canvas)
    {
        canvas.Paint += CanvasPaint;
        canvas.MouseMove += CanvasMouseMove;
        canvas.MouseClick += CanvasMouseClick;
    }
    private void DetachCanvas(Control canvas)
    {
        canvas.Paint -= CanvasPaint;
        canvas.MouseMove -= CanvasMouseMove;
        canvas.MouseClick -= CanvasMouseClick;
    }

    public void Dispose()
    {
        Visible = false;
        if (Canvas != null) Canvas.Invalidate(Rectangle.Ceiling(rect));
        Canvas = null;
        gp.Dispose();             
    }        
}

用法:我只实施了3项活动:MouseEnterMouseLeaveClick。这些事件与我们在正常控制中使用的事件非常相似。以下是您要测试的演示代码,它将在表单上呈现椭圆:

public partial class Form1 : Form
{
    public Form1()
    {            
        InitializeComponent();
        var e = new Ellipse(new Point(400, 400), 100, 100) { Canvas = this };
        e.MouseEnter += (s, ev) => {
            e.BackColor = Color.Red;
        };
        e.MouseLeave += (s, ev) => {
            e.BackColor = Color.Green;
        };
        e.Click += (s, ev) => {
            e.Visible = false; //Hide the ellipse
        };
    }
}

请注意,您可以为其他形状创建自己的类。

更新:我更新了Ellipse类并进行了一些修改以避免内存泄漏,要删除您只需要调用Dispose的椭圆,它将删除椭圆和您不能再使用它,对于List<Ellipse>的要求,请尝试:

//You have to handle `Ellipse.Click` to set the `Selected` manually, this is by design
//do this for every ellipses
Ellipse selectedEllipse;
//Use this handler for all the Click event of your ellipses
private void Ellipse_Click(object sender, EventArgs e){  
  var ellipse = sender as Ellipse;
  if(ellipse == selectedEllipse) return;
  if(selectedEllipse != null) selectedEllipse.Selected = false;
  ellipse.Selected = true;
  selectedEllipse = ellipse;
}
List<Ellipse> ellipses = ...; //this is your List<Ellipse>
for(int i = ellipses.Count - 1; i >= 0; i--){
  if(ellipses[i].Selected){
    ellipses[i].Dispose();
    ellipses.RemoveAt(i);
  }
}

可以修改每个Ellipse.Click处理Ellipse事件的代码,以允许多个选定的。这就是为什么在开始点击时没有选择硬编码的原因。

答案 2 :(得分:0)

尝试一下!

 Bitmap Painting;
 Pen Pen_Drawing;
 Graphics Graph_Drawing;

 Pen_Drawing.Dispose();
 Graph_Drawing.Dispose();
 Painting.Dispose();

 Painting = new Bitmap(500, 500);
 Pen_Drawing = new Pen(Color.FromArgb(95, 158, 160), 1f);
 Graph_Drawing = Graphics.FromImage(Painting);