Vytvoření vstupního ovládacího prvku rukopisu
Můžete vytvořit vlastní ovládací prvek, který dynamicky a staticky vykresluje rukopis. To znamená, že rukopis je vykreslován v reálném čase, když uživatel nakreslí tah, což způsobí, že inkoust "proudí" z pera tabletu. Rukopis se zobrazí po jeho přidání do ovládacího prvku, a to buď pomocí pera tabletu, vložením ze schránky nebo načtením ze souboru. Chcete-li dynamicky vykreslit inkoust, musí ovládací prvek použít DynamicRenderer. Pokud chcete staticky vykreslit rukopis, musíte přepsat metody událostí pera (OnStylusDown, OnStylusMovea OnStylusUp) ke shromažďování StylusPoint dat, vytváření tahů a jejich přidání do InkPresenter (který vykreslí rukopis na ovládacím prvku).
Toto téma obsahuje následující pododdíly:
Postupy: Shromažďování dat bodů pera a vytváření tahů rukopisu
Pokud chcete vytvořit ovládací prvek, který shromažďuje a spravuje tahy rukopisu, postupujte takto:
Odvození třídy z Control nebo jedné z tříd odvozených z Control, například 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 {
}
Přidejte do třídy InkPresenter a nastavte vlastnost Content na novou InkPresenter.
InkPresenter ip; public InkControl() { // Add an InkPresenter for drawing. ip = new InkPresenter(); this.Content = ip; }
Připojte RootVisual z DynamicRenderer k InkPresenter voláním metody AttachVisuals a přidejte DynamicRenderer do kolekce StylusPlugIns. To umožňuje, aby InkPresenter zobrazoval inkoust, protože data bodu pera jsou shromažďována vaším ovládáním.
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); }
Přepište metodu OnStylusDown. V této metodě zachyťte stylus voláním Capture. Zachycením pera bude ovládací prvek nadále přijímat události StylusMove a StylusUp, i když pero opustí oblast ovládacího prvku. To není výhradně povinné, ale téměř vždy žádoucí pro dobré uživatelské prostředí. Vytvořte nový StylusPointCollection pro shromáždění StylusPoint dat. Nakonec do StylusPointCollectionpřidejte počáteční sadu dat StylusPoint .
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); }
Přepište OnStylusMove metodu a přidejte data StylusPoint do objektu StylusPointCollection, který jste vytvořili dříve.
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); }
Metodu OnStylusUp přepište a vytvořte novou Stroke s daty StylusPointCollection. Přidejte nové Stroke, které jste vytvořili, do kolekce Strokes objektu InkPresenter a uvolněte zachycení stylusu.
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); }
Postupy: Povolení ovládacího prvku přijímat vstup z myši
Pokud do aplikace přidáte předchozí ovládací prvek, spustíte ho a použijete myš jako vstupní zařízení, všimnete si, že tahy nejsou trvalé. Pokud chcete zachovat tahy při použití myši jako vstupní zařízení, postupujte takto:
Přepište OnMouseLeftButtonDown a vytvořte novou StylusPointCollection. Získejte pozici myši, když došlo k události, a pomocí dat bodu vytvořte StylusPoint, a přidejte StylusPoint do 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)); }
Přepište metodu OnMouseMove. Zjistěte pozici myši, když došlo k události, a vytvořte StylusPoint s použitím dat bodu. Přidejte StylusPoint do objektu StylusPointCollection, který jste vytvořili dříve.
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)); }
Přepište metodu OnMouseLeftButtonUp. Vytvořte nový Stroke s daty StylusPointCollection a přidejte nové Stroke, které jste vytvořili, do Strokes kolekce 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; }
Dát to dohromady
Následující příklad je vlastní ovládací prvek, který shromažďuje rukopis, když uživatel používá myš nebo pero.
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;
}
}
Použití dalších modulů plug-in a DynamicRenderers
Stejně jako InkCanvas může mít váš uživatelský ovládací prvek vlastní objekty StylusPlugIn a také další objekty typu DynamicRenderer. Přidejte je do kolekce StylusPlugIns. Pořadí StylusPlugIn objektů v StylusPlugInCollection ovlivňuje vzhled rukopisu při vykreslení. Předpokládejme, že máte DynamicRenderer s názvem dynamicRenderer
a vlastní StylusPlugIn označovanou jako translatePlugin
, která odsouvá inkoust z pera tabletu. Pokud je translatePlugin
první StylusPlugIn v StylusPlugInCollectiona dynamicRenderer
je druhá, posune se inkoust, který "proudí", když uživatel přesune pero. Pokud je dynamicRenderer
první a translatePlugin
druhý, inkoust nebude posunut, dokud uživatel nezvedne pero.
Závěr
Můžete vytvořit ovládací prvek, který shromažďuje a vykresluje rukopis překrytím metody událostí stylusu. Vytvořením vlastního ovládacího prvku, odvozením vlastních StylusPlugIn tříd a jejich vložením do StylusPlugInCollection, můžete implementovat prakticky jakékoli chování, které je možné imaginovat pomocí digitálního rukopisu. Máte přístup k StylusPoint datům, která se generují, takže máte možnost přizpůsobit Stylus vstup a vykreslit je na obrazovce podle potřeby pro vaši aplikaci. Vzhledem k tomu, že máte nízkoúrovňový přístup k datům StylusPoint, můžete implementovat sběr inkoustu a vykreslit jej s optimálním výkonem pro vaši aplikaci.
Viz také
.NET Desktop feedback