Ejemplo del complemento RealTimeStylus
Esta aplicación muestra cómo trabajar con la clase RealTimeStylus . Para obtener información general detallada de las API de StylusInput, incluida la clase RealTimeStylus , consulte Acceso y manipulación de entradas de lápiz óptico. Para obtener información sobre los complementos sincrónicos y asincrónicos, consulte Plug-ins y la clase RealTimeStylus.
Información general sobre el ejemplo
Los complementos, los objetos que implementan la interfaz IStylusSyncPlugin o IStylusAsyncPlugin se pueden agregar a un objeto RealTimeStylus . Esta aplicación de ejemplo usa varios tipos de complemento:
- Complemento de filtro de paquetes: modifica los paquetes. El complemento de filtro de paquetes de este ejemplo modifica la información del paquete limitando todos los datos de paquetes (x,y) dentro de un área rectangular.
- Complemento de representador dinámico personalizado: modifica las calidades de representación dinámica. El complemento de representación dinámica personalizada de este ejemplo modifica la forma en que se representa la entrada de lápiz dibujando un círculo pequeño alrededor de cada punto (x,y) en un trazo.
- Complemento representador dinámico: modifica las cualidades de representación dinámica. En este ejemplo se muestra el uso del objeto DynamicRenderer como complemento para controlar la representación dinámica de la entrada de lápiz.
- Complemento De reconocedor de gestos: reconoce gestos de aplicación. En este ejemplo se muestra el uso del objeto GestureRecognizer como complemento para reconocer los gestos de la aplicación (cuando se ejecuta en un sistema con el reconocedor de gestos de Microsoft presente).
Además, este ejemplo proporciona una interfaz de usuario que permite al usuario agregar, quitar y cambiar el orden de cada complemento de la colección. La solución de ejemplo contiene dos proyectos, RealTimeStylusPluginApp y RealTimeStylusPlugins. RealTimeStylusPluginApp contiene la interfaz de usuario del ejemplo. RealTimeStylusPlugins contiene las implementaciones de los complementos. El proyecto RealTimeStylusPlugins define el espacio de nombres RealTimeStylusPlugins, que contiene el filtro de paquetes y los complementos de representador dinámico personalizados. El proyecto RealTimeStylusPluginApp hace referencia a este espacio de nombres. El proyecto RealTimeStylusPlugins usa los espacios de nombres Microsoft.Ink, Microsoft.StylusInput y Microsoft.StylusInput.PluginData .
Para obtener información general sobre los espacios de nombres Microsoft.StylusInput y Microsoft.StylusInput.PluginData , consulte Arquitectura de las API de StylusInput.
Complemento de filtro de paquetes
El complemento de filtro de paquetes es un complemento sincrónico que muestra la modificación de paquetes. En concreto, define un rectángulo en el formulario. Los paquetes que se dibujan fuera de la región se representan dentro de la región. La clase de complemento , PacketFilterPlugin
, se registra para la notificación de los eventos de StylusDown
entrada de lápiz , StylusUp
y Packets
. La clase implementa los métodos StylusDown, StylusUp y Packets definidos en la clase IStylusSyncPlugin .
El constructor público para PacketFilterPlugin
requiere una estructura Rectangle . Este rectángulo define el área rectangular, en coordenadas de espacio de entrada de lápiz (.01mm = 1 unidad HIMETRIC), en la que se incluirán los paquetes. El rectángulo se mantiene en un campo privado, rectangle
.
public class PacketFilterPlugin:IStylusSyncPlugin
{
private System.Drawing.Rectangle rectangle = System.Drawing.Rectangle.Empty;
public PacketFilterPlugin(Rectangle r)
{
rectangle = r;
}
// ...
La PacketFilterPlugin
clase se registra para las notificaciones de eventos mediante la implementación del descriptor de acceso get para la propiedad DataInterest . En este caso, el complemento está interesado en responder a las StylusDown
notificaciones , Packets
, StylusUp
y Error
. El ejemplo devuelve estos valores tal y como se define en la enumeración DataInterestMask . Se llama al método StylusDown cuando la punta del lápiz se pone en contacto con la superficie del digitalizador. Se llama al método StylusUp cuando la punta del lápiz sale de la superficie del digitalizador. Se llama al método Packets cuando el objeto RealTimeStylus recibe paquetes. Se llama al método Error cuando el complemento actual o un complemento anterior produce una excepción.
public DataInterestMask DataInterest
{
get
{
return DataInterestMask.StylusDown |
DataInterestMask.Packets |
DataInterestMask.StylusUp |
DataInterestMask.Error;
}
}
//...
La PacketFilterPlugin
clase controla la mayoría de estas notificaciones en un método auxiliar, ModifyPacketData
. El ModifyPacketData
método obtiene los valores x e y de cada nuevo paquete de la clase PacketsData . Si alguno de los valores está fuera del rectángulo, el método reemplaza el valor por el punto más cercano que todavía está dentro del rectángulo. Este es un ejemplo de cómo un complemento puede reemplazar los datos de paquetes a medida que se reciben del flujo de entrada de lápiz.
private void ModifyPacketData(StylusDataBase data)
{
for (int i = 0; i < data.Count ; i += data.PacketPropertyCount)
{
// packet data always has x followed by y followed by the rest
int x = data[i];
int y = data[i+1];
// Constrain points to the input rectangle
x = Math.Max(x, rectangle.Left);
x = Math.Min(x, rectangle.Right);
y = Math.Max(y, rectangle.Top);
y = Math.Min(y, rectangle.Bottom);
// If necessary, modify the x,y packet data
if (x != data[i])
{
data[i] = x;
}
if (y != data[i+1])
{
data[i+1] = y;
}
}
}
Complemento de representador dinámico personalizado
La CustomDynamicRenderer
clase también implementa la clase IStylusSyncPlugin para recibir notificaciones de entrada manuscrita. A continuación, controla la Packets
notificación para dibujar un círculo pequeño alrededor de cada nuevo punto de paquete.
La clase contiene una variable Graphics que contiene una referencia al objeto gráfico pasado al constructor de clase. Este es el objeto gráfico que se usa para la representación dinámica.
private Graphics myGraphics;
public CustomDynamicRendererPlugin(Graphics g)
{
myGraphics = g;
}
//...
Cuando el complemento de representador dinámico personalizado recibe una notificación paquetes, extrae los datos (x,y) y dibuja un círculo verde pequeño alrededor del punto. Este es un ejemplo de representación personalizada basada en el flujo de entrada de lápiz.
public void Packets(RealTimeStylus sender, PacketsData data)
{
for (int i = 0; i < data.Count; i += data.PacketPropertyCount)
{
// Packet data always has x followed by y followed by the rest
Point point = new Point(data[i], data[i+1]);
// Since the packet data is in Ink Space coordinates, we need to convert to Pixels...
point.X = (int)Math.Round((float)point.X * (float)myGraphics.DpiX/2540.0F);
point.Y = (int)Math.Round((float)point.Y * (float)myGraphics.DpiY/2540.0F);
// Draw a circle corresponding to the packet
myGraphics.DrawEllipse(Pens.Green, point.X - 2, point.Y - 2, 4, 4);
}
}
El proyecto RealTimeStylusPluginApp
El proyecto RealTimeStylusPluginApp muestra los complementos descritos anteriormente, así como los complementos GestureRecognizer y DynamicRenderer . La interfaz de usuario del proyecto consta de:
- Formulario que contiene un control GroupBox utilizado para definir el área de entrada de lápiz.
- Un control CheckedListBox que se va a enumerar y seleccionar los complementos disponibles.
- Un par de objetos Button para permitir volver a ordenar los complementos.
El proyecto define una estructura, PlugInListItem
, para facilitar la administración de los complementos usados en el proyecto. La PlugInListItem
estructura contiene el complemento y una descripción.
La RealTimeStylusPluginApp
propia clase implementa la clase IStylusAsyncPlugin . Esto es necesario para que se pueda notificar a la RealTimeStylusPluginApp
clase cuando el complemento GestureRecognizer agrega datos de gestos a la cola de salida. La aplicación se registra para la notificación de CustomStylusDataAdded. Cuando se reciben los datos de gestos, RealTimeStylusPluginApp
coloca una descripción de ellos en la barra de estado de la parte inferior del formulario.
public void CustomStylusDataAdded(RealTimeStylus sender, CustomStylusData data)
{
if (data.CustomDataId == GestureRecognizer.GestureRecognitionDataGuid)
{
GestureRecognitionData grd = data.Data as GestureRecognitionData;
if (grd != null)
{
if (grd.Count > 0)
{
GestureAlternate ga = grd[0];
sbGesture.Text = "Gesture=" + ga.Id + ", Confidence=" + ga.Confidence;
}
}
}
}
Nota
En la implementación CustomStylusDataAdded , es interesante identificar los datos de gestos personalizados en la cola de salida por GUID (mediante el campo GestureRecognitionDataGuid ) o por tipo (mediante el resultado de la instrucción as). En el ejemplo se usan ambas técnicas de identificación con fines de demostración. Cualquier enfoque solo es válido.
En el controlador de eventos Load del formulario, la aplicación crea instancias de las PacketFilter
clases y CustomDynamicRenderer
y las agrega al cuadro de lista. A continuación, la aplicación intenta crear una instancia de la clase GestureRecognizer y, si se ejecuta correctamente, la agrega al cuadro de lista. Esto produce un error si el reconocedor de gestos no está presente en el sistema. A continuación, la aplicación crea una instancia de un objeto DynamicRenderer y lo agrega al cuadro de lista. Por último, la aplicación habilita cada uno de los complementos y el propio objeto RealTimeStylus .
Otra cosa importante que hay que tener en cuenta sobre el ejemplo es que, en los métodos auxiliares, el objeto RealTimeStylus se deshabilita primero antes de que se agreguen o quiten complementos y, a continuación, vuelvan a habilitarse una vez completada la adición o eliminación.
private void RemoveFromPluginCollection(int index)
{
IStylusSyncPlugin plugin = ((PluginListItem)chklbPlugins.Items[index]).Plugin;
bool rtsEnabled = myRealTimeStylus.Enabled;
myRealTimeStylus.Enabled = false;
myRealTimeStylus.SyncPluginCollection.Remove(plugin);
myRealTimeStylus.Enabled = rtsEnabled;
}
Temas relacionados