Compartir a través de


Ejemplo de colección de lápiz RealTimeStylus

Esta aplicación muestra la colección de tintas y la representación cuando se usa la clase RealTimeStylus .

El proyecto InkCollection

Este ejemplo consta de una única solución que contiene un proyecto, InkCollection. La aplicación define el InkCollection espacio de nombres que contiene una sola clase, también denominada InkCollection. La clase hereda de la clase Form e implementa la interfaz IStylusAsyncPlugin .

namespace InkCollection
{
    public class InkCollection : Form, IStylusAsyncPlugin
    {
        //...
      

La clase InkCollection define un conjunto de constantes privadas que se usan para especificar varios grosores de entrada de lápiz. La clase también declara instancias privadas de la clase RealTimeStylus, myRealTimeStylus, la clase DynamicRenderer, myDynamicRenderery la clase myRendererRenderer . DynamicRenderer representa el trazo que se está recopilando actualmente. El objeto Renderer, myRenderer, representa los objetos Stroke que ya se han recopilado.

private const float ThinInkWidth = 10;
private const float MediumInkWidth = 100;
private const float ThickInkWidth = 200;

private RealTimeStylus myRealTimeStylus;

private DynamicRenderer myDynamicRenderer;
private Renderer myRenderer;

La clase también declara un objeto Hashtable , myPackets, que se usa para almacenar datos de paquetes recopilados por uno o varios objetos Cursor . Los valores id. del objeto Stylus se usan como clave hash para identificar de forma única los datos de paquete recopilados para un objeto Cursor determinado.

Una instancia privada del objeto Ink , myInk, almacena los objetos Stroke recopilados por myRealTimeStylus.

private Hashtable myPackets;
        
private Ink myInk;

Evento de carga de formularios

En el controlador de eventos Load del formulario, myDynamicRenderer se crea una instancia mediante dynamicRenderer que toma un control como argumento y myRenderer se construye con un constructor sin argumentos.

private void InkCollection_Load(object sender, System.EventArgs e)
{
    myDynamicRenderer = new DynamicRenderer(this);
    myRenderer = new Renderer();
    // ...

Preste atención al comentario que sigue a la creación de instancias de los representadores, ya myDynamicRenderer que usa los valores predeterminados para DrawingAttributes al representar la entrada de lápiz. Este es el comportamiento estándar. Sin embargo, si desea proporcionar la entrada de lápiz representada por myDynamicRenderer un aspecto diferente de la entrada de lápiz representada por myRenderer, puede cambiar la propiedad DrawingAttributes en myDynamicRenderer. Para ello, quite la marca de comentario de las líneas siguientes antes de compilar y ejecutar la aplicación.

    // myDynamicRenderer.DrawingAttributes.PenTip = PenTip.Rectangle;
    // myDynamicRenderer.DrawingAttributes.Height = (.5F)*MediumInkWidth;
    // myDynamicRenderer.DrawingAttributes.Transparency = 128;

A continuación, la aplicación crea el objeto RealTimeStylus que se usa para recibir notificaciones de lápiz óptico y agrega el objeto DynamicRenderer a la cola de notificaciones de complemento sincrónica. En concreto, myRealTimeStylus agrega myDynamicRenderer a la propiedad SyncPluginCollection .

    myRealTimeStylus = new RealTimeStylus(this, true);

    myRealTimeStylus.SyncPluginCollection.Add(myDynamicRenderer);

A continuación, el formulario se agrega a la cola de notificaciones de complemento asincrónica. En concreto, InkCollection se agrega a la propiedad AsyncPluginCollection . Por último, myRealTimeStylus y myDynamicRenderer se habilitan, y se crean instancias de myPackets y myInk.

    myRealTimeStylus.AsyncPluginCollection.Add(this);

    myRealTimeStylus.Enabled = true;
    myDynamicRenderer.Enabled = true;  
      
    myPackets = new Hashtable();
    myInk = new Ink();
}

Además de enlazar los controladores de menú para cambiar el color y el tamaño de la entrada de lápiz, se requiere un bloque de código más breve antes de implementar la interfaz. El ejemplo debe controlar el evento Paint del formulario. En el controlador de eventos, la aplicación debe actualizarse myDynamicRenderer porque es posible que se recopile un objeto Stroke en el momento en que se produzca el evento Paint. En ese caso, la parte del objeto Stroke que ya se ha recopilado debe volver a dibujarse. El representador estático se usa para volver a dibujar objetos Stroke que ya se han recopilado. Estos trazos se encuentran en el objeto Ink porque se colocan allí cuando se dibujan, como se muestra en la sección siguiente.

private void InkCollection_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    myDynamicRenderer.Refresh();

