Beispiel für das RealTimeStylus-Plug-In

Diese Anwendung veranschaulicht das Arbeiten mit der RealTimeStylus-Klasse . Eine detaillierte Übersicht über die StylusInput-APIs, einschließlich der RealTimeStylus-Klasse , finden Sie unter Zugreifen auf und Bearbeiten von Eingabestiften. Informationen zu synchronen und asynchronen Plug-Ins finden Sie unter Plug-Ins und die RealTimeStylus-Klasse.

Übersicht über das Beispiel

Plug-Ins, Objekte, die die IStylusSyncPlugin - oder IStylusAsyncPlugin-Schnittstelle implementieren, können einem RealTimeStylus-Objekt hinzugefügt werden. Diese Beispielanwendung verwendet mehrere Arten von Plug-Ins:

  • Paketfilter-Plug-In: Ändert Pakete. Das Paketfilter-Plug-In in diesem Beispiel ändert Paketinformationen, indem es alle (x,y) Paketdaten innerhalb eines rechteckigen Bereichs einschränkt.
  • Benutzerdefiniertes Dynamisches Renderer-Plug-In: Ändert dynamische Renderingqualitäten. Das plug-in für benutzerdefiniertes dynamisches Rendering in diesem Beispiel ändert die Art und Weise, wie Freihand gerendert wird, indem es einen kleinen Kreis um jeden (x,y) Punkt auf einem Strich zeichnet.
  • Dynamisches Renderer-Plug-In: Ändert dynamische Renderingqualitäten. In diesem Beispiel wird die Verwendung des DynamicRenderer-Objekts als Plug-In zum Verarbeiten des dynamischen Renderings von Freihand veranschaulicht.
  • Gestenerkennungs-Plug-In: Erkennt Anwendungsgesten. Dieses Beispiel veranschaulicht die Verwendung des GestureRecognizer-Objekts als Plug-In zum Erkennen von Anwendungsgesten (bei Ausführung auf einem System mit vorhandener Microsoft-Gestenerkennung).

Darüber hinaus bietet dieses Beispiel eine Benutzeroberfläche, die es dem Benutzer ermöglicht, die Reihenfolge der einzelnen Plug-Ins in der Sammlung hinzuzufügen, zu entfernen und zu ändern. Die Beispiellösung enthält zwei Projekte: RealTimeStylusPluginApp und RealTimeStylusPlugins. RealTimeStylusPluginApp enthält die Benutzeroberfläche für das Beispiel. RealTimeStylusPlugins enthält die Implementierungen der Plug-Ins. Das RealTimeStylusPlugins-Projekt definiert den RealTimeStylusPlugins-Namespace, der den Paketfilter und benutzerdefinierte dynamische Renderer-Plug-Ins enthält. Auf diesen Namespace verweist das RealTimeStylusPluginApp-Projekt. Das RealTimeStylusPlugins-Projekt verwendet die Namespaces Microsoft.Ink, Microsoft.StylusInput und Microsoft.StylusInput.PluginData .

Eine Übersicht über die Namespaces Microsoft.StylusInput und Microsoft.StylusInput.PluginData finden Sie unter Architektur der StylusInput-APIs.

Paketfilter-Plug-In

Das Paketfilter-Plug-In ist ein synchrones Plug-In, das die Paketänderung veranschaulicht. Insbesondere definiert es ein Rechteck im Formular. Alle Pakete, die außerhalb der Region gezeichnet werden, werden innerhalb der Region gerendert. Die Plug-In-Klasse , PacketFilterPluginregistriert sich für Benachrichtigungen von StylusDownEingabeereignissen, StylusUp, und Packets Stifteingabeereignissen. Die Klasse implementiert die Für die IStylusSyncPlugin-KlassedefiniertenMethoden StylusDown, StylusUp und Packets.

Der öffentliche Konstruktor für PacketFilterPlugin erfordert eine Rectangle-Struktur . Dieses Rechteck definiert den rechteckigen Bereich in Freihandraumkoordinaten (.01mm = 1 HIMETRIC-Einheit), in dem Pakete enthalten sind. Das Rechteck befindet sich in einem privaten Feld, rectangle.

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

Die PacketFilterPlugin -Klasse registriert sich für Ereignisbenachrichtigungen, indem sie den get-Accessor für die DataInterest-Eigenschaft implementiert. In diesem Fall ist das Plug-In daran interessiert, auf die StylusDownBenachrichtigungen, Packets, StylusUpund Error zu reagieren. Das Beispiel gibt diese Werte zurück, wie in der DataInterestMask-Enumeration definiert. Die StylusDown-Methode wird aufgerufen, wenn die Stiftspitze die Digitizeroberfläche kontaktiert. Die StylusUp-Methode wird aufgerufen, wenn die Stiftspitze die Digitizeroberfläche verlässt. Die Packets-Methode wird aufgerufen, wenn das RealTimeStylus-Objekt Pakete empfängt. Die Error-Methode wird aufgerufen, wenn das aktuelle Plug-In oder ein vorheriges Plug-In eine Ausnahme auslöst.

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

