Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Это приложение основывается на примере коллекции рукописного ввода, демонстрируя удаление штрихов. Пример предоставляет пользователю меню с четырьмя режимами на выбор: включение рукописного ввода, стирание на остриях, стирание на пересечениях и стирание штрихов.
В режиме рукописного ввода объект InkCollector собирает рукописный ввод, как показано в примере сбора чернил .
В режиме стирания удаляются сегменты существующих росчерков рукописного ввода, которых пользователь касается курсором. Кроме того, вершины или пересечения могут быть обозначены красным кругом.
Наиболее интересные части этого примера лежат в обработчике событий OnPaint формы InkErase и в функциях стирания, вызываемых из обработчика событий OnMouseMove формы.
Окружение вершин и пересечений
Обработчик событий формы OnPaint сначала наносит штрихи, а в зависимости от режима работы приложения может найти и пометить все впадины или пересечения небольшим красным кругом. Кисп помечает точку, в которой штрих меняет направление резко. Пересечение обозначает точку, в которой один штрих пересекается с самим собой или другим штрихом.
Событие Paint происходит всякий раз, когда элемент управления перерисовывается.
Заметка
Пример заставляет форму перерисовывать себя при удалении штриха или изменении режима приложения, используя метод формы Refresh.
private void InkErase_OnPaint(object sender, PaintEventArgs e)
{
Strokes strokesToPaint = myInkCollector.Ink.Strokes;
myInkCollector.Renderer.Draw(e.Graphics, strokesToPaint);
switch (mode)
{
case ApplicationMode.CuspErase:
PaintCusps(e.Graphics, strokesToPaint);
break;
case ApplicationMode.IntersectErase:
PaintIntersections(e.Graphics, strokesToPaint);
break;
}
}
В PaintCuspsкод выполняет итерацию по каждому заостренному краю в каждом штрихе и рисует красный круг вокруг него. Свойство polylineCusps штриха возвращает индексы точек в стойке, которые соответствуют cus ps. Кроме того, обратите внимание на метод объекта InkSpaceToPixel, который преобразует точку в координаты, относящиеся к методу DrawEllipse.
private void PaintCusps(Graphics g, Strokes strokesToPaint)
{
foreach (Stroke currentStroke in strokesToPaint)
{
int[] cusps = currentStroke.PolylineCusps;
foreach (int i in cusps)
{
Point pt = currentStroke.GetPoint(i);
// Convert the X, Y position to Window based pixel coordinates
myInkCollector.Renderer.InkSpaceToPixel(g, ref pt);
// Draw a red circle as the cusp position
g.DrawEllipse(Pens.Red, pt.X-3, pt.Y-3, 6, 6);
}
}
}
В PaintIntersectionsкод выполняет итерацию по каждому штриху, чтобы найти его пересечения со всем набором штрихов. Обратите внимание, что методу FindIntersections штриха передается коллекция штрихов, и он возвращает массив индексов с плавающей запятой, представляющих пересечения. Затем код вычисляет координату X-Y для каждого пересечения и рисует красный круг вокруг него.
private void PaintIntersections(Graphics g, Strokes strokesToPaint)
{
foreach (Stroke currentStroke in strokesToPaint)
{
float[] intersections = currentStroke.FindIntersections(strokesToPaint);
}
}
Обработка пера с двумя концами
Три обработчика событий определены для объекта InkCollector для событий CursorDown, NewPacketsи Stroke. Каждый обработчик событий проверяет свойство Cursor объекта инвертированного, чтобы увидеть, какой конец пера используется. Когда перо перевернуто:
- Метод
myInkCollector_CursorDownделает штрих прозрачным. - Метод
myInkCollector_NewPacketsстирает штрихи. - Метод
myInkCollector_Strokeотменяет событие. события NewPackets создаются до события Stroke.
Отслеживание курсора
Будь то использование пользователем пера или мыши, создаются события MouseMove. Обработчик событий MouseMove сначала проверяет, является ли текущий режим режимом удаления, и если нажата любая кнопка мыши, и игнорирует событие, если эти состояния отсутствуют. Затем обработчик событий преобразует координаты пикселей для курсора в координаты в пространстве рукописного ввода с помощью метода PixelToInkSpace объекта Renderer и вызывает один из методов стирания кода в зависимости от текущего режима стирания.
Стирающиеся штрихи
Метод EraseStrokes получает местоположение курсора в пространстве рукописного ввода и создает коллекцию штрихов, находящихся в пределах HitTestRadius единиц. Параметр currentStroke указывает, что объект Stroke не должен быть удален. Затем коллекция штрихов удаляется из сборщика, а форма перерисовывается.
private void EraseStrokes(Point pt, Stroke currentStroke)
{
Strokes strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);
if (null!=currentStroke && strokesHit.Contains(currentStroke))
{
strokesHit.Remove(currentStroke);
}
myInkCollector.Ink.DeleteStrokes(strokesHit);
if (strokesHit.Count > 0)
{
this.Refresh();
}
}
Стирение на пересечениях
Метод EraseAtIntersections выполняет итерацию по каждому штриху, который попадает в радиус теста и создает массив пересечений между этим штрихом и всеми остальными штрихами в коллекции. Если пересечения не найдены, тогда весь штрих удаляется; в противном случае определяется ближайшая к тестовой точке точка на штрихе, и от нее определяются пересечения с обеих сторон, описывающие сегмент, который необходимо удалить.
Метод разделения объекта штриха используется для разделения сегмента от остальной части штриха, а затем удаляется сегмент, оставляя остальную часть штриха нетронутым. Как и в EraseStrokes, форма перерисовывается перед возвратом метода.
private void EraseAtIntersections(Point pt)
{
Strokes strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);
foreach (Stroke currentStroke in strokesHit)
{
float[] intersections = currentStroke.FindIntersections(myInkCollector.Ink.Strokes);
...
float findex = currentStroke.NearestPoint(pt);
...
strokeToDelete = currentStroke.Split(intersections[i]);
...
}
...
}
Стирание в точках перегиба
Для каждого штриха, попадающего в тестовый радиус, метод EraseAtCusps извлекает массив вершин из метода Stroke объекта PolylineCusps. Каждый конец штриха также является острием, поэтому если штрих имеет только два острия, то весь штрих удаляется; в противном случае находится ближайшая точка на штрихе к тестовой точке, и от этого определяются пересечения с обеих сторон этой точки, описывая сегмент, который нужно удалить.
Метод разделения объекта штриха используется для разделения сегмента от остальной части штриха, а затем удаляется сегмент, оставляя остальную часть штриха нетронутым. Как и в EraseStrokes, форма перерисовывается перед возвратом из метода.
private void EraseAtCusps(Point pt)
{
...
strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);
foreach (Stroke currentStroke in strokesHit)
{
int[] cusps = currentStroke.PolylineCusps;
...
float findex = currentStroke.NearestPoint(pt);
...
strokeToDelete = currentStroke.Split(cusps[i]);
myInkCollector.Ink.DeleteStroke(strokeToDelete);
...
}
...
}
Закрытие формы
Метод dispose формы удаляет объект InkCollector, myInkCollector.