Bagikan melalui


Membuat Kontrol Input Tinta

Anda dapat membuat kontrol kustom yang merender tinta secara dinamis dan statis. Artinya, merender tinta saat pengguna menarik goresan, menyebabkan tinta tampak "mengalir" dari pena tablet, dan menampilkan tinta setelah ditambahkan ke kontrol, baik melalui pena tablet, ditempelkan dari Clipboard, atau dimuat dari file. Untuk merender tinta secara dinamis, kontrol Anda harus menggunakan DynamicRenderer. Untuk merender tinta secara statis, Anda harus mengambil alih metode peristiwa stylus (OnStylusDown, , dan OnStylusUp) untuk mengumpulkan StylusPoint data, membuat goresan, dan menambahkannya ke InkPresenter (yang merender tinta OnStylusMovepada kontrol).

Topik ini berisi sub bagian berikut:

Cara: Mengumpulkan Data Titik Stylus dan Membuat Goresan Tinta

Untuk membuat kontrol yang mengumpulkan dan mengelola goresan tinta, lakukan hal berikut:

  1. Mendapatkan kelas dari Control atau salah satu kelas yang berasal dari Control, seperti 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 Tambahkan ke kelas dan atur Content properti ke yang baruInkPresenter.

    InkPresenter ip;
    
    public InkControl()
    {
        // Add an InkPresenter for drawing.
        ip = new InkPresenter();
        this.Content = ip;
    }
    
  3. Lampirkan RootVisualDynamicRenderer ke ke InkPresenter dengan memanggil AttachVisuals metode , dan tambahkan ke DynamicRendererStylusPlugIns koleksi . Ini memungkinkan InkPresenter untuk menampilkan tinta saat data titik stylus dikumpulkan oleh kontrol Anda.

    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. Ambil alih metode OnStylusDown. Dalam metode ini, ambil stylus dengan panggilan ke Capture. Dengan menangkap stylus, kontrol Anda akan terus menerima StylusMove dan StylusUp peristiwa bahkan jika stylus meninggalkan batas kontrol. Ini tidak benar-benar wajib, tetapi hampir selalu diinginkan untuk pengalaman pengguna yang baik. Buat baru StylusPointCollection untuk mengumpulkan StylusPoint data. Terakhir, tambahkan kumpulan StylusPoint data awal ke 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. Ambil alih OnStylusMove metode dan tambahkan StylusPoint data ke StylusPointCollection objek yang Anda buat sebelumnya.

    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. Ambil alih OnStylusUp metode dan buat yang baru Stroke dengan StylusPointCollection data. Tambahkan yang baru Stroke Anda buat ke Strokes koleksi InkPresenter pengambilan stylus dan rilis.

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

Cara: Mengaktifkan Kontrol Anda untuk Menerima Input dari Mouse

Jika Anda menambahkan kontrol sebelumnya ke aplikasi Anda, jalankan, dan gunakan mouse sebagai perangkat input, Anda akan melihat bahwa goresan tidak bertahan. Untuk mempertahankan goresan ketika mouse digunakan sebagai perangkat input, lakukan hal berikut:

  1. Ambil alih OnMouseLeftButtonDown dan buat baru StylusPointCollection Dapatkan posisi mouse saat peristiwa terjadi dan buat StylusPoint menggunakan data titik dan tambahkan StylusPoint ke 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. Ambil alih metode OnMouseMove. Dapatkan posisi mouse saat peristiwa terjadi dan buat StylusPoint menggunakan data titik. StylusPoint Tambahkan ke StylusPointCollection objek yang Anda buat sebelumnya.

    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. Ambil alih metode OnMouseLeftButtonUp. Buat baru Stroke dengan StylusPointCollection data, dan tambahkan yang baru Stroke yang Anda buat ke Strokes koleksi 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;
    }
    

Menempatkannya bersama-sama

Contoh berikut adalah kontrol kustom yang mengumpulkan tinta saat pengguna menggunakan mouse atau pena.

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

Menggunakan Plug-in Tambahan dan DynamicRenderers

Seperti InkCanvas, kontrol kustom Anda dapat memiliki objek kustom StylusPlugIn dan tambahan DynamicRenderer . Tambahkan ini ke StylusPlugIns koleksi. Urutan StylusPlugIn objek dalam StylusPlugInCollection mempengaruhi penampilan tinta ketika dirender. Misalkan Anda memiliki DynamicRenderer panggilan dynamicRenderer dan kustom StylusPlugIn yang disebut translatePlugin yang mengimbangi tinta dari pena tablet. Jika translatePlugin adalah yang pertama StylusPlugIn di StylusPlugInCollection, dan dynamicRenderer merupakan yang kedua, tinta yang "mengalir" akan diimbangi saat pengguna memindahkan pena. Jika dynamicRenderer pertama, dan translatePlugin kedua, tinta tidak akan diimbangi sampai pengguna mengangkat pena.

Kesimpulan

Anda dapat membuat kontrol yang mengumpulkan dan merender tinta dengan mengesampingkan metode peristiwa stylus. Dengan membuat kontrol Anda sendiri, mengambil kelas Anda sendiri StylusPlugIn , dan memasukkannya ke dalam StylusPlugInCollection, Anda dapat menerapkan hampir semua perilaku yang dapat dibayangkan dengan tinta digital. Anda memiliki akses ke StylusPoint data seperti yang dihasilkan, memberi Anda kesempatan untuk menyesuaikan Stylus input dan merendernya di layar yang sesuai untuk aplikasi Anda. Karena Anda memiliki akses tingkat rendah seperti itu StylusPoint ke data, Anda dapat menerapkan pengumpulan tinta dan merendernya dengan performa optimal untuk aplikasi Anda.

Baca juga