Partager via


Exemple de plug-in RealTimeStylus

Cette application montre comment utiliser la classe RealTimeStylus . Pour obtenir une vue d’ensemble détaillée des API StylusInput, y compris la classe RealTimeStylus , consultez Accès et manipulation de l’entrée de stylet. Pour plus d’informations sur les plug-ins synchrones et asynchrones, consultez Plug-ins et la classe RealTimeStylus.

Vue d’ensemble de l’exemple

Les plug-ins, les objets qui implémentent l’interface IStylusSyncPlugin ou IStylusAsyncPlugin peuvent être ajoutés à un objet RealTimeStylus . Cet exemple d’application utilise plusieurs types de plug-in :

  • Plug-in de filtre de paquets : modifie les paquets. Le plug-in de filtre de paquets dans cet exemple modifie les informations sur les paquets en limitant toutes les données de paquets (x,y) dans une zone rectangulaire.
  • Plug-in de renderer dynamique personnalisé : modifie les qualités de rendu dynamique. Le plug-in de rendu dynamique personnalisé de cet exemple modifie la façon dont l’entrée manuscrite est rendue en dessinant un petit cercle autour de chaque point (x,y) sur un trait.
  • Plug-in du convertisseur dynamique : modifie les qualités de rendu dynamique. Cet exemple illustre l’utilisation de l’objet DynamicRenderer en tant que plug-in pour gérer le rendu dynamique de l’entrée manuscrite.
  • Plug-in Gesture Recognizer : reconnaît les mouvements d’application. Cet exemple illustre l’utilisation de l’objet GestureRecognizer en tant que plug-in pour reconnaître les mouvements d’application (lors de l’exécution sur un système avec le module de reconnaissance de mouvements Microsoft présent).

En outre, cet exemple fournit une interface utilisateur qui permet à l’utilisateur d’ajouter, de supprimer et de modifier l’ordre de chaque plug-in dans la collection. L’exemple de solution contient deux projets, RealTimeStylusPluginApp et RealTimeStylusPlugins. RealTimeStylusPluginApp contient l’interface utilisateur de l’exemple. RealTimeStylusPlugins contient les implémentations des plug-ins. Le projet RealTimeStylusPlugins définit l’espace de noms RealTimeStylusPlugins, qui contient le filtre de paquets et les plug-ins de convertisseur dynamique personnalisés. Cet espace de noms est référencé par le projet RealTimeStylusPluginApp. Le projet RealTimeStylusPlugins utilise les espaces de noms Microsoft.Ink, Microsoft.StylusInput et Microsoft.StylusInput.PluginData .

Pour obtenir une vue d’ensemble des espaces de noms Microsoft.StylusInput et Microsoft.StylusInput.PluginData , consultez Architecture des API StylusInput.

Plug-in de filtre de paquets

Le plug-in de filtre de paquets est un plug-in synchrone qui illustre la modification de paquets. Plus précisément, il définit un rectangle sur le formulaire. Tous les paquets dessinés en dehors de la région sont affichés à l’intérieur de la région. La classe de plug-in, PacketFilterPlugin, s’inscrit pour la notification des événements d’entrée StylusDown, StylusUpet Packets du stylet. La classe implémente les méthodes StylusDown, StylusUp et Packets définies sur la classe IStylusSyncPlugin .

Le constructeur public pour PacketFilterPlugin nécessite une structure Rectangle . Ce rectangle définit la zone rectangulaire, en coordonnées d’espace d’entrée manuscrite (0,01mm = 1 unité HIMETRIC), dans laquelle les paquets seront contenus. Le rectangle est conservé dans un champ privé, rectangle.

