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

时间:2016-07-13 08:00:47

标签: c# .net winforms gdi+ picturebox

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

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

        public Form1()
    {
        InitializeComponent();

        pictureBox1.Paint += new PaintEventHandler(pic_Paint);
    }

    public Point positionCursor { get; set; }
    private List<Point> points = new List<Point>();
    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);
            }
        }
    }

enter image description here

1 个答案:

答案 0 :(得分:8)

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

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

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

示例代码

我发现您在本主题中提出了多个问题。所以我在这里分享一些代码来帮助你朝着正确的方向发展。

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

List<Rectangle> Shapes = new List<Rectangle>();
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 键在单击时是否关闭,进行选择,然后将找到的索引设置为{{1}在绘画时使用它。

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以获得更平滑的绘图。然后在for循环中绘制形状,并注意AntiAlias为所选形状使用不同的填充颜色。

要绘制文字,您不需要使用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设置为true。

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

示例圆类

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

Circle