建立筆墨輸入控制項

您可以建立動態和靜態呈現筆跡的自訂控制項。 也就是說,將筆跡轉譯為使用者繪製筆劃,導致筆跡從平板電腦畫筆「流動」,並在它新增至控制項之後顯示筆跡,無論是透過平板電腦畫筆貼上剪貼簿,還是從檔案載入。 若要動態轉譯筆跡,您的控制項必須使用 DynamicRenderer 。 若要以靜態方式呈現筆跡,您必須覆寫手寫筆事件方法 ( OnStylusDown 、 和 OnStylusUp ) 來收集資料 StylusPointOnStylusMove 建立筆劃,並將其新增至 InkPresenter (轉譯控制項上的筆跡)。

本主題包含下列子章節:

如何:收集手寫筆點資料及建立筆跡筆劃

若要建立可收集和管理筆跡筆劃的控制項,請執行下列動作:

  1. Control 衍生類別,或衍生自 Control 的其中一個類別,例如 Label

    using System;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Input.StylusPlugIns;
    using System.Windows.Controls;
    using System.Windows;
    
    class InkControl : Label
    {
    
    }
    
  2. InkPresenter將 新增至 類別,並將 屬性設定 Content 為新的 InkPresenter

    InkPresenter ip;
    
    public InkControl()
    {
        // Add an InkPresenter for drawing.
        ip = new InkPresenter();
        this.Content = ip;
    }
    
  3. RootVisualDynamicRenderer 呼叫 AttachVisuals 方法,將 的 附加至 InkPresenter ,並將 加入 DynamicRendererStylusPlugIns 集合。 這可讓 顯示 InkPresenter 筆跡,因為手寫筆點資料是由您的控制項所收集。

    public InkControl()
    {
    
        // Add a dynamic renderer that
        // draws ink as it "flows" from the stylus.
        dr = new DynamicRenderer();
        ip.AttachVisuals(dr.RootVisual, dr.DrawingAttributes);
        this.StylusPlugIns.Add(dr);
    }
    
  4. 覆寫 OnStylusDown 方法。 在此方法中,使用 呼叫 Capture 來擷取手寫筆。 藉由擷取手寫筆,即使手寫筆離開控制項的界限,您的控制項仍會繼續接收 StylusMoveStylusUp 事件。 這不是絕對強制性的,但幾乎總是想要良好的使用者體驗。 建立新的 StylusPointCollection 來收集資料 StylusPoint 。 最後,將初始資料集 StylusPoint 新增至 StylusPointCollection

    protected override void OnStylusDown(StylusDownEventArgs e)
    {
        // Capture the stylus so all stylus input is routed to this control.
        Stylus.Capture(this);
    
        // Allocate memory for the StylusPointsCollection and
        // add the StylusPoints that have come in so far.
        stylusPoints = new StylusPointCollection();
        StylusPointCollection eventPoints =
            e.GetStylusPoints(this, stylusPoints.Description);
    
        stylusPoints.Add(eventPoints);
    }
    
  5. 覆寫 方法, OnStylusMove 並將資料新增 StylusPointStylusPointCollection 您稍早建立的物件。

    protected override void OnStylusMove(StylusEventArgs e)
    {
        if (stylusPoints == null)
        {
            return;
        }
    
        // Add the StylusPoints that have come in since the
        // last call to OnStylusMove.
        StylusPointCollection newStylusPoints =
            e.GetStylusPoints(this, stylusPoints.Description);
        stylusPoints.Add(newStylusPoints);
    }
    
  6. 覆寫 方法, OnStylusUp 並使用資料建立新的 StrokeStylusPointCollection 。 將您建立的新 Stroke 新增至 Strokes 和 發行手寫筆擷取的 InkPresenter 集合。

    protected override void OnStylusUp(StylusEventArgs e)
    {
        if (stylusPoints == null)
        {
            return;
        }
    
        // Add the StylusPoints that have come in since the
        // last call to OnStylusMove.
        StylusPointCollection newStylusPoints =
            e.GetStylusPoints(this, stylusPoints.Description);
        stylusPoints.Add(newStylusPoints);
    
        // Create a new stroke from all the StylusPoints since OnStylusDown.
        Stroke stroke = new Stroke(stylusPoints);
    
        // Add the new stroke to the Strokes collection of the InkPresenter.
        ip.Strokes.Add(stroke);
    
        // Clear the StylusPointsCollection.
        stylusPoints = null;
    
        // Release stylus capture.
        Stylus.Capture(null);
    }
    

