Sdílet prostřednictvím


Ukázka modulu plug-in RealTimeStylus

Tato aplikace ukazuje práci s třídou RealTimeStylus. Podrobný přehled rozhraní API StylusInput, včetně třídy RealTimeStylus, naleznete v tématu Přístup a manipulace se vstupem Stylus. Informace o synchronních a asynchronních modulech plug-in naleznete v tématu Moduly plug-in a třída RealTimeStylus.

Přehled ukázky

Moduly plug-in, objekty, které implementují rozhraní IStylusSyncPlugin nebo IStylusAsyncPlugin, lze přidat do objektu RealTimeStylus. Tato ukázková aplikace používá několik typů modulů plug-in:

  • Modul plug-in filtru paketů: Upravuje pakety. Modul plug-in filtru paketů v této ukázce upraví informace o paketech omezením všech dat paketů (x,y) v obdélníkové oblasti.
  • Vlastní modul plug-in Dynamic Renderer: Upravuje vlastnosti dynamického vykreslování. Vlastní modul plug-in dynamického vykreslování v této ukázce upraví způsob vykreslení rukopisu tak, že kolem každého bodu (x,y) na tahu nakreslí malý kruh.
  • Modul plug-in dynamického rendereru: Upravuje vlastnosti dynamického vykreslování. Tato ukázka ukazuje použití objektu DynamicRenderer jako zásuvného modulu pro zpracování dynamického vykreslování inkoustu.
  • Modul plug-in pro rozpoznávání gest: Rozpozná gesta aplikací. Tato ukázka ukazuje použití objektu GestureRecognizer jako modulu plug-in k rozpoznávání gest aplikací (při spuštění v systému s přítomným rozpoznáváním gest Microsoftu).

Tato ukázka navíc poskytuje uživatelské rozhraní, které uživateli umožňuje přidávat, odebírat a měnit pořadí jednotlivých modulů plug-in v kolekci. Ukázkové řešení obsahuje dva projekty RealTimeStylusPluginApp a RealTimeStylusPlugins. RealTimeStylusPluginApp obsahuje uživatelské rozhraní pro ukázku. RealTimeStylusPlugins obsahuje implementace modulů plug-in. Projekt RealTimeStylusPlugins definuje obor názvů RealTimeStylusPlugins, který obsahuje filtr paketů a vlastní moduly plug-in dynamického rendereru. Na tento obor názvů odkazuje projekt RealTimeStylusPluginApp. Projekt RealTimeStylusPlugins používá Microsoft.Ink, Microsoft.StylusInputa Microsoft.StylusInput.PluginData obory názvů.

Přehled oborů názvů Microsoft.StylusInput a Microsoft.StylusInput.PluginData naleznete v tématu Architektura rozhraní StylusInput APIs.

Modul plugin filtru paketů

Plug-in filtru paketů je synchronní nástroj, který ukazuje úpravy paketů. Konkrétně definuje obdélník ve formuláři. Všechny pakety, které jsou vykresleny mimo oblast, se vykreslí uvnitř oblasti. Třída plug-in PacketFilterPluginregistruje se k oznámení o událostech zadávání perem StylusDown, StylusUpa Packets. Třída implementuje StylusDown, StylusUpa Packets metody definované na IStylusSyncPlugin třídy.

Veřejný konstruktor pro PacketFilterPlugin vyžaduje strukturu obdélníku. Tento obdélník definuje obdélníkovou oblast, vyjádřenou v souřadnicích v prostoru inkoustu (0,01 mm = 1 jednotka HIMETRIC), kde budou pakety zahrnuty. Obdélník je uložen v soukromém poli, rectangle.

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

Třída PacketFilterPlugin se registruje k oznámením událostí implementací přistupovače get pro vlastnost DataInterest. V tomto případě se modul plug-in zajímá o reakci na oznámení StylusDown, Packets, StylusUpa Error. Ukázka vrátí tyto hodnoty, jak je definováno ve výčtu DataInterestMask. Když se hrot pera dotkne povrchu digitizátoru, je volána metoda StylusDown. Metoda StylusUp je volána, když špička pera opustí povrch digitizátoru. Packets metoda je volána, když RealTimeStylus objekt přijímá pakety. Metoda Error je volána, když aktuální zásuvný modul nebo předchozí zásuvný modul vyvolá výjimku.

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

