次の方法で共有


RealTimeStylus プラグインのサンプル

このアプリケーションは、 RealTimeStylus クラスの操作を示しています。 RealTimeStylus クラスなど、StylusInput API の詳細な概要については、「スタイラス入力へのアクセスと操作」を参照してください。 同期プラグインと非同期プラグインの詳細については、「 プラグインと RealTimeStylus クラス」を参照してください。

サンプルの概要

プラグイン、 IStylusSyncPlugin または IStylusAsyncPlugin インターフェイスを実装するオブジェクトを RealTimeStylus オブジェクトに追加できます。 このサンプル アプリケーションでは、いくつかの種類のプラグインを使用します。

  • パケット フィルター プラグイン: パケットを変更します。 このサンプルのパケット フィルター プラグインは、四角形領域内のすべての (x,y) パケット データを制約することで、パケット情報を変更します。
  • カスタム動的レンダラー プラグイン: 動的レンダリング品質を変更します。 このサンプルのカスタム ダイナミック レンダリング プラグインは、ストローク上の各 (x,y) ポイントの周りに小さな円を描画することで、インクのレンダリング方法を変更します。
  • 動的レンダラー プラグイン: 動的レンダリング品質を変更します。 このサンプルでは、インクの動的レンダリングを処理するためのプラグインとして DynamicRenderer オブジェクトを使用する方法を示します。
  • ジェスチャ認識エンジン プラグイン: アプリケーション ジェスチャを認識します。 このサンプルでは、アプリケーション ジェスチャを認識するためのプラグインとして GestureRecognizer オブジェクトを使用する方法を示します (Microsoft ジェスチャ認識エンジンが存在するシステムで実行されている場合)。

さらに、このサンプルでは、ユーザーがコレクション内の各プラグインの追加、削除、および順序の変更を行えるユーザー インターフェイスを提供します。 このサンプル ソリューションには、RealTimeStylusPluginApp と RealTimeStylusPlugins という 2 つのプロジェクトが含まれています。 RealTimeStylusPluginApp には、サンプルのユーザー インターフェイスが含まれています。 RealTimeStylusPlugins には、プラグインの実装が含まれています。RealTimeStylusPlugins プロジェクトは、パケット フィルターとカスタム動的レンダラー プラグインを含む RealTimeStylusPlugins 名前空間を定義します。この名前空間は、RealTimeStylusPluginApp プロジェクトによって参照されます。 RealTimeStylusPlugins プロジェクトでは、 Microsoft.InkMicrosoft.StylusInputおよび Microsoft.StylusInput.PluginData 名前空間を使用します。

Microsoft.StylusInput 名前空間と Microsoft.StylusInput.PluginData 名前空間の概要については、「StylusInput API のアーキテクチャ」を参照してください。

パケット フィルター プラグイン

パケット フィルター プラグインは、パケット変更を示す同期プラグインです。 具体的には、フォーム上に四角形を定義します。 リージョンの外部に描画されるすべてのパケットは、リージョン内にレンダリングされます。 プラグイン クラス の は、PacketFilterPluginおよび Packets ペン入力イベントのStylusDownStylusUp通知に登録します。 クラスは、IStylusSyncPlugin クラスで定義されている StylusDownStylusUp、Packets メソッドを実装します。

のパブリック コンストラクター PacketFilterPlugin には 、Rectangle 構造体が必要です。 この四角形は、パケットが含まれる四角形領域をインク空間座標 (.01mm = 1 HIMETRIC 単位) で定義します。 四角形は、プライベート フィールド rectangleに保持されます。

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

クラスは PacketFilterPluginDataInterest プロパティの get アクセサーを実装することで、イベント通知を登録します。 この場合、プラグインは、および Error の通知に応答することにStylusUpStylusDownPackets関心があります。 このサンプルでは、 DataInterestMask 列挙で定義されているこれらの値を返します。 StylusDown メソッドは、ペン先がデジタイザーサーフェスに接触したときに呼び出されます。 StylusUp メソッドは、ペン先がデジタイザーサーフェスから離れると呼び出されます。 Packets メソッドは、RealTimeStylus オブジェクトがパケットを受信するときに呼び出されます。 Error メソッドは、現在のプラグインまたは以前のプラグインが例外をスローしたときに呼び出されます。

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

