Bagikan melalui


Melukis dan menggambar pada kontrol (Formulir Windows .NET)

Lukisan kontrol kustom adalah salah satu dari banyak tugas rumit yang mudah dilakukan oleh Formulir Windows. Saat menulis kontrol kustom, Anda memiliki banyak opsi yang tersedia untuk menangani tampilan grafis kontrol Anda. Jika Anda menulis kontrol kustom, yaitu kontrol yang mewarisi dari Control, Anda harus menyediakan kode untuk merender representasi grafisnya.

Penting

Dokumentasi Panduan Desktop untuk .NET 7 dan .NET 6 sedang dibangun.

Jika Anda membuat kontrol komposit, itu adalah kontrol yang mewarisi dari UserControl atau salah satu kontrol Formulir Windows yang ada, Anda dapat mengambil alih representasi grafis standar dan menyediakan kode grafis Anda sendiri.

Jika Anda ingin menyediakan penyajian kustom untuk kontrol yang ada tanpa membuat kontrol baru, opsi Anda menjadi lebih terbatas. Namun, masih ada berbagai kemungkinan grafis untuk kontrol dan aplikasi Anda.

Elemen berikut terlibat dalam penyajian kontrol:

  • Fungsionalitas gambar yang disediakan oleh kelas System.Windows.Forms.Controldasar .
  • Elemen penting dari pustaka grafis GDI.
  • Geometri wilayah gambar.
  • Prosedur untuk membebaskan sumber daya grafis.

Gambar disediakan oleh kontrol

Kelas dasar Control menyediakan fungsionalitas menggambar melalui peristiwanya Paint . Kontrol menaikkan Paint peristiwa setiap kali perlu memperbarui tampilannya. Untuk informasi selengkapnya tentang peristiwa di .NET, lihat Menangani dan meningkatkan peristiwa.

Kelas data peristiwa untuk Paint peristiwa, PaintEventArgs, menyimpan data yang diperlukan untuk menggambar kontrol - handel ke objek grafis dan persegi panjang yang mewakili wilayah untuk digambar.

public class PaintEventArgs : EventArgs, IDisposable
{

    public System.Drawing.Rectangle ClipRectangle {get;}
    public System.Drawing.Graphics Graphics {get;}

    // Other properties and methods.
}
Public Class PaintEventArgs
    Inherits EventArgs
    Implements IDisposable

    Public ReadOnly Property ClipRectangle As System.Drawing.Rectangle
    Public ReadOnly Property Graphics As System.Drawing.Graphics

    ' Other properties and methods.
End Class

Graphics adalah kelas terkelola yang merangkum fungsionalitas gambar, seperti yang dijelaskan dalam diskusi GDI nanti dalam artikel ini. ClipRectangle adalah instans Rectangle struktur dan menentukan area yang tersedia di mana kontrol dapat menggambar. Pengembang kontrol dapat menghitung ClipRectangle penggunaan ClipRectangle properti kontrol, seperti yang dijelaskan dalam diskusi geometri nanti di artikel ini.

OnPaint

Kontrol harus menyediakan logika penyajian dengan mengesampingkan OnPaint metode yang diwarisinya dari Control. OnPaint mendapatkan akses ke objek grafis dan persegi panjang untuk menggambar melalui Graphics dan ClipRectangle properti instans yang PaintEventArgs diteruskan ke objek tersebut.

Kode berikut menggunakan System.Drawing namespace layanan:

protected override void OnPaint(PaintEventArgs e)
{
    // Call the OnPaint method of the base class.
    base.OnPaint(e);

    // Declare and instantiate a new pen that will be disposed of at the end of the method.
    using var myPen = new Pen(Color.Aqua);

    // Create a rectangle that represents the size of the control, minus 1 pixel.
    var area = new Rectangle(new Point(0, 0), new Size(this.Size.Width - 1, this.Size.Height - 1));

    // Draw an aqua rectangle in the rectangle represented by the control.
    e.Graphics.DrawRectangle(myPen, area);
}
Protected Overrides Sub OnPaint(e As PaintEventArgs)
    MyBase.OnPaint(e)

    ' Declare and instantiate a drawing pen.
    Using myPen = New System.Drawing.Pen(Color.Aqua)

        ' Create a rectangle that represents the size of the control, minus 1 pixel.
        Dim area = New Rectangle(New Point(0, 0), New Size(Me.Size.Width - 1, Me.Size.Height - 1))

        ' Draw an aqua rectangle in the rectangle represented by the control.
        e.Graphics.DrawRectangle(myPen, area)

    End Using