如何:讓您的控制項接受滑鼠的輸入

如果您將上述控制項新增至應用程式、執行它,並使用滑鼠做為輸入裝置,您會發現筆劃不會保存。 若要在使用滑鼠作為輸入裝置時保存筆劃,請執行下列動作:

  1. 覆寫 並 OnMouseLeftButtonDown 建立新的 StylusPointCollection 取得事件發生時滑鼠的位置,並使用點資料建立 StylusPoint ,並將 新增 StylusPointStylusPointCollection

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
    
        base.OnMouseLeftButtonDown(e);
    
        // If a stylus generated this event, return.
        if (e.StylusDevice != null)
        {
            return;
        }
    
        // Start collecting the points.
        stylusPoints = new StylusPointCollection();
        Point pt = e.GetPosition(this);
        stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
    }
    
  2. 覆寫 OnMouseMove 方法。 取得事件發生時滑鼠的位置,並使用點資料建立 StylusPointStylusPoint將 新增至 StylusPointCollection 您稍早建立的物件。

    protected override void OnMouseMove(MouseEventArgs e)
    {
    
        base.OnMouseMove(e);
    
        // If a stylus generated this event, return.
        if (e.StylusDevice != null)
        {
            return;
        }
    
        // Don't collect points unless the left mouse button
        // is down.
        if (e.LeftButton == MouseButtonState.Released ||
            stylusPoints == null)
        {
            return;
        }
    
        Point pt = e.GetPosition(this);
        stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
    }
    
  3. 覆寫 OnMouseLeftButtonUp 方法。 使用資料建立新的 StrokeStylusPointCollection ,並將您建立的新 新增 StrokeStrokesInkPresenter 集合。

    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
    {
    
        base.OnMouseLeftButtonUp(e);
    
        // If a stylus generated this event, return.
        if (e.StylusDevice != null)
        {
            return;
        }
    
        if (stylusPoints == null)
        {
            return;
        }
    
        Point pt = e.GetPosition(this);
        stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
    
        // Create a stroke and add it to the InkPresenter.
        Stroke stroke = new Stroke(stylusPoints);
        stroke.DrawingAttributes = dr.DrawingAttributes;
        ip.Strokes.Add(stroke);
    
        stylusPoints = null;
    }
    

將它放在一起

下列範例是自訂控制項,當使用者使用滑鼠或手寫筆時,會收集筆跡。

using System;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Controls;
using System.Windows;
// A control for managing ink input
class InkControl : Label
{
    InkPresenter ip;
    DynamicRenderer dr;

    // The StylusPointsCollection that gathers points
    // before Stroke from is created.
    StylusPointCollection stylusPoints = null;

    public InkControl()
    {
        // Add an InkPresenter for drawing.
        ip = new InkPresenter();
        this.Content = ip;

        // Add a dynamic renderer that
        // draws ink as it "flows" from the stylus.
        dr = new DynamicRenderer();
        ip.AttachVisuals(dr.RootVisual, dr.DrawingAttributes);
        this.StylusPlugIns.Add(dr);
    }

    static InkControl()
    {
        // Allow ink to be drawn only within the bounds of the control.
        Type owner = typeof(InkControl);
        ClipToBoundsProperty.OverrideMetadata(owner,
            new FrameworkPropertyMetadata(true));
    }

    protected override void OnStylusDown(StylusDownEventArgs e)
    {
        // Capture the stylus so all stylus input is routed to this control.
        Stylus.Capture(this);

        // Allocate memory for the StylusPointsCollection and
        // add the StylusPoints that have come in so far.
        stylusPoints = new StylusPointCollection();
        StylusPointCollection eventPoints =
            e.GetStylusPoints(this, stylusPoints.Description);

        stylusPoints.Add(eventPoints);
    }

