Tworzenie formantu danych wejściowych atramentu

Możesz utworzyć niestandardową kontrolkę, która dynamicznie i statycznie renderuje atrament. Oznacza to, że renderowanie pisma odręcznego jako użytkownik rysuje pociągnięcie, co powoduje wyświetlenie pisma odręcznego z pióra tabletu i wyświetlenie pisma odręcznego po dodaniu go do kontrolki za pośrednictwem pióra tabletu, wklejonego ze Schowka lub załadowanego z pliku. Aby dynamicznie renderować atrament, kontrolka musi używać elementu DynamicRenderer. Aby statycznie renderować atrament, należy zastąpić metody zdarzeń rysika (, i ) w celu zbierania StylusPoint danych, tworzenia pociągnięć i dodawania ich do InkPresenter kontrolki (co renderuje atrament na kontrolce).OnStylusUpOnStylusMoveOnStylusDown

Ten temat zawiera następujące podsekcje:

Instrukcje: zbieranie danych punktów rysików i tworzenie pociągnięć pisma odkowego

Aby utworzyć kontrolkę, która zbiera pociągnięcia pisma odręcznego i zarządza nimi, wykonaj następujące czynności:

  1. Utwórz klasę z Control klasy lub jednej z klas pochodnych z Controlklasy , takiej jak 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. Dodaj element InkPresenter do klasy i ustaw Content właściwość na nową InkPresenter.

    InkPresenter ip;
    
    public InkControl()
    {
        // Add an InkPresenter for drawing.
        ip = new InkPresenter();
        this.Content = ip;
    }
    
  3. Dołącz element RootVisualDynamicRenderer do obiektu InkPresenter , wywołując metodę AttachVisuals i dodaj element DynamicRenderer do kolekcji StylusPlugIns . Dzięki temu można InkPresenter wyświetlić atrament, ponieważ dane punktu rysika są zbierane przez kontrolkę.

    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. Zastąpij metodę OnStylusDown . W tej metodzie przechwyć rysik za pomocą wywołania metody Capture. Przechwytując rysik, kontrolka będzie nadal odbierać StylusMove zdarzenia, StylusUp nawet jeśli rysik opuszcza granice kontrolki. Nie jest to ściśle obowiązkowe, ale prawie zawsze pożądane dla dobrego środowiska użytkownika. Utwórz nowy StylusPointCollection element do zbierania StylusPoint danych. Na koniec dodaj początkowy zestaw StylusPoint danych do elementu 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. Zastąpij metodę OnStylusMove i dodaj StylusPoint dane do utworzonego StylusPointCollection wcześniej obiektu.

    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. Zastąpij metodę OnStylusUp i utwórz nową StrokeStylusPointCollection z danymi. Dodaj nowy Stroke utworzony do Strokes kolekcji przechwytywania InkPresenter stylu i wydania.

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

Instrukcje: włączanie kontrolki akceptowania danych wejściowych z myszy

Jeśli dodasz poprzednią kontrolkę do aplikacji, uruchom ją i użyjesz myszy jako urządzenia wejściowego, zauważysz, że pociągnięcia nie są utrwalane. Aby utrwały pociągnięcia, gdy mysz jest używana jako urządzenie wejściowe, wykonaj następujące czynności:

  1. Zastąpij OnMouseLeftButtonDown element i utwórz nową StylusPointCollection pozycję Pobierz pozycję myszy, gdy wystąpiło zdarzenie, a następnie utwórz StylusPoint element przy użyciu danych punktów i dodaj element StylusPoint do elementu StylusPointCollection.

    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. Zastąpij metodę OnMouseMove . Uzyskaj pozycję myszy, gdy wystąpiło zdarzenie, i utwórz StylusPoint element przy użyciu danych punktów. Dodaj obiekt StylusPoint do utworzonego StylusPointCollection wcześniej obiektu.

    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. Zastąpij metodę OnMouseLeftButtonUp . Utwórz nowy Stroke element przy użyciu StylusPointCollection danych i dodaj nowy Stroke utworzony do Strokes kolekcji .InkPresenter

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

Łączenie go

Poniższy przykład to niestandardowa kontrolka, która zbiera atrament, gdy użytkownik używa myszy lub pióra.

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

Korzystanie z dodatkowych wtyczek i elementów DynamicRenderers

Podobnie jak w przypadku aplikacji InkCanvas, kontrolka niestandardowa może mieć niestandardowe StylusPlugIn i dodatkowe DynamicRenderer obiekty. Dodaj je do kolekcji StylusPlugIns . Kolejność StylusPlugIn obiektów w obiekcie StylusPlugInCollection wpływa na wygląd pisma odręcznego podczas renderowania. Załóżmy, że masz wywołanie dynamicRenderer i niestandardową DynamicRendererStylusPlugIn nazwę, translatePlugin która przesuwa atrament z pióra tabletu. Jeśli translatePlugin element jest pierwszy StylusPlugIn w elemecie StylusPlugInCollectioni dynamicRenderer jest drugim, atrament, który "przepływy" zostanie przesunięty, gdy użytkownik przenosi pióro. Jeśli dynamicRenderer jest pierwszy i translatePlugin drugi, atrament nie zostanie przesunięty, dopóki użytkownik nie zniesie pióra.

Podsumowanie

Możesz utworzyć kontrolkę, która zbiera i renderuje pisma odręcznego, przesłaniając metody zdarzeń rysika. Tworząc własną kontrolkę, wyprowadzając własne StylusPlugIn klasy i wstawiając je do StylusPlugInCollectionelementu , możesz zaimplementować praktycznie dowolne zachowanie możliwe do wymyślenia za pomocą cyfrowego pisma oddyskowego. Masz dostęp do StylusPoint danych generowanych w miarę ich generowania, co daje możliwość dostosowania Stylus danych wejściowych i renderowania ich na ekranie odpowiednio dla aplikacji. Ponieważ masz taki niski dostęp do StylusPoint danych, możesz zaimplementować kolekcję pisma odręcznego i renderować ją z optymalną wydajnością aplikacji.

Zobacz też