    myRenderer.Draw(e.Graphics, myInk.Strokes);
} 

Implementación de la interfaz IStylusAsyncPlugin

La aplicación de ejemplo define los tipos de notificaciones que tiene interés en recibir en la implementación de la propiedad DataInterest . Por lo tanto, la propiedad DataInterest define qué notificaciones reenvía el objeto RealTimeStylus al formulario. En este ejemplo, la propiedad DataInterest define el interés en stylusDown, packets, stylusUp y notificaciones de error a través de la enumeración DataInterestMask .

public DataInterestMask DataInterest
{
    get
    {
        return DataInterestMask.StylusDown |
               DataInterestMask.Packets |
               DataInterestMask.StylusUp |
               DataInterestMask.Error;
    }
}

La notificación StylusDown se produce cuando el lápiz toca la superficie del digitalizador. Cuando esto sucede, el ejemplo asigna una matriz que se usa para almacenar los datos de paquete para el objeto Stylus . StylusDownData del método StylusDown se agrega a la matriz y la matriz se inserta en la tabla hash mediante la propiedad Id del objeto Stylus como clave.

public void StylusDown(RealTimeStylus sender, StylusDownData data)
{
    ArrayList collectedPackets = new ArrayList();

    collectedPackets.AddRange(data.GetData());

    myPackets.Add(data.Stylus.Id, collectedPackets);
}

La notificación Paquetes se produce cuando el lápiz se mueve en la superficie del digitalizador. Cuando esto ocurre, la aplicación agrega un nuevo StylusDownData a la matriz de paquetes del objeto Stylus . Para ello, se usa la propiedad Id del objeto Stylus como clave para recuperar la matriz de paquetes para el lápiz óptico de la tabla hash. A continuación, los nuevos datos de paquete se insertan en la matriz recuperada.

public void Packets(RealTimeStylus sender, PacketsData data)
{
    ((ArrayList)(myPackets[data.Stylus.Id])).AddRange(data.GetData());
}

La notificación StylusUp se produce cuando el lápiz sale de la superficie del digitalizador. Cuando se produce esta notificación, el ejemplo recupera la matriz de paquetes para este objeto Stylus de la tabla hash que lo quita de la tabla hash, ya que ya no es necesaria, agrega los nuevos datos de paquete y usa la matriz de datos de paquetes para crear un nuevo objeto Stroke , stroke.

public void StylusUp(RealTimeStylus sender, StylusUpData data)
{
    ArrayList collectedPackets = (ArrayList)myPackets[data.Stylus.Id];
    myPackets.Remove(data.Stylus.Id);

    collectedPackets.AddRange(data.GetData());

    int[] packets = (int[])(collectedPackets.ToArray(typeof(int)));
    TabletPropertyDescriptionCollection tabletProperties =
        myRealTimeStylus.GetTabletPropertyDescriptionCollection(data.Stylus.TabletContextId);

    Stroke stroke = myInk.CreateStroke(packets, tabletProperties);
    if (stroke != null) 
    {
         stroke.DrawingAttributes.Color = myDynamicRenderer.DrawingAttributes.Color;
         stroke.DrawingAttributes.Width = myDynamicRenderer.DrawingAttributes.Width;
    } 
}

Para obtener un ejemplo que muestre un uso más sólido de la clase RealTimeStylus , incluido el uso de la creación de complementos personalizados, consulte Ejemplo de complemento RealTimeStylus.

Microsoft.Ink.Renderer

Microsoft.StylusInput.DynamicRenderer

Microsoft.StylusInput.RealTimeStylus

Microsoft.StylusInput.IStylusAsyncPlugin

Acceso y manipulación de entrada de lápiz óptico