Creación de un control de entrada manuscritaCreating an Ink Input Control

Puede crear un control personalizado dinámicamente y estáticamente representa la entrada de lápiz.You can create a custom control that dynamically and statically renders ink. Es decir, represente la tinta mientras el usuario dibuja un trazo, causando parece "fluir" del lápiz de tablet PC y mostrar tinta después de se agrega al control, mediante el lápiz de tablet PC, pegado desde el Portapapeles, o cargar desde un archivo.That is, render ink as a user draws a stroke, causing the ink to appear to "flow" from the tablet pen, and display ink after it is added to the control, either via the tablet pen, pasted from the Clipboard, or loaded from a file. Para representar dinámicamente la tinta, el control debe usar un DynamicRenderer.To dynamically render ink, your control must use a DynamicRenderer. Para representar estáticamente tinta, debe invalidar los métodos de evento de lápiz (OnStylusDown, OnStylusMove, y OnStylusUp) para recopilar StylusPoint datos, crear los trazos y agregarlos a un InkPresenter (que representa la entrada de lápiz en el control).To statically render ink, you must override the stylus event methods (OnStylusDown, OnStylusMove, and OnStylusUp) to collect StylusPoint data, create strokes, and add them to an InkPresenter (which renders the ink on the control).

Este tema contiene las siguientes subsecciones:This topic contains the following subsections:

Procedimiento Recopilar datos de puntos de lápiz y crear trazos de tintaHow to: Collect Stylus Point Data and Create Ink Strokes

Para crear un control que recopila y administra la tinta trazos realice lo siguiente:To create a control that collects and manages ink strokes do the following:

  1. Derive una clase de Control o una de las clases derivadas de Control, tales como Label.Derive a class from Control or one of the classes derived from Control, such as 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. Agregar un InkPresenter a la clase y establezca el Content propiedad a la nueva InkPresenter.Add an InkPresenter to the class and set the Content property to the new InkPresenter.

    InkPresenter ip;
    
    public InkControl()
    {
        // Add an InkPresenter for drawing.
        ip = new InkPresenter();
        this.Content = ip;
    }
    
  3. Adjuntar el RootVisual de la DynamicRenderer a la InkPresenter mediante una llamada a la AttachVisuals método y agregue el DynamicRenderer a la StylusPlugIns colección.Attach the RootVisual of the DynamicRenderer to the InkPresenter by calling the AttachVisuals method, and add the DynamicRenderer to the StylusPlugIns collection. Esto permite la InkPresenter para mostrar la entrada de lápiz como el control recopila los datos del punto del lápiz.This allows the InkPresenter to display the ink as the stylus point data is collected by your control.

    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. Invalide el método OnStylusDown .Override the OnStylusDown method. En este método, captura el lápiz óptico con una llamada a Capture.In this method, capture the stylus with a call to Capture. Al capturar el lápiz, redirigirá mediante el control para continuar recibiendo StylusMove y StylusUp incluso si el lápiz sale de los límites del control de eventos.By capturing the stylus, your control will to continue to receive StylusMove and StylusUp events even if the stylus leaves the control's boundaries. Esto no es estrictamente obligatorio, pero casi siempre deseado para una buena experiencia del usuario.This is not strictly mandatory, but almost always desired for a good user experience. Cree un nuevo StylusPointCollection para recopilar StylusPoint datos.Create a new StylusPointCollection to gather StylusPoint data. Por último, agregue el conjunto inicial de StylusPoint datos a la StylusPointCollection.Finally, add the initial set of StylusPoint data to the 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. Invalidar el OnStylusMove método y agregue el StylusPoint datos a la StylusPointCollection objeto que creó anteriormente.Override the OnStylusMove method and add the StylusPoint data to the StylusPointCollection object that you created earlier.

    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. Invalidar el OnStylusUp método y cree un nuevo Stroke con el StylusPointCollection datos.Override the OnStylusUp method and create a new Stroke with the StylusPointCollection data. Agregue el nuevo Stroke que ha creado para el Strokes colección de los InkPresenter y liberar la captura del lápiz óptico.Add the new Stroke you created to the Strokes collection of the InkPresenter and release stylus capture.

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

Procedimiento Habilitar el Control y aceptar la entrada del mouseHow to: Enable Your Control to Accept Input from the Mouse

