代码之家  ›  专栏  ›  技术社区  ›  ephraim

自由形状的编辑点

  •  2
  • ephraim  · 技术社区  · 6 年前

    我有一些图形用户界面,让用户绘制成本有限的图形。 我使用graphicspath addline函数创建了它。

    现在,我想实现你可以在所附的microsoft word图像中看到的东西-“编辑点”。

    enter image description here

    我面临几个问题:

    1. 我的路径有成堆的“线”->每个线只有一个像素大小。我只想选择“关键点”。我该怎么做?这是一种“扁平化”的逆转,找不到这样的函数。

    2. 是否有一个现有的.NET函数来绘制路径周围的蓝色小矩形和绿色小圆圈?那么围绕每个选定点的矩形呢? enter image description here

    每一次的帮助,即使是部分的帮助,都是值得感激的。

    1 回复  |  直到 6 年前
        1
  •  2
  •   TaW    5 年前

    在你问题的第一部分,请看一下 this post ,它具有 List<Point> . 请注意 GraphicsPath.PathPoints 集合是只读的,因此必须从减少的点列表重新创建路径。

    关于第二部分的几点评论:

    • 没有创建句柄的内置例程。也不让他们做任何事。所以你需要为他们编码。

    • 我附加了一个简单的类 MoveLabel 可以用来做这个。它可以放在控件上或添加到 Controls 收集。然后你可以移动它。我添加了一个回调函数 MoveAction 在释放鼠标时处理结果。

    您可以添加..

    public delegate void Moved(MoveLabel sender);
    

    …到窗体类,或者,为了避免 Form1 引用,在窗体类之外,但在 莫维拉贝尔 .

    它可以直接用于移动点列表中的点:

    在面板上创建:

    var lab= new MoveLabel(Color.CadetBlue, 9, Point.Round(points[i]), i);
    lab.Parent = panel;
    lab.MoveAction = moved;
    

    一个简单的处理函数:

    void moved(MoveLabel sender)
    {
        points[sender.PointIndex] = 
                new Point(sender.Left - sender.Width / 2, sender.Top - sender.Height / 2);
        panel.Invalidate();
    }
    

    注意到 图形路径点 是只读的,所以我们必须从新点列表中重新创建路径!实际上一个人可以修改个人 PathPoints 在代码中,但结果不正确;因此必须复制 症结 到A PointF[] ,在那里修改它们并重新创建路径。对于复杂路径,最好使用 this overload

    如果要实现旋转(或其他转换),可以使用 GraphicsPath.Transform 功能。可以使用可移动标签来确定旋转或缩放数据。 这是我最小的 莫维拉贝尔 班级:

    public class MoveLabel : Label
    {
        public Form1.Moved MoveAction { get; set; }
        public int PointIndex { get; set; }
    
        private Point mDown = Point.Empty;
    
        public MoveLabel()
        {
            MouseDown += (ss, ee) => { mDown = ee.Location; };
            MouseMove += (ss, ee) => {
                if (ee.Button.HasFlag(MouseButtons.Left))
                {
                    Location = new Point(Left + ee.X - Width / 2, Top + ee.Y - Height / 2);
                    mDown = Location;
                }
            };
            MouseUp += (ss, ee) => { if (MoveAction != null) MoveAction(this);  };
        }
    
        public MoveLabel(Color c, int size, Point location, int pointIndex) : this()
        {
            BackColor = Color.CadetBlue;
            Size = new Size(size, size);
            Location = location;
            PointIndex = pointIndex;
        }
    }
    

    这也可以很好地从贝塞尔曲线移动点。通过添加呼叫 MoveAction(this); MouseMove 你可以得到实时更新的linq代码。确保 Panels DoubleBuffered 为此:

    例子:

    enter image description here


    顺便说一句:我刚来 this post 它显示了曲线或任何其他gdi+矢量图形可以很容易地保存到 emf ,保持向量质量!


    更新: 而不是 Panel ,这是一个 Container 你可以用一个 Picturebox 或A Label Autosize=false );两者都有 DoubleBuffered 打开“开箱即用”属性并支持绘图 面板 做。