Třída PacketFilterPlugin zpracovává většinu těchto oznámení pomocí pomocné metody ModifyPacketData. Metoda ModifyPacketData získá hodnoty x a y pro každý nový paket z třídy PacketsData. Pokud je obě hodnoty mimo obdélník, metoda nahradí hodnotu nejbližším bodem, který stále spadá do obdélníku. Toto je příklad toho, jak může plug-in nahradit data paketů, jakmile jsou přijaty ze vstupu z pera.

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

Vlastní modul plug-in Dynamic Renderer

Třída CustomDynamicRenderer také implementuje třídu IStylusSyncPlugin pro příjem oznámení o psaní perem. Potom zpracuje oznámení Packets, aby kolem každého nového bodu paketu nakreslí malý kruh.

Třída obsahuje Graphics proměnnou, která obsahuje odkaz na grafický objekt předaný do konstruktoru třídy. Toto je grafický objekt používaný k dynamickému vykreslování.

private Graphics myGraphics;

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

Když vlastní modul plug-in dynamického rendereru obdrží oznámení o paketech, extrahuje data (x,y) a kolem bodu nakreslí malý zelený kruh. Toto je příklad vlastního vykreslování založeného na streamu pro zadání pera.

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

Projekt RealTimeStylusPluginApp

Projekt RealTimeStylusPluginApp demonstruje dříve popsané plug-iny, stejně jako plug-iny GestureRecognizer a DynamicRenderer. Uživatelské rozhraní projektu se skládá z:

  • Formulář, který obsahuje ovládací prvek GroupBox sloužící k definování oblasti pro zadávání rukopisu.
  • Ovládací prvek CheckedListBox pro zobrazení a výběr dostupných pluginů.
  • Dvojice objektů Button pro umožnění přeuspořádání plug-inů.

Projekt definuje strukturu, PlugInListItem, aby bylo snazší spravovat moduly plug-in používané v projektu. Struktura PlugInListItem obsahuje zásuvný modul a popis.

Samotná třída RealTimeStylusPluginApp implementuje třídu IStylusAsyncPlugin. To je nezbytné, aby třída RealTimeStylusPluginApp mohla být upozorněna, když plug-in GestureRecognizer přidá data gest do výstupní fronty. Aplikace zaregistruje oznámení CustomStylusDataAdded. Při přijetí dat gest RealTimeStylusPluginApp umístí popis na stavový řádek v dolní části formuláře.

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

Poznámka

V CustomStylusDataAdded implementaci je zajímavé, že můžete identifikovat vlastní data gest ve výstupní frontě buď pomocí identifikátoru GUID (pomocí pole GestureRecognitionDataGuid) nebo podle typu (pomocí výsledku z příkazu 'as'). Ukázka používá obě metody identifikace pro demonstrační účely. Oba přístupy jsou také platné.

 

V obslužné rutině události načtení formuláře vytvoří aplikace instance tříd PacketFilter a CustomDynamicRenderer a přidá je do seznamu. Aplikace se pak pokusí vytvořit instanci třídy GestureRecognizer a v případě úspěchu ji přidá do seznamu. To selže, pokud v systému není k dispozici rozpoznávání gest. Dále aplikace vytvoří instanci objektu DynamicRenderer, který přidá do seznamu. Nakonec aplikace povolí každý ze zásuvných modulů a samotný objekt RealTimeStylus.

Další důležitou věcí, kterou je potřeba si uvědomit o ukázce, je, že v pomocných metodách je objekt RealTimeStylus nejprve zakázán před přidáním nebo odebráním modulů plug-in a po dokončení přidání nebo odebrání znovu povolen.

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

Přístup k vstupu perem a manipulace s jeho vstupy

Zásuvné moduly a třída RealTimeStylus

Ukázka kolekce RealTimeStylus Ink