    protected override void OnStylusMove(StylusEventArgs e)
    {
        if (stylusPoints == null)
        {
            return;
        }

        // Add the StylusPoints that have come in since the
        // last call to OnStylusMove.
        StylusPointCollection newStylusPoints =
            e.GetStylusPoints(this, stylusPoints.Description);
        stylusPoints.Add(newStylusPoints);
    }

    protected override void OnStylusUp(StylusEventArgs e)
    {
        if (stylusPoints == null)
        {
            return;
        }

        // Add the StylusPoints that have come in since the
        // last call to OnStylusMove.
        StylusPointCollection newStylusPoints =
            e.GetStylusPoints(this, stylusPoints.Description);
        stylusPoints.Add(newStylusPoints);

        // Create a new stroke from all the StylusPoints since OnStylusDown.
        Stroke stroke = new Stroke(stylusPoints);

        // Add the new stroke to the Strokes collection of the InkPresenter.
        ip.Strokes.Add(stroke);

        // Clear the StylusPointsCollection.
        stylusPoints = null;

        // Release stylus capture.
        Stylus.Capture(null);
    }

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {

        base.OnMouseLeftButtonDown(e);

        // If a stylus generated this event, return.
        if (e.StylusDevice != null)
        {
            return;
        }

        // Start collecting the points.
        stylusPoints = new StylusPointCollection();
        Point pt = e.GetPosition(this);
        stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {

        base.OnMouseMove(e);

        // If a stylus generated this event, return.
        if (e.StylusDevice != null)
        {
            return;
        }

        // Don't collect points unless the left mouse button
        // is down.
        if (e.LeftButton == MouseButtonState.Released ||
            stylusPoints == null)
        {
            return;
        }

        Point pt = e.GetPosition(this);
        stylusPoints.Add(new StylusPoint(pt.X, pt.Y));
    }

    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
    {

        base.OnMouseLeftButtonUp(e);

        // If a stylus generated this event, return.
        if (e.StylusDevice != null)
        {
            return;
        }

        if (stylusPoints == null)
        {
            return;
        }

        Point pt = e.GetPosition(this);
        stylusPoints.Add(new StylusPoint(pt.X, pt.Y));

        // Create a stroke and add it to the InkPresenter.
        Stroke stroke = new Stroke(stylusPoints);
        stroke.DrawingAttributes = dr.DrawingAttributes;
        ip.Strokes.Add(stroke);

        stylusPoints = null;
    }
}

使用其他外掛程式和 DynamicRenderers

如同 InkCanvas,您的自訂控制項可以有自訂 StylusPlugIn 和其他 DynamicRenderer 物件。 將這些新增至 StylusPlugIns 集合。 中的 StylusPlugInCollection 物件順序 StylusPlugIn 會影響轉譯時筆跡的外觀。 假設您有一個 DynamicRenderer 呼叫 dynamicRenderer ,而名為 的自訂 StylusPlugIntranslatePlugin 從平板電腦畫筆位移筆墨。 如果 translatePlugin 是 中的 StylusPlugInCollection 第一個 StylusPlugIn ,而 dynamicRenderer 是第二個,當使用者移動畫筆時,「流動」的筆跡將會位移。 如果 dynamicRenderer 為第一個,且 translatePlugin 為第二個,則直到使用者解除手寫筆之前,筆跡才會位移。

推論

您可以藉由覆寫手寫筆事件方法,建立可收集和轉譯筆跡的控制項。 藉由建立您自己的控制項、衍生您自己的 StylusPlugIn 類別,並將其插入 至 StylusPlugInCollection ,您幾乎可以實作任何可想像的數位筆跡行為。 您可以在產生資料時存取 StylusPoint 資料,讓您有機會自訂 Stylus 輸入,並視您的應用程式在畫面上轉譯。 因為您對資料有如此低階的 StylusPoint 存取權,所以您可以實作筆跡集合,並以應用程式的最佳效能轉譯它。

另請參閱