Создание элемента управления рукописным вводом
Вы можете создать пользовательский элемент управления, динамически и статически отображает рукописные данные. То есть отрисовку рукописных фрагментов, как пользователь рисует штрих, вызывая рукописный ввод «поток» от планшетного пера и отображения рукописного ввода после него добавляется к элементу управления, либо с помощью пера, вставленный из буфера обмена, или загрузить из файла. Для динамического отображения рукописного ввода, необходимо использовать элемент управления DynamicRenderer. Для статического отображения рукописного ввода, необходимо переопределить методы событий пера (OnStylusDown, OnStylusMove, и OnStylusUp) для сбора StylusPoint данные, создавать штрихи и добавить их в InkPresenter (отображает рукописные данные в элементе управления).
В этом разделе содержатся следующие подразделы:
Практическое руководство. Сбор данных точек пера и создание рукописных штрихов
Практическое руководство. Включить элемент управления принимать ввод от мыши
С помощью дополнительных подключаемых модулей и DynamicRenderers
Практическое руководство. Сбор данных точек пера и создание рукописных штрихов
Чтобы создать элемент управления, который собирает и управляет рукописного ввода штрихов сделайте следующее:
Наследуйте класс от Control или одного из классов, производный от Control, такие как Label.
using System; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Input.StylusPlugIns; using System.Windows.Controls; using System.Windows;
class InkControl : Label {
}
Добавить InkPresenter в классе и задайте Content свойство к новому InkPresenter.
InkPresenter ip; public InkControl() { // Add an InkPresenter for drawing. ip = new InkPresenter(); this.Content = ip; }
Присоединение RootVisual из DynamicRenderer для InkPresenter путем вызова AttachVisuals метод и добавьте DynamicRenderer для StylusPlugIns коллекции. Это позволяет InkPresenter отображать рукописные данные по мере сбора данных точек пера элементом управления.
public InkControl() {
// Add a dynamic renderer that // draws ink as it "flows" from the stylus. dr = new DynamicRenderer(); ip.AttachVisuals(dr.RootVisual, dr.DrawingAttributes); this.StylusPlugIns.Add(dr); }
Переопределите метод OnStylusDown . В этом методе, захватывающий перо вызовом Capture. При захвате пера, элемент управления будет продолжать получать StylusMove и StylusUp события даже в том случае, если перо покидает границы элемента управления. Это не является строго обязательным, но почти всегда желательно для удобства работы пользователей. Создайте новый StylusPointCollection для сбора StylusPoint данных. Наконец, добавьте начального набора StylusPoint данные StylusPointCollection.
protected override void OnStylusDown(StylusDownEventArgs e) { // Capture the stylus so all stylus input is routed to this control. Stylus.Capture(this); // Allocate memory for the StylusPointsCollection and // add the StylusPoints that have come in so far. stylusPoints = new StylusPointCollection(); StylusPointCollection eventPoints = e.GetStylusPoints(this, stylusPoints.Description); stylusPoints.Add(eventPoints); }
Переопределить OnStylusMove метод и добавьте StylusPoint данные StylusPointCollection объект, который был создан ранее.
protected override void OnStylusMove(StylusEventArgs e) { if (stylusPoints == null) { return; } // Add the StylusPoints that have come in since the // last call to OnStylusMove. StylusPointCollection newStylusPoints = e.GetStylusPoints(this, stylusPoints.Description); stylusPoints.Add(newStylusPoints); }
Переопределить OnStylusUp метод и создайте новый Stroke с StylusPointCollection данных. Добавьте новые Stroke созданной вами для Strokes коллекцию InkPresenter и освободить захват пера.
protected override void OnStylusUp(StylusEventArgs e) { if (stylusPoints == null) { return; } // Add the StylusPoints that have come in since the // last call to OnStylusMove. StylusPointCollection newStylusPoints = e.GetStylusPoints(this, stylusPoints.Description); stylusPoints.Add(newStylusPoints); // Create a new stroke from all the StylusPoints since OnStylusDown. Stroke stroke = new Stroke(stylusPoints); // Add the new stroke to the Strokes collection of the InkPresenter. ip.Strokes.Add(stroke); // Clear the StylusPointsCollection. stylusPoints = null; // Release stylus capture. Stylus.Capture(null); }
Практическое руководство. Включить элемент управления принимать ввод от мыши
Если добавить предыдущий элемент управления в приложение, запустите его и использовать мышь в качестве устройства ввода, можно заметить, что штрихов не сохраняются. Для сохранения штрихов, когда указатель мыши используется как устройство ввода сделайте следующее:
Переопределить OnMouseLeftButtonDown и создайте новый StylusPointCollection получать положение указателя мыши при происхождении события и создавать StylusPoint точки данных и добавьте StylusPoint для StylusPointCollection.
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { base.OnMouseLeftButtonDown(e); // If a stylus generated this event, return. if (e.StylusDevice != null) { return; } // Start collecting the points. stylusPoints = new StylusPointCollection(); Point pt = e.GetPosition(this); stylusPoints.Add(new StylusPoint(pt.X, pt.Y)); }
Переопределите метод OnMouseMove . Получите положение указателя мыши при происхождении события и создайте StylusPoint с использованием точки данных. Добавить StylusPoint для StylusPointCollection объект, который был создан ранее.
protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); // If a stylus generated this event, return. if (e.StylusDevice != null) { return; } // Don't collect points unless the left mouse button // is down. if (e.LeftButton == MouseButtonState.Released || stylusPoints == null) { return; } Point pt = e.GetPosition(this); stylusPoints.Add(new StylusPoint(pt.X, pt.Y)); }
Переопределите метод OnMouseLeftButtonUp . Создайте новый Stroke с StylusPointCollection данных и добавьте новые Stroke созданной вами для Strokes коллекцию InkPresenter.
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { base.OnMouseLeftButtonUp(e); // If a stylus generated this event, return. if (e.StylusDevice != null) { return; } if (stylusPoints == null) { return; } Point pt = e.GetPosition(this); stylusPoints.Add(new StylusPoint(pt.X, pt.Y)); // Create a stroke and add it to the InkPresenter. Stroke stroke = new Stroke(stylusPoints); stroke.DrawingAttributes = dr.DrawingAttributes; ip.Strokes.Add(stroke); stylusPoints = null; }
Сводная информация
Ниже приведен пользовательский элемент управления, сбора данных рукописного ввода при использовании пользователем мыши или пера.
using System;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Controls;
using System.Windows;
// A control for managing ink input
class InkControl : Label
{
InkPresenter ip;
DynamicRenderer dr;
// The StylusPointsCollection that gathers points
// before Stroke from is created.
StylusPointCollection stylusPoints = null;
public InkControl()
{
// Add an InkPresenter for drawing.
ip = new InkPresenter();
this.Content = ip;
// Add a dynamic renderer that
// draws ink as it "flows" from the stylus.
dr = new DynamicRenderer();
ip.AttachVisuals(dr.RootVisual, dr.DrawingAttributes);
this.StylusPlugIns.Add(dr);
}
static InkControl()
{
// Allow ink to be drawn only within the bounds of the control.
Type owner = typeof(InkControl);
ClipToBoundsProperty.OverrideMetadata(owner,
new FrameworkPropertyMetadata(true));
}
protected override void OnStylusDown(StylusDownEventArgs e)
{
// Capture the stylus so all stylus input is routed to this control.
Stylus.Capture(this);
// Allocate memory for the StylusPointsCollection and
// add the StylusPoints that have come in so far.
stylusPoints = new StylusPointCollection();
StylusPointCollection eventPoints =
e.GetStylusPoints(this, stylusPoints.Description);
stylusPoints.Add(eventPoints);
}
protected override void OnStylusMove(StylusEventArgs e)
{
if (stylusPoints == null)
{
return;
}
// Add the StylusPoints that have come in since the
// last call to OnStylusMove.
StylusPointCollection newStylusPoints =
e.GetStylusPoints(this, stylusPoints.Description);
stylusPoints.Add(newStylusPoints);
}
protected override void OnStylusUp(StylusEventArgs e)
{
if (stylusPoints == null)
{
return;
}
// Add the StylusPoints that have come in since the
// last call to OnStylusMove.
StylusPointCollection newStylusPoints =
e.GetStylusPoints(this, stylusPoints.Description);
stylusPoints.Add(newStylusPoints);
// Create a new stroke from all the StylusPoints since OnStylusDown.
Stroke stroke = new Stroke(stylusPoints);
// Add the new stroke to the Strokes collection of the InkPresenter.
ip.Strokes.Add(stroke);
// Clear the StylusPointsCollection.
stylusPoints = null;
// Release stylus capture.
Stylus.Capture(null);
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
// If a stylus generated this event, return.
if (e.StylusDevice != null)
{
return;
}
// Start collecting the points.
stylusPoints = new StylusPointCollection();
Point pt = e.GetPosition(this);
stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
// If a stylus generated this event, return.
if (e.StylusDevice != null)
{
return;
}
// Don't collect points unless the left mouse button
// is down.
if (e.LeftButton == MouseButtonState.Released ||
stylusPoints == null)
{
return;
}
Point pt = e.GetPosition(this);
stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
// If a stylus generated this event, return.
if (e.StylusDevice != null)
{
return;
}
if (stylusPoints == null)
{
return;
}
Point pt = e.GetPosition(this);
stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
// Create a stroke and add it to the InkPresenter.
Stroke stroke = new Stroke(stylusPoints);
stroke.DrawingAttributes = dr.DrawingAttributes;
ip.Strokes.Add(stroke);
stylusPoints = null;
}
}
С помощью дополнительных подключаемых модулей и DynamicRenderers
Как и InkCanvas, пользовательский элемент управления может иметь пользовательские StylusPlugIn и дополнительные DynamicRenderer объектов. Добавить шаблоны в StylusPlugIns коллекции. Порядок StylusPlugIn объекты в StylusPlugInCollection влияет на внешний вид рукописного ввода при его отрисовке. Предположим, что у вас есть DynamicRenderer вызывается dynamicRenderer
и пользовательское StylusPlugIn вызывается translatePlugin
, offsets рукописный ввод от пера. Если translatePlugin
является первым StylusPlugIn в StylusPlugInCollection, и dynamicRenderer
является вторым, будет смещаться рукописный текст, который «потоки», когда пользователь перемещает перо. Если dynamicRenderer
является первым, и translatePlugin
является вторым, не будет смещаться рукописный ввод, пока пользователь отрывает перо.
Заключение
Можно создать элемент управления, который собирает и отображает рукописные данные, переопределив методы событий пера. Создав собственный элемент управления, создания своих собственных производных StylusPlugIn классы и их вставка в StylusPlugInCollection, можно реализовать практически для любых аспектов поведения, возможное сопоставление с рукописный ввод. У вас есть доступ к StylusPoint данных, как оно создается, дает возможность настроить Stylus входных данных и их вывода на экран, подходящие для вашего приложения. Так как у вас есть такой низкоуровневый доступ к StylusPoint данных, можно реализовать коллекцию рукописного ввода и отображать ее с оптимальной производительности приложения.