Si agrega el control anterior a la aplicación, ejecútelo y usar el mouse como un dispositivo de entrada, observará que no se conservan los trazos.If you add the preceding control to your application, run it, and use the mouse as an input device, you will notice that the strokes are not persisted. Para conservar los trazos cuando el mouse se usa como el dispositivo de entrada realice lo siguiente:To persist the strokes when the mouse is used as the input device do the following:

  1. Invalidar el OnMouseLeftButtonDown y cree un nuevo StylusPointCollection obtener la posición del mouse cuando se produjo el evento y crear un StylusPoint con el punto de datos y agregue el StylusPoint a la StylusPointCollection.Override the OnMouseLeftButtonDown and create a new StylusPointCollection Get the position of the mouse when the event occurred and create a StylusPoint using the point data and add the StylusPoint to the 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));
    
    }
    
  2. Invalide el método OnMouseMove .Override the OnMouseMove method. Obtiene la posición del mouse cuando se produjo el evento y crear un StylusPoint con los datos del punto.Get the position of the mouse when the event occurred and create a StylusPoint using the point data. Agregar el StylusPoint a la StylusPointCollection objeto que creó anteriormente.Add the StylusPoint to the StylusPointCollection object that you created earlier.

    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. Invalide el método OnMouseLeftButtonUp .Override the OnMouseLeftButtonUp method. Cree un nuevo Stroke con el StylusPointCollection datos y agregue el nuevo Stroke que ha creado para el Strokes colección de la InkPresenter.Create a new Stroke with the StylusPointCollection data, and add the new Stroke you created to the Strokes collection of the 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;
    
    }
    

Incorporación de todosPutting it together

El ejemplo siguiente es un control personalizado que recopila entradas de lápiz cuando el usuario usa el mouse o lápiz.The following example is a custom control that collects ink when the user uses either the mouse or the pen.

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 de complementos adicionales y representadores dinámicosUsing Additional Plug-ins and DynamicRenderers

Al igual que el objeto InkCanvas, su control personalizado puede tener personalizado StylusPlugIn adicional y DynamicRenderer objetos.Like the InkCanvas, your custom control can have custom StylusPlugIn and additional DynamicRenderer objects. Agregue las siguientes a la StylusPlugIns colección.Add these to the StylusPlugIns collection. El orden de los StylusPlugIn objetos en el StylusPlugInCollection afecta al aspecto de la entrada de lápiz cuando se representa.The order of the StylusPlugIn objects in the StylusPlugInCollection affects the appearance of the ink when it is rendered. Suponga que tiene un DynamicRenderer llamado dynamicRenderer y personalizada StylusPlugIn llamado translatePlugin que compensa la tinta del lápiz de Tablet PC.Suppose you have a DynamicRenderer called dynamicRenderer and a custom StylusPlugIn called translatePlugin that offsets the ink from the tablet pen. Si translatePlugin es la primera StylusPlugIn en el StylusPlugInCollection, y dynamicRenderer es el segundo, se desplazará la tinta que "fluye" cuando el usuario mueve el lápiz.If translatePlugin is the first StylusPlugIn in the StylusPlugInCollection, and dynamicRenderer is the second, the ink that "flows" will be offset as the user moves the pen. Si dynamicRenderer es el primero, y translatePlugin en segundo lugar, es la entrada de lápiz no se desplazará hasta que el usuario levanta el lápiz.If dynamicRenderer is first, and translatePlugin is second, the ink will not be offset until the user lifts the pen.

ConclusiónConclusion

Puede crear un control que recopila y representa la entrada de lápiz invalidando los métodos de eventos de lápiz óptico.You can create a control that collects and renders ink by overriding the stylus event methods. Al crear su propio control, derive su propia StylusPlugIn clases e insertándolos el en StylusPlugInCollection, puede implementar prácticamente cualquier comportamiento imaginable con entrada de lápiz digital.By creating your own control, deriving your own StylusPlugIn classes, and inserting them the into StylusPlugInCollection, you can implement virtually any behavior imaginable with digital ink. Tener acceso a la StylusPoint datos a medida que se generan, lo que le ofrece la oportunidad de personalizar Stylus de entrada y para representarlo en la pantalla según corresponda para su aplicación.You have access to the StylusPoint data as it is generated, giving you the opportunity to customize Stylus input and render it on the screen as appropriate for your application. Dado que tienen ese acceso de bajo nivel para el StylusPoint datos, puede implementar la recopilación de tinta y representarlo con un rendimiento óptimo para su aplicación.Because you have such low-level access to the StylusPoint data, you can implement ink collection and render it with optimal performance for your application.

Vea tambiénSee also