我在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);
}
答案 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)。您必须使用方法GraphicsPath
或Region
绘制FillPath
或FillRegion
。在本演示中,我使用了GraphicsPath
,有两种有趣的方法可以帮助我们实现IsVisible
和IsOutlineVisible
的测试,在这种情况下我们只使用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项活动:MouseEnter
,MouseLeave
和Click
。这些事件与我们在正常控制中使用的事件非常相似。以下是您要测试的演示代码,它将在表单上呈现椭圆:
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);