Bagikan melalui


Membuat Kontrol Masukan 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, OnStylusMove, dan OnStylusUp) untuk mengumpulkan data StylusPoint, membuat goresan, dan menambahkannya ke InkPresenter (yang merender tinta pada 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. Turunkan kelas dari Control atau dari salah satu kelas yang diturunkan 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. Tambahkan InkPresenter ke kelas dan atur properti Content menjadi InkPresenteryang baru.

    InkPresenter ip;
    
    public InkControl()
    {
        // Add an InkPresenter for drawing.
        ip = new InkPresenter();
        this.Content = ip;
    }
    
  3. Lampirkan RootVisualDynamicRenderer ke InkPresenter dengan memanggil metode AttachVisuals, dan tambahkan DynamicRenderer ke koleksi StylusPlugIns. Ini memungkinkan InkPresenter 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. Timpa metode OnStylusDown. Dalam cara ini, tangkap stylus dengan panggilan ke Capture. Dengan menangkap stylus, kontrol Anda masih akan menerima peristiwa StylusMove dan StylusUp meskipun stylus meninggalkan batas kontrol. Ini tidak benar-benar wajib, tetapi hampir selalu diinginkan untuk pengalaman pengguna yang baik. Buat StylusPointCollection baru untuk mengumpulkan data StylusPoint. Terakhir, tambahkan set awal data StylusPoint 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 metode OnStylusMove dan tambahkan data StylusPoint ke objek StylusPointCollection 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 metode OnStylusUp dan buat Stroke baru dengan data StylusPointCollection. Tambahkan Stroke baru yang Anda buat ke koleksi Strokes dari InkPresenter dan lepaskan pengambilan stylus.

    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 menggambar garis tetap ketika mouse digunakan sebagai perangkat input, lakukan hal berikut:

  1. Ambil alih OnMouseLeftButtonDown dan buat StylusPointCollection baru 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. Timpa metode OnMouseMove. Dapatkan posisi mouse saat peristiwa terjadi dan buat StylusPoint menggunakan data titik. Tambahkan StylusPoint ke objek StylusPointCollection 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. Timpa metode OnMouseLeftButtonUp. Buat Stroke baru dengan data StylusPointCollection, dan tambahkan Stroke baru yang Anda buat ke dalam koleksi Strokes dari 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;
    }
    

Menyusunnya menjadi satu

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 Plugin Tambahan dan Renderer Dinamis

Seperti InkCanvas, kontrol kustom Anda dapat memiliki objek kustom StylusPlugIn dan tambahan DynamicRenderer. Tambahkan ini ke koleksi StylusPlugIns. Urutan objek StylusPlugIn dalam StylusPlugInCollection memengaruhi tampilan tinta saat dirender. Misalkan Anda memiliki DynamicRenderer yang disebut dynamicRenderer dan StylusPlugIn kustom yang disebut translatePlugin yang mengimbangi tinta dari pena tablet. Jika translatePlugin adalah StylusPlugIn pertama di StylusPlugInCollection, dan dynamicRenderer adalah yang kedua, tinta yang "mengalir" akan diimbangi saat pengguna memindahkan pena. Jika dynamicRenderer pertama, dan translatePlugin adalah yang 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, mendapatkan kelas StylusPlugIn Anda sendiri, dan memasukkannya ke dalam StylusPlugInCollection, Anda dapat menerapkan hampir semua perilaku yang dapat dibayangkan dengan tinta digital. Anda memiliki akses ke data StylusPoint saat dihasilkan, memberi Anda kesempatan untuk menyesuaikan input Stylus dan merendernya di layar sesuai dengan aplikasi Anda. Karena Anda memiliki akses tingkat rendah ke data StylusPoint, Anda dapat menerapkan pengumpulan tinta dan merendernya dengan performa optimal untuk aplikasi Anda.

Lihat juga