绘制后如何将圆圈视为控件? – 移动和选择形状

实际上,点击每个圆圈之后我想要改变它的颜色,例如,我希望它变成红色,总的来说,我想把它当作对照。

我知道如何在双击图片框时绘制代表图表节点的圆圈。 我正在使用以下代码:

public Form1() { InitializeComponent(); pictureBox1.Paint += new PaintEventHandler(pic_Paint); } public Point positionCursor { get; set; } private List points = new List(); public int circleNumber { get; set; } private void pictureBox1_DoubleClick(object sender, EventArgs e) { positionCursor = this.PointToClient(new Point(Cursor.Position.X - 25, Cursor.Position.Y - 25)); points.Add(positionCursor); Label lbl = new Label(); lbl.BackColor = Color.Transparent; lbl.Font = new Font("Arial", 7); lbl.Size = new Size(20, 15); if (circleNumber >= 10) { lbl.Location = new Point(points[circleNumber].X + 3, points[circleNumber].Y + 6); } else { lbl.Location = new Point(points[circleNumber].X + 7, points[circleNumber].Y + 7); } lbl.Text = circleNumber.ToString(); pictureBox1.Controls.Add(lbl); circleNumber++; pictureBox1.Invalidate(); } private void pic_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; using (var pen = new Pen(Color.DimGray, 2)) { foreach (Point pt in points) { g.FillEllipse(Brushes.White, pt.X, pt.Y, 25, 25); g.DrawEllipse(pen, pt.X, pt.Y, 26, 26); } } } 

在此处输入图像描述

您需要执行命中测试以检查某个点是否在圆圈中。 作为选项,您可以向GraphicsPath添加圆圈,并使用路径的IsVisible方法检查该点是否为圆形。

例如,将ponit p作为直径为d的圆的左上角位置,您可以检查当前点击的点是否在圆圈中或者这样:

 var result = false; using (var path = new GraphicsPath()) { path.AddEllipse(pX, pY, d, d); result = path.IsVisible(e.Location); } 

示例代码

我看到你在这个主题中提出了多个问题。 所以在这里我分享一些代码来帮助你朝着正确的方向前进。

定义填充颜色,选定填充颜色,圆形大小,边框宽度等变量,以便在需要时更改它们。

 List Shapes = new List(); int selectedIndex = -1; Size size = new Size(25, 25); Color fillColor = Color.White; Color selectedfillCOlor = Color.Red; Color borderColor = Color.Gray; int borderWidth = 2; 

的DoubleClick

这里将圆圈添加到“ Shapes列表中。 将列的边界矩形添加到列表中就足够了。

 private void pic_MouseDoubleClick(object sender, MouseEventArgs e) { var p = e.Location; p.Offset(-size.Width / 2, -size.Height / 2); Shapes.Add(new Rectangle(p, size)); pic.Invalidate(); } 

点击

这里执行命中测试以检查该点是否在一个圆圈中。检查点击时是否按下Ctrl键,进行选择,然后将找到的索引设置为selectedIndex以在绘制时使用它。

 private void pic_MouseClick(object sender, MouseEventArgs e) { if (ModifierKeys != Keys.Control) return; selectedIndex = -1; for (int i = 0; i < Shapes.Count; i++) { using (var path = new GraphicsPath()) { path.AddEllipse(Shapes[i]); if (path.IsVisible(e.Location)) selectedIndex = i; } } pic.Invalidate(); } 

涂料

将图形对象的SmoothingMode设置为AntiAlias以获得更平滑的绘图。 然后在for循环中绘制形状,并注意selectedIndex为所选形状使用不同的填充颜色。

要绘制文本,您不需要使用label ,只需使用TextRenderer类绘制文本即可。

 private void pic_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; for (int i = 0; i < Shapes.Count; i++) { var selected = (selectedIndex == i); using (var brush = new SolidBrush(selected ? selectedfillCOlor : fillColor)) e.Graphics.FillEllipse(brush, Shapes[i]); using (var pen = new Pen(borderColor, borderWidth)) e.Graphics.DrawEllipse(pen, Shapes[i]); TextRenderer.DrawText(e.Graphics, (i + 1).ToString(), this.Font, Shapes[i], Color.Black, TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter); } } 

一些笔记

  • 最好将代码封装在从PictureBox或派生Control派生的新控件中,并将DoubleBuffered设置为true。

  • Circle封装在Circle类中是一个很好的选择, Circle类执行命中测试和圆形渲染。 特别是如果您想稍后移动它们或执行其他一些交互,或者让每个圆圈都拥有它自己的属性,如颜色等。

样本圈类

这是一个示例圆类,可以作为一个很好的起点。

 public class Circle { private Color selectedFillColor = Color.Red; private Color normalFillColor = Color.Red; private Color borderColor = Color.Red; private int borderWidth = 2; public Point Location { get; set; } public int Diameter { get; set; } public Rectangle Bounds { get { return new Rectangle(Location, new Size(Diameter, Diameter)); } } public bool HitTest(Point p) { var result = false; using (var path = new GraphicsPath()) { path.AddEllipse(Bounds); result = path.IsVisible(p); } return result; } public bool Selected { get; set; } public void Draw(Graphics g) { using (var brush = new SolidBrush( Selected ? selectedFillColor : normalFillColor)) g.FillEllipse(brush, Bounds); using (var pen = new Pen(borderColor, 2)) g.DrawEllipse(pen, Bounds); } }