Exemple de plug-in RealTimeStylus

Cette application illustre l’utilisation de 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 du 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, 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. Dans cet exemple, le plug-in de filtre de paquets modifie les informations de paquets en limitant toutes les données de paquet (x, y) au sein d’une zone rectangulaire.
  • Plug-in de rendu dynamique personnalisé : modifie les qualités de rendu dynamiques. Dans cet exemple, le plug-in de rendu dynamique personnalisé modifie la façon dont l’encre est rendue en dessinant un petit cercle autour de chaque point (x, y) sur un trait.
  • Plug-in de rendu dynamique : modifie les qualités de rendu dynamiques. Cet exemple illustre l’utilisation de l’objet DynamicRenderer en tant que plug-in pour gérer le rendu dynamique de l’encre.
  • Plug-in de module de reconnaissance de mouvement : reconnaît les gestes d’application. Cet exemple illustre l’utilisation de l’objet GestureRecognizer en tant que plug-in pour reconnaître les gestes d’application (en cas d’exécution sur un système sur lequel le module de reconnaissance de mouvement Microsoft est 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 de 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 les plug-ins filtre de paquets et convertisseur dynamique personnalisé. Cet espace de noms est référencé par le projet RealTimeStylusPluginApp. Le projet RealTimeStylusPlugins utilise les espaces de noms Microsoft. Ink, Microsoft. StylusInputet 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 qui sont dessinés en dehors de la région sont rendus à l’intérieur de la région. La classe de plug-in, PacketFilterPlugin , s’inscrit pour la notification des StylusDown StylusUp Packets événements d’entrée de stylet, et. La classe implémente les méthodes StylusDown, StylusUpet Packets définies sur la classe IStylusSyncPlugin .

Le constructeur public pour PacketFilterPlugin requiert une structure rectangle . Ce rectangle définit la zone rectangulaire, en coordonnées d’espace d’encre (. 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 s’intéresse à répondre aux StylusDown Packets StylusUp notifications,, et Error . L’exemple retourne ces valeurs telles qu’elles sont définies dans l’énumération DataInterestMask . La méthode StylusDown est appelée lorsque l’info-bulle du stylet contacte la surface du digitaliseur. La méthode StylusUp est appelée lorsque la pointe du stylet quitte la surface du digitaliseur. La méthode Packets est appelée lorsque l’objet RealTimeStylus reçoit des paquets. La méthode d' erreur est appelée quand 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 de la classe PacketsData . Si l’une des valeurs est à l’extérieur 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 des données de paquets au fur et à mesure de leur réception à partir 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 rendu 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 Graphics 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 de paquets, 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);
    }
}

RealTimeStylusPluginApp Project

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.
  • Un contrôle CheckedListBox pour répertorier et sélectionner les plug-ins disponibles.
  • Paire d' objets bouton qui permet 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 afin que la RealTimeStylusPluginApp classe puisse être notifiée lorsque le plug-in GestureRecognizer ajoute des données de mouvement à la file d’attente de sortie. L’application s’inscrit à la notification de CustomStylusDataAdded. Une fois les données de mouvement reçues, RealTimeStylusPluginApp les insèrent une description dans la barre d’État 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 de pouvoir 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 est également valide.

Dans le gestionnaire d’événements Load du formulaire, l’application crée des instances PacketFilter des CustomDynamicRenderer classes et, puis les ajoute à la zone de liste. L’application tente ensuite de créer une instance de la classe GestureRecognizer et, en cas de réussite, l’ajoute à la zone de liste. Cela é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.

Il est également important de noter que dans les méthodes d’assistance, l’objet RealTimeStylus est désactivé avant l’ajout ou la suppression de plug-ins, 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 de l’entrée du stylet

Plug-ins et classe RealTimeStylus

Exemple de collection d’encres RealTimeStylus