Udostępnij za pośrednictwem


Przykład wtyczki RealTimeStylus

Ta aplikacja demonstruje pracę z klasą RealTimeStylus. Aby zapoznać się ze szczegółowym omówieniem interfejsów API StylusInput, w tym klasy RealTimeStylus, zobacz Uzyskiwanie dostępu do danych wejściowych Stylus i manipulowanie nimi. Aby uzyskać informacje na temat wtyczek synchronicznych i asynchronicznych, zobacz Plug-ins and the RealTimeStylus Class.

Omówienie przykładu

Wtyczki, obiekty implementujące interfejs IStylusSyncPlugin lub IStylusAsyncPlugin interfejsu można dodać do obiektu RealTimeStylus. Ta przykładowa aplikacja używa kilku typów wtyczek:

  • Wtyczka filtru pakietów: modyfikuje pakiety. Wtyczka filtru pakietów w tym przykładzie modyfikuje informacje o pakiecie przez ograniczenie wszystkich danych pakietów (x,y) w prostokątnym obszarze.
  • Niestandardowa wtyczka dynamicznego modułu renderowania: modyfikuje dynamiczne cechy renderowania. Niestandardowa dynamiczna wtyczka renderowania w tym przykładzie modyfikuje sposób renderowania tuszu, rysując małe okręgi wokół każdego punktu (x,y) na pociągnięciu.
  • Wtyczka dynamicznego modułu renderowania: modyfikuje dynamiczne cechy renderowania. W tym przykładzie pokazano użycie obiektu DynamicRenderer jako dodatku do obsługi dynamicznego renderowania tuszu.
  • Wtyczka rozpoznawania gestów: rozpoznaje gesty aplikacji. W tym przykładzie pokazano użycie obiektu GestureRecognizer jako dodatku rozszerzającego do rozpoznawania gestów aplikacji (gdy uruchamiany jest na systemie z rozpoznawaniem gestów Microsoft).

Ponadto ten przykład udostępnia interfejs użytkownika, który umożliwia użytkownikowi dodawanie, usuwanie i zmienianie kolejności każdej wtyczki w kolekcji. Przykładowe rozwiązanie zawiera dwa projekty: RealTimeStylusPluginApp i RealTimeStylusPlugins. Aplikacja RealTimeStylusPluginApp zawiera interfejs użytkownika dla przykładu. Funkcja RealTimeStylusPlugins zawiera implementacje wtyczek. Projekt RealTimeStylusPlugins definiuje przestrzeń nazw RealTimeStylusPlugins, która zawiera filtr pakietów i niestandardowe wtyczki modułu renderowania dynamicznego. Ta przestrzeń nazw jest przywołyana przez projekt RealTimeStylusPluginApp. Projekt RealTimeStylusPlugins używa Microsoft.Ink, Microsoft.StylusInputi Microsoft.StylusInput.PluginData przestrzeni nazw.

Aby zapoznać się z omówieniem przestrzeni nazw Microsoft.StylusInput i Microsoft.StylusInput.PluginData, zobacz Architektura interfejsów API StylusInput.

Wtyczka filtru pakietów

Wtyczka filtru pakietów jest wtyczką synchroniczną, która demonstruje modyfikację pakietów. W szczególności definiuje prostokąt w formularzu. Wszystkie pakiety pobierane poza regionem są renderowane wewnątrz regionu. Klasa wtyczki, PacketFilterPlugin, rejestruje się w celu powiadomienia o StylusDown, StylusUpi Packets zdarzeniach wprowadzania pióra. Klasa implementuje metody StylusDown, StylusUpi Pakiety zdefiniowane w klasie IStylusSyncPlugin.

Publiczny konstruktor dla PacketFilterPlugin wymaga struktury prostokąta . Ten prostokąt definiuje prostokątny obszar w współrzędnych przestrzeni tuszu (.01 mm = 1 jednostka HIMETRIC), w którym będą zawierane pakiety. Prostokąt jest przechowywany w polu prywatnym, rectangle.

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

Klasa PacketFilterPlugin rejestruje powiadomienia o zdarzeniach, implementując metodę get dla właściwości DataInterest. W tym przypadku wtyczka jest zainteresowana odpowiadaniem na powiadomienia StylusDown, Packets, StylusUpi Error. Przykład zwraca te wartości, jak określono w enumeracji DataInterestMask. Metoda StylusDown jest wywoływana, gdy czubek pióra kontaktuje się z powierzchnią digitalizatora. Metoda StylusUp jest wywoływana, gdy końcówka pióra opuszcza powierzchnię cyfryzatora. Metoda pakietów jest wywoływana, gdy obiekt RealTimeStylus odbiera pakiety. Metoda Error jest wywoływana, gdy bieżąca wtyczka lub poprzednia wtyczka zgłasza wyjątek.

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