クラスは PacketFilterPluginModifyPacketDataヘルパー メソッド でこれらの通知の大部分を処理します。 メソッドは ModifyPacketDataPacketsData クラスから新しい各パケットの x 値と y 値を取得します。 いずれかの値が四角形の外側にある場合、 メソッドは、その値を、四角形内の最も近いポイントに置き換えます。 これは、プラグインがペン入力ストリームから受信したパケット データを置き換える方法の例です。

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

カスタム動的レンダラー プラグイン

クラスは CustomDynamicRenderer 、ペン入力通知を受け取る IStylusSyncPlugin クラスも実装します。 その後、通知を Packets 処理して、新しい各パケット ポイントの周りに小さな円を描画します。

クラスには、クラス コンストラクターに渡されるグラフィックス オブジェクトへの参照を保持する Graphics 変数が含まれています。 これは、動的レンダリングに使用されるグラフィックス オブジェクトです。

private Graphics myGraphics;

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

カスタム動的レンダラー プラグインは、パケット通知を受け取ると、(x,y) データを抽出し、ポイントの周りに小さな緑色の円を描画します。 これは、ペン入力ストリームに基づくカスタム レンダリングの例です。

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 プロジェクト

RealTimeStylusPluginApp プロジェクトでは、前に説明したプラグインと、 GestureRecognizer プラグインと DynamicRenderer プラグインを示します。プロジェクトのユーザー インターフェイスは次で構成されます。

  • インク入力領域の定義に使用される GroupBox コントロールを含む Form。
  • 使用可能なプラグインを一覧表示して選択する CheckedListBox コントロール。
  • プラグインの順序を変更できるようにする Button オブジェクト のペア。

プロジェクトでは、 PlugInListItemプロジェクトで使用されるプラグインの管理を容易にするために、 という構造が定義されています。 構造体には PlugInListItem 、プラグインと説明が含まれています。

クラス自体はRealTimeStylusPluginApp、IStylusAsyncPlugin クラスを実装します。 これは、GestureRecognizer プラグインがジェスチャ データをRealTimeStylusPluginApp出力キューに追加したときにクラスに通知できるようにするために必要です。 アプリケーションは CustomStylusDataAdded の通知に登録します。 ジェスチャ データを受信すると、 RealTimeStylusPluginApp フォームの下部にあるステータス バーにその説明が表示されます。

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

Note

CustomStylusDataAdded 実装では、GUID (GestureRecognitionDataGuid フィールドを使用) または型 (as ステートメントの結果を使用) によって、出力キュー内のカスタム ジェスチャ データを識別できることは興味深い点です。 このサンプルでは、デモ目的で両方の識別手法を使用します。 どちらの方法も有効です。

 

フォームの Load イベント ハンドラーでは、アプリケーションによって クラスと CustomDynamicRenderer クラスのインスタンスがPacketFilter作成され、リスト ボックスに追加されます。 その後、アプリケーションは GestureRecognizer クラスのインスタンスの作成を試み、成功した場合はリスト ボックスに追加します。 ジェスチャ認識エンジンがシステムに存在しない場合、これは失敗します。 次に、アプリケーションによって DynamicRenderer オブジェクトがインスタンス化され、リスト ボックスに追加されます。 最後に、アプリケーションは、各プラグインと RealTimeStylus オブジェクト自体を有効にします。

このサンプルに関するもう 1 つの重要な点は、ヘルパー メソッドでは、プラグインが追加または削除される前に RealTimeStylus オブジェクトが最初に無効になり、追加または削除が完了した後に再度有効になるということです。

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

スタイラス入力へのアクセスと操作

プラグインと RealTimeStylus クラス

RealTimeStylus Ink Collection のサンプル