共用方式為


RealTimeStylus 外掛程式範例

此應用程式示範如何使用 RealTimeStylus 類別。 如需 StylusInput API 的詳細概觀,包括 RealTimeStylus 類別,請參閱 存取及操作手寫筆輸入。 如需同步和異步外掛程式的相關信息,請參閱 外掛程式和 RealTimeStylus 類別

範例概觀

實作 IStylusSyncPluginIStylusAsyncPlugin 介面的外掛程式物件可以新增至 RealTimeStylus 物件。 這個範例應用程式使用數種類型的外掛程式:

  • 封包篩選外掛程式:修改封包。 此範例中的封包篩選外掛程式會透過限制所有 (x, y) 封包數據在一個矩形區域內來修改封包資訊。
  • 自定義動態轉譯器外掛程式:修改動態轉譯品質。 此範例中的自訂動態渲染外掛程式會透過在筆劃上的每個(x, y)點周圍繪製小圓圈,來修改墨跡的顯示方式。
  • 動態轉譯器外掛程式:修改動態轉譯品質。 此範例示範如何使用 DynamicRenderer 對象作為外掛程式來處理筆跡的動態轉譯。
  • 手勢辨識器外掛程式:辨識應用程式手勢。 此範例示範如何使用 GestureRecognizer 對象作為外掛程式來辨識應用程式手勢(在Microsoft筆勢辨識器存在的系統上執行時)。

此外,此範例提供使用者介面,可讓使用者新增、移除和變更集合中每個外掛程式的順序。 此範例解決方案包含兩個專案:RealTimeStylusPluginApp 和 RealTimeStylusPlugins。 RealTimeStylusPluginApp 包含範例的使用者介面。 RealTimeStylusPlugins 包含外掛程式的實作。RealTimeStylusPlugins 專案會定義 RealTimeStylusPlugins 命名空間,其中包含封包篩選和自定義動態轉譯器外掛程式。這個命名空間是由 RealTimeStylusPluginApp 項目所參考。 RealTimeStylusPlugins 專案使用 Microsoft.InkMicrosoft.StylusInputMicrosoft.StylusInput.PluginData 命名空間。

如需 Microsoft.StylusInputMicrosoft.StylusInput.PluginData 命名空間的概觀,請參閱 stylusInput API 架構。

封包篩選外掛程式

封包篩選外掛程式是示範封包修改的同步外掛程式。 具體而言,它會在表單上定義一個矩形。 在區域外部繪製的任何封包,會在區域內轉譯。 外掛程式類別 PacketFilterPlugin註冊了 StylusDownStylusUpPackets 的手寫筆輸入事件通知。 類別會實作 StylusDownStylusUpPacketsIStylusSyncPlugin 類別上定義的方法。

PacketFilterPlugin 的公用建構函式需要 矩形 結構。 此矩形在筆跡空間座標中定義了一個矩形區域(1 HIMETRIC 單位 = 0.01 毫米),封包將包含在此區域內。 矩形會被存放在私有欄位 rectangle中。

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

PacketFilterPlugin 類別會實作 DataInterest 屬性的 get 存取子,以註冊事件通知。 在此情況下,外掛程式有興趣回應 StylusDownPacketsStylusUpError 通知。 此範例會依據 DataInterestMask 列舉中所定義的內容傳回這些值。 當筆尖接觸數位板表面時,會呼叫 StylusDown 方法。 當筆尖離開數位板表面時,會呼叫 StylusUp 方法。 當 RealTimeStylus 物件接收封包時,會呼叫 Packets 方法。 當目前的外掛程式或先前的外掛程式擲回例外狀況時,會呼叫 Error 方法。

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

PacketFilterPlugin 類別會在輔助方法 ModifyPacketData中處理大部分的通知。 ModifyPacketData 方法會從 PacketsData 類別取得每個新封包的 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;
}
        //...
            

當自定義動態轉譯器外掛程式收到 Packets 通知時,它會擷取 (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 專案示範先前所述的外掛程式,以及 GestureRecognizerDynamicRenderer 外掛程式。專案的使用者介面包含:

  • 表單,包含用來定義筆跡輸入區域的 GroupBox 控件。
  • 要列出並選取可用外掛程式的 CheckedListBox 控制項。
  • 一組 Button 物件,以重新排序外掛程式。

專案會定義 結構,PlugInListItem,讓管理專案中所使用的外掛程式變得更容易。 PlugInListItem 結構包含外掛程式和描述。

RealTimeStylusPluginApp 類別本身會實作 IStylusAsyncPlugin 類別。 這是必要的,因此 RealTimeStylusPluginApp 類別可以在 GestureRecognizer 外掛程式將手勢數據新增至輸出佇列時收到通知。 應用程式會註冊通知 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;
            }
        }
    }
}

注意

CustomStylusDataAdded 的實作中,有趣的是,你可以透過 GUID 使用 GestureRecognitionDataGuid 欄位來識別輸出佇列中的自定義手勢資料,或是使用 as 語句的結果來識別其類型。 此範例會針對示範目的使用這兩種識別技術。 單靠任一種方法也是有效的。

 

在表單的 Load 事件處理程式中,應用程式會建立 PacketFilterCustomDynamicRenderer 類別的實例,並將其新增至清單框。 然後,應用程式會嘗試建立 GestureRecognizer 類別的實例,如果成功,請將它新增至清單框。 如果系統上沒有手勢辨識器,就會失敗。 接下來,應用程式會具現化 DynamicRenderer 物件,並將其新增至清單框。 最後,應用程式會啟用每個外掛程式和 RealTimeStylus 物件本身。

另一件值得注意的範例是,在協助程式方法中,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 資料收集範例