Condividi tramite


Creazione di un controllo di input penna

È possibile creare un controllo personalizzato che esegue il rendering dell'input penna in modo dinamico e statico. Ovvero, il rendering dell'input penna come utente disegna un tratto, causando la visualizzazione dell'input penna dall'input penna del tablet e la visualizzazione dell'input penna dopo l'aggiunta al controllo, tramite la penna del tablet, incollata dagli Appunti o caricata da un file. Per eseguire il rendering dinamico dell'input penna, il controllo deve usare un oggetto DynamicRenderer. Per eseguire il rendering statico dell'input penna, è necessario eseguire l'override dei metodi di evento dello stilo (OnStylusDown, OnStylusMovee OnStylusUp) per raccogliere StylusPoint dati, creare tratti e aggiungerli a un InkPresenter oggetto (che esegue il rendering dell'input penna nel controllo).

In questo argomento sono contenute le seguenti sottosezioni:

Procedura: Raccogliere i dati dei punti di stilo e creare tratti input penna

Per creare un controllo che raccoglie e gestisce i tratti input penna, eseguire le operazioni seguenti:

  1. Derivare una classe da Control o una delle classi derivate da Control, ad esempio 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
    {
    
    }
    
  2. Aggiungere un oggetto InkPresenter alla classe e impostare la Content proprietà sul nuovo InkPresenteroggetto .

    InkPresenter ip;
    
    public InkControl()
    {
        // Add an InkPresenter for drawing.
        ip = new InkPresenter();
        this.Content = ip;
    }
    
  3. Collegare l'oggetto dell'oggetto all'oggetto DynamicRendererInkPresenter chiamando il AttachVisuals metodo e aggiungere l'oggetto StylusPlugInsDynamicRenderer alla raccolta.RootVisual In questo modo l'oggetto InkPresenter consente di visualizzare l'input penna quando i dati del punto dello stilo vengono raccolti dal controllo.

    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);
    }
    
  4. Eseguire l'override del metodo OnStylusDown. In questo metodo acquisire lo stilo con una chiamata a Capture. Acquisendo lo stilo, il controllo continuerà a ricevere StylusMove ed StylusUp eventi anche se lo stilo esce dai limiti del controllo. Questo non è strettamente obbligatorio, ma quasi sempre desiderato per una buona esperienza utente. Creare un nuovo StylusPointCollection oggetto per raccogliere StylusPoint dati. Infine, aggiungere il set iniziale di StylusPoint dati a 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);
    }
    
  5. Eseguire l'override del OnStylusMove metodo e aggiungere i StylusPoint dati all'oggetto StylusPointCollection creato in precedenza.

    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);
    }
    
  6. Eseguire l'override del OnStylusUp metodo e creare un nuovo Stroke oggetto con i StylusPointCollection dati. Aggiungere il nuovo creato Stroke alla Strokes raccolta dell'acquisizione dello InkPresenter stilo e di rilascio.

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

Procedura: Abilitare il controllo per accettare l'input dal mouse

Se si aggiunge il controllo precedente all'applicazione, eseguirlo e usare il mouse come dispositivo di input, noterai che i tratti non sono persistenti. Per rendere persistenti i tratti quando il mouse viene usato come dispositivo di input, eseguire le operazioni seguenti:

  1. Eseguire l'override di OnMouseLeftButtonDown e creare un nuovo StylusPointCollection oggetto Get la posizione del mouse quando si è verificato l'evento e creare un StylusPoint oggetto usando i dati del punto e aggiungere a StylusPointStylusPointCollection.

    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));
    }
    
  2. Eseguire l'override del metodo OnMouseMove. Ottiene la posizione del mouse quando si è verificato l'evento e crea un StylusPoint oggetto usando i dati del punto. Aggiungere l'oggetto StylusPoint all'oggetto StylusPointCollection creato in precedenza.

    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));
    }
    
  3. Eseguire l'override del metodo OnMouseLeftButtonUp. Creare un nuovo Stroke oggetto con i StylusPointCollection dati e aggiungere il nuovo Stroke creato alla Strokes raccolta di 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;
    }
    

Riepilogo

L'esempio seguente è un controllo personalizzato che raccoglie l'input penna quando l'utente usa il mouse o la penna.

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

Uso di plug-in aggiuntivi e DynamicRenderers

Analogamente a InkCanvas, il controllo personalizzato può avere oggetti personalizzati StylusPlugIn e aggiuntivi DynamicRenderer . Aggiungerli alla StylusPlugIns raccolta. L'ordine StylusPlugIn degli oggetti in StylusPlugInCollection influisce sull'aspetto dell'input penna quando viene eseguito il rendering. Si supponga di avere un DynamicRenderer chiamato dynamicRenderer e un oggetto personalizzato StylusPlugIn denominato translatePlugin che sfalsa l'input penna dalla penna del tablet. Se translatePlugin è il primo StylusPlugIn in StylusPlugInCollectione dynamicRenderer è il secondo, l'input penna "flussi" verrà sfalsato quando l'utente sposta la penna. Se dynamicRenderer è primo, e translatePlugin è secondo, l'input penna non verrà sfalsato finché l'utente non solleva la penna.

Conclusione

È possibile creare un controllo che raccoglie ed esegue il rendering dell'input penna eseguendo l'override dei metodi di evento dello stilo. Creando un proprio controllo, derivando le proprie StylusPlugIn classi e inserendole in StylusPlugInCollection, è possibile implementare praticamente qualsiasi comportamento immaginabile con input penna digitale. È possibile accedere ai StylusPoint dati man mano che vengono generati, offrendo la possibilità di personalizzare Stylus l'input e eseguirne il rendering sullo schermo in base alle esigenze dell'applicazione. Poiché si ha un accesso di basso livello ai StylusPoint dati, è possibile implementare la raccolta di input penna ed eseguirne il rendering con prestazioni ottimali per l'applicazione.

Vedi anche