Die PacketFilterPlugin -Klasse verarbeitet die meisten dieser Benachrichtigungen in einer Hilfsmethode, ModifyPacketData. Die ModifyPacketData -Methode ruft die x- und y-Werte für jedes neue Paket aus der PacketsData-Klasse ab. Wenn sich ein Wert außerhalb des Rechtecks befindet, ersetzt die Methode den Wert durch den nächstgelegenen Punkt, der weiterhin innerhalb des Rechtecks liegt. Dies ist ein Beispiel dafür, wie ein Plug-In Paketdaten ersetzen kann, wenn sie vom Stifteingabestream empfangen werden.

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

Benutzerdefiniertes Dynamisches Renderer-Plug-In

Die CustomDynamicRenderer -Klasse implementiert auch die IStylusSyncPlugin-Klasse , um Stifteingabebenachrichtigungen zu empfangen. Anschließend wird die Packets Benachrichtigung verarbeitet, um einen kleinen Kreis um jeden neuen Paketpunkt zu zeichnen.

Die -Klasse enthält eine Graphics-Variable , die einen Verweis auf das Grafikobjekt enthält, das an den Klassenkonstruktor übergeben wird. Dies ist das Grafikobjekt, das für das dynamische Rendering verwendet wird.

private Graphics myGraphics;

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

Wenn das benutzerdefinierte dynamische Renderer-Plug-In eine Paketbenachrichtigung empfängt, extrahiert es die (x,y)-Daten und zeichnet einen kleinen grünen Kreis um den Punkt. Dies ist ein Beispiel für ein benutzerdefiniertes Rendering basierend auf dem Stifteingabestream.

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

Das RealTimeStylusPluginApp-Projekt

Das RealTimeStylusPluginApp-Projekt veranschaulicht die zuvor beschriebenen Plug-Ins sowie die Gesterecognizer - und DynamicRenderer-Plug-Ins . Die Benutzeroberfläche des Projekts besteht aus:

Das Projekt definiert eine Struktur, PlugInListItem, um die Verwaltung der im Projekt verwendeten Plug-Ins zu vereinfachen. Die PlugInListItem Struktur enthält das Plug-In und eine Beschreibung.

Die RealTimeStylusPluginApp Klasse selbst implementiert die IStylusAsyncPlugin-Klasse . Dies ist erforderlich, damit die RealTimeStylusPluginApp Klasse benachrichtigt werden kann, wenn das Gestenrecognizer-Plug-In der Ausgabewarteschlange Gestendaten hinzufügt. Die Anwendung registriert sich für die Benachrichtigung von CustomStylusDataAdded. Wenn Gestendaten empfangen werden, RealTimeStylusPluginApp platziert eine Beschreibung davon auf der status leiste am unteren Rand des Formulars.

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

Hinweis

In der CustomStylusDataAdded-Implementierung ist es interessant, dass Sie die benutzerdefinierten Gestendaten in der Ausgabewarteschlange entweder durch GUID (mithilfe des Felds GestureRecognitionDataGuid ) oder nach typ (mithilfe des Ergebnisses aus der as-Anweisung) identifizieren können. Das Beispiel verwendet beide Identifizierungstechniken zu Demonstrationszwecken. Beide Ansätze allein sind ebenfalls gültig.

 

Im Load-Ereignishandler des Formulars erstellt die Anwendung Instanzen der PacketFilter - und CustomDynamicRenderer -Klasse und und fügt sie dem Listenfeld hinzu. Anschließend versucht die Anwendung, eine instance der GestureRecognizer-Klasse zu erstellen, und fügt sie bei erfolgreicher Ausführung dem Listenfeld hinzu. Dies schlägt fehl, wenn die Gestenerkennung im System nicht vorhanden ist. Als Nächstes instanziiert die Anwendung ein DynamicRenderer-Objekt und fügt es dem Listenfeld hinzu. Schließlich aktiviert die Anwendung jedes Plug-Ins und das RealTimeStylus-Objekt selbst.

Eine weitere wichtige Sache zum Beispiel ist, dass in den Hilfsmethoden das RealTimeStylus-Objekt zuerst deaktiviert wird, bevor Plug-Ins hinzugefügt oder entfernt werden, und nach Abschluss des Hinzufügens oder Entfernens erneut aktiviert werden.

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

Zugreifen auf und Bearbeiten von Eingabestiften

Plug-Ins und die RealTimeStylus-Klasse

Beispiel für die RealTimeStylus-Freihandsammlung