Редактировать точки FreeShape - PullRequest
0 голосов
/ 06 июня 2018

У меня есть некоторый графический интерфейс, позволяющий пользователю рисовать costimized GraphicsPath.Я создал его с помощью функции GraphicsPath AddLine.

Теперь я хочу реализовать то, что вы видите на прикрепленном изображении Microsoft Word - «Редактировать точки».

enter image description here

Я столкнулся с несколькими проблемами:

  1. На моем пути есть полные "Линии" -> каждый размером только один пиксель.Я хочу выбрать только «ключевые точки».Как я могу это сделать?Это своего рода реверс "Flatten", не может найти такую ​​функцию.

  2. Существует ли существующая функция .Net для рисования маленьких синих прямоугольников и маленького зеленого круга вокругдорожка?а как насчет прямоугольников вокруг каждой выбранной точки?enter image description here

Буду признателен за любую помощь, даже частичную.

1 Ответ

0 голосов
/ 06 июня 2018

Для первой части вашего вопроса посмотрите на этот пост , который имеет функцию сокращения для List<Point>.Обратите внимание, что коллекция GraphicsPath.PathPoints доступна только для чтения, поэтому вам придется заново создать путь из списка сокращенных точек.

Несколько замечаний ко второй части:

  • Нет встроенной подпрограммы для создания дескрипторов.Ни заставлять их делать что-либо.Поэтому вам нужно написать для них код.

  • Я добавляю простой класс MoveLabel, который можно использовать для этого.Его можно поместить на элемент управления или добавить в его коллекцию Controls.Тогда вы можете переместить его.Я добавил функцию обратного вызова MoveAction для обработки результата при отпускании мыши.

Вы можете добавить ..

public delegate void Moved(MoveLabel sender);

.. к классу формы, или, чтобы избежать ссылки Form1, вне класса формыно в области действия MoveLabel.

. Может использоваться непосредственно для перемещения точек в списке точек:

Создать его на панели:

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();
}

Обратите внимание, что GraphicsPath.PathPoints только для чтения, поэтому мы должны заново создать путь из нового списка точек!На самом деле можно изменить индивидуальный PathPoints в коде, но результат не прилипает;поэтому нужно скопировать PathPoints в PointF[], изменить их там и заново создать путь.Для сложных путей лучше всего использовать эту перегрузку ..

Если вы хотите реализовать вращение (или другие преобразования), вы можете использовать функцию GraphicsPath.Transform .Вы можете использовать подвижные метки для определения данных поворота или масштабирования. Вот мой минимальный класс MoveLabel:

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


Кстати: я только что натолкнулся на этот пост , который показывает, насколько легко можно нарисовать кривую или любую другую векторную графику GDI +сохранено в emf, сохраняя качество вектора!


Обновление: Вместо Panel, который является элементом управления Container и не предназначен для рисования на вас.можно использовать Picturebox или LabelAutosize=false);оба имеют свойство DoubleBuffered, включенное из коробки, и поддерживают рисование лучше, чем Panels do.

...