End Sub

Metode OnPaint kelas dasar Control tidak menerapkan fungsionalitas gambar apa pun tetapi hanya memanggil delegasi peristiwa yang terdaftar di acara tersebut Paint . Ketika Anda mengambil OnPaintalih , Anda biasanya harus memanggil OnPaint metode kelas dasar sehingga delegasi terdaftar menerima peristiwa tersebut Paint . Namun, kontrol yang melukis seluruh permukaannya tidak boleh memanggil kelas dasar , karena OnPaintini memperkenalkan berkedip.

Catatan

Jangan memanggil OnPaint langsung dari kontrol Anda; sebagai gantinya Invalidate , panggil metode (diwarisi dari Control) atau beberapa metode lain yang memanggil Invalidate. Metode pada gilirannya Invalidate memanggil OnPaint. Metode Invalidate ini kelebihan beban, dan, tergantung pada argumen yang disediakan untuk Invalidatee, menggambar ulang beberapa atau semua area layarnya.

Kode dalam OnPaint metode kontrol Anda akan dijalankan ketika kontrol pertama kali digambar, dan setiap kali di-refresh. Untuk memastikan bahwa kontrol Anda digambar ulang setiap kali diubah ukurannya, tambahkan baris berikut ke konstruktor kontrol Anda:

SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.ResizeRedraw, True)

OnPaintBackground

Kelas dasar Control mendefinisikan metode lain yang berguna untuk menggambar, OnPaintBackground metode .

protected virtual void OnPaintBackground(PaintEventArgs e);
Protected Overridable Sub OnPaintBackground(e As PaintEventArgs)

OnPaintBackground melukis latar belakang (dan dengan cara itu, bentuk) jendela dan dijamin cepat, sementara OnPaint melukis detailnya dan mungkin lebih lambat karena permintaan cat individu digabungkan menjadi satu Paint peristiwa yang mencakup semua area yang harus digambar ulang. Anda mungkin ingin memanggil OnPaintBackground jika, misalnya, Anda ingin menggambar latar belakang berwarna gradien untuk kontrol Anda.

Meskipun OnPaintBackground memiliki nomenklatur seperti peristiwa dan mengambil argumen yang sama dengan OnPaint metode , OnPaintBackground bukan metode peristiwa yang benar. Tidak ada PaintBackground peristiwa dan OnPaintBackground tidak memanggil delegasi peristiwa. Saat mengambil alih OnPaintBackground metode , kelas turunan tidak diperlukan untuk memanggil OnPaintBackground metode kelas dasarnya.

Dasar-Dasar GDI+

Kelas ini Graphics menyediakan metode untuk menggambar berbagai bentuk seperti lingkaran, segitiga, busur, dan elipsis, dan metode untuk menampilkan teks. Namespace System.Drawing berisi namespace layanan dan kelas yang merangkum elemen grafis seperti bentuk (lingkaran, persegi panjang, busur, dan lainnya), warna, font, kuas, dan sebagainya.

Geometri Wilayah Gambar

Properti ClientRectangle kontrol menentukan wilayah persegi panjang yang tersedia untuk kontrol pada layar pengguna, sementara ClipRectangle properti PaintEventArgs menentukan area yang dicat. Kontrol mungkin hanya perlu melukis sebagian area yang tersedia, seperti halnya ketika bagian kecil tampilan kontrol berubah. Dalam situasi tersebut, pengembang kontrol harus menghitung persegi panjang aktual untuk menggambar dan meneruskan itu ke Invalidate. Versi Invalidate kelebihan beban yang mengambil Rectangle atau Region sebagai argumen menggunakan argumen tersebut ClipRectangle untuk menghasilkan properti .PaintEventArgs

Membebaskan Sumber Daya Grafis

Objek grafis mahal karena menggunakan sumber daya sistem. Objek tersebut termasuk instans System.Drawing.Graphics kelas dan instans System.Drawing.Brush, , System.Drawing.Pendan kelas grafis lainnya. Penting bagi Anda untuk membuat sumber daya grafis hanya ketika Anda membutuhkannya dan merilisnya segera setelah Anda selesai menggunakannya. Jika Anda membuat instans IDisposable jenis yang mengimplementasikan antarmuka, panggil metodenya Dispose ketika Anda selesai dengannya untuk membebaskan sumber daya.

Baca juga