Klasa PacketFilterPlugin obsługuje większość tych powiadomień w metodzie pomocniczej, ModifyPacketData. Metoda ModifyPacketData pobiera wartości x i y dla każdego nowego pakietu z klasy PacketsData. Jeśli którakolwiek wartość znajduje się poza prostokątem, metoda zastępuje wartość najbliższym punktem, który nadal znajduje się w prostokątze. Jest to przykład sposobu, w jaki wtyczka może zastąpić dane pakietu w miarę jak są odbierane ze strumienia wejściowego pióra.

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

Niestandardowa wtyczka modułu renderowania dynamicznego

Klasa CustomDynamicRenderer implementuje również klasę IStylusSyncPlugin w celu odbierania powiadomień wejściowych piórem. Następnie obsługuje powiadomienie Packets, aby narysować mały okrąg wokół każdego nowego punktu pakietu.

Klasa zawiera zmienną Graphics, która zawiera odwołanie do obiektu graficznego przekazanego do konstruktora klasy. Jest to obiekt graficzny używany do renderowania dynamicznego.

private Graphics myGraphics;

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

Gdy niestandardowa wtyczka renderowania dynamicznego odbiera powiadomienie o pakietach, wyodrębnia dane (x, y) i rysuje zielony mały okrąg wokół punktu. Jest to przykład renderowania niestandardowego na podstawie strumienia danych wejściowych pióra.

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 wcześniej opisane wtyczki, a także wtyczki GestureRecognizer i DynamicRenderer. Interfejs użytkownika projektu składa się z następujących elementów:

  • Formularz zawierający kontrolkę GroupBox służącą do definiowania obszaru wprowadzania tuszu.
  • Kontrolka typu CheckedListBox do wyświetlania listy i wyboru dostępnych wtyczek.
  • Para obiektów typu Button, aby umożliwić zmianę kolejności wtyczek.

Projekt definiuje strukturę, PlugInListItem, aby ułatwić zarządzanie wtyczkami używanymi w projekcie. Struktura PlugInListItem zawiera wtyczkę i opis.

Klasa RealTimeStylusPluginApp implementuje klasę IStylusAsyncPlugin. Jest to konieczne, aby można było powiadomić klasę RealTimeStylusPluginApp, gdy wtyczka GestureRecognizer dodaje dane gestów do kolejki wyjściowej. Aplikacja rejestruje się do otrzymywania powiadomień o CustomStylusDataAdded. Po odebraniu danych gestów RealTimeStylusPluginApp umieszcza opis na pasku stanu w dolnej części formularza.

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

Notatka

W implementacji CustomStylusDataAdded jest interesujące, że można zidentyfikować niestandardowe dane gestów w kolejce wyjściowej albo za pomocą identyfikatora GUID (przy użyciu pola GestureRecognitionDataGuid), albo według typu (przy użyciu wyniku z instrukcji as). W przykładzie użyto obu technik identyfikacji do celów demonstracyjnych. Każde z podejść jest również prawidłowe samodzielnie.

 

W procedurze obsługi zdarzenia ładowania formularza aplikacja tworzy wystąpienia klas PacketFilter i CustomDynamicRenderer i dodaje je do listy. Następnie aplikacja próbuje utworzyć wystąpienie klasy GestureRecognizer i, jeśli się powiedzie, doda je do pola listy. Nie powiedzie się, jeśli rozpoznawanie gestów nie jest obecne w systemie. Następnie aplikacja tworzy wystąpienie obiektu DynamicRenderer i dodaje go do pola listy. Na koniec aplikacja włącza każdą z wtyczek oraz sam obiekt RealTimeStylus.

Należy pamiętać o tym, że w metodach pomocniczych obiekt RealTimeStylus jest najpierw wyłączony przed dodaniem lub usunięciem wtyczek, a następnie jest ponownie włączony po zakończeniu dodawania lub usuwania.

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

Uzyskiwanie dostępu i manipulowanie danymi z rysika

Wtyczki i klasa RealTimeStylus

przykład kolekcji RealTimeStylus Ink Collection