public class PacketFilterPlugin:IStylusSyncPlugin  
{
    private System.Drawing.Rectangle rectangle = System.Drawing.Rectangle.Empty;
    public PacketFilterPlugin(Rectangle r)
    {
        rectangle = r;
    }
    // ...

La PacketFilterPlugin classe s’inscrit pour les notifications d’événements en implémentant l’accesseur get pour la propriété DataInterest . Dans ce cas, le plug-in souhaite répondre aux StylusDownnotifications , Packets, StylusUpet Error . L’exemple retourne ces valeurs telles que définies dans l’énumération DataInterestMask . La méthode StylusDown est appelée lorsque la pointe du stylet contacte la surface du numériseur. La méthode StylusUp est appelée lorsque la pointe du stylet quitte la surface du numériseur. La méthode Packets est appelée lorsque l’objet RealTimeStylus reçoit des paquets. La méthode Error est appelée lorsque le plug-in actuel ou un plug-in précédent lève une exception.

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

La PacketFilterPlugin classe gère la plupart de ces notifications dans une méthode d’assistance, ModifyPacketData. La ModifyPacketData méthode obtient les valeurs x et y de chaque nouveau paquet à partir de la classe PacketsData . Si l’une ou l’autre valeur se trouve en dehors du rectangle, la méthode remplace la valeur par le point le plus proche qui se trouve toujours dans le rectangle. Il s’agit d’un exemple de la façon dont un plug-in peut remplacer les données de paquet à mesure qu’elles sont reçues du flux d’entrée de stylet.

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

Plug-in de renderer dynamique personnalisé

La CustomDynamicRenderer classe implémente également la classe IStylusSyncPlugin pour recevoir des notifications d’entrée de stylet. Il gère ensuite la Packets notification pour dessiner un petit cercle autour de chaque nouveau point de paquet.

La classe contient une variable Graphics qui contient une référence à l’objet graphics passé dans le constructeur de classe. Il s’agit de l’objet graphique utilisé pour le rendu dynamique.

private Graphics myGraphics;

public CustomDynamicRendererPlugin(Graphics g)
{
    myGraphics = g;
}
        //...
            

Lorsque le plug-in de rendu dynamique personnalisé reçoit une notification Packets, il extrait les données (x,y) et dessine un petit cercle vert autour du point. Il s’agit d’un exemple de rendu personnalisé basé sur le flux d’entrée de stylet.

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

Projet RealTimeStylusPluginApp

Le projet RealTimeStylusPluginApp illustre les plug-ins décrits précédemment, ainsi que les plug-ins GestureRecognizer et DynamicRenderer . L’interface utilisateur du projet se compose des éléments suivants :

  • Formulaire qui contient un contrôle GroupBox utilisé pour définir la zone d’entrée manuscrite.
  • Contrôle CheckedListBox pour répertorier et sélectionner les plug-ins disponibles.
  • Paire d’objets Button permettant de réorganiser les plug-ins.

Le projet définit une structure, PlugInListItem, pour faciliter la gestion des plug-ins utilisés dans le projet. La PlugInListItem structure contient le plug-in et une description.

La RealTimeStylusPluginApp classe elle-même implémente la classe IStylusAsyncPlugin . Cela est nécessaire pour que la RealTimeStylusPluginApp classe puisse être avertie lorsque le plug-in GestureRecognizer ajoute des données de mouvement à la file d’attente de sortie. L’application s’inscrit pour la notification de CustomStylusDataAdded. Lorsque des données de mouvement sont reçues, RealTimeStylusPluginApp placez une description de ces données sur la barre de status en bas du formulaire.

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

Notes

Dans l’implémentation CustomStylusDataAdded , il est intéressant que vous puissiez identifier les données de mouvement personnalisées dans la file d’attente de sortie par GUID (à l’aide du champ GestureRecognitionDataGuid ) ou par type (à l’aide du résultat de l’instruction as). L’exemple utilise les deux techniques d’identification à des fins de démonstration. L’une ou l’autre approche seule est également valide.

 

Dans le gestionnaire d’événements Load du formulaire, l’application crée des instances des PacketFilter classes et et CustomDynamicRenderer les ajoute à la zone de liste. L’application tente ensuite de créer un instance de la classe GestureRecognizer et, si elle réussit, l’ajoute à la zone de liste. Cette opération échoue si le module de reconnaissance de mouvement n’est pas présent sur le système. Ensuite, l’application instancie un objet DynamicRenderer et l’ajoute à la zone de liste. Enfin, l’application active chacun des plug-ins et l’objet RealTimeStylus lui-même.

Une autre chose importante à noter à propos de l’exemple est que dans les méthodes d’assistance, l’objet RealTimeStylus est d’abord désactivé avant que les plug-ins ne soient ajoutés ou supprimés, puis réactivé une fois l’ajout ou la suppression terminé.

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

Microsoft.StylusInput.DynamicRenderer

Microsoft.StylusInput.GestureRecognizer

Microsoft.StylusInput.RealTimeStylus

Microsoft.StylusInput.DataInterestMask

Microsoft.StylusInput.IStylusSyncPlugin

Microsoft.StylusInput.IStylusAsyncPlugin

Microsoft.StylusInput.PluginData.PacketsData

Accès et manipulation d’entrée de stylet

Plug-ins et classe RealTimeStylus

Exemple de collection d’encres RealTimeStylus