Kontrol Subkelas
Jika kontrol melakukan hampir semua yang Anda inginkan, tetapi Anda memerlukan beberapa fitur lagi, Anda dapat mengubah atau menambahkan fitur ke kontrol asli dengan mensubkelasnya. Subkelas dapat memiliki semua fitur kelas yang ada serta fitur tambahan apa pun yang ingin Anda berikan.
Dokumen ini membahas bagaimana subkelas dibuat dan menyertakan topik berikut.
Kontrol Subkelas Sebelum ComCtl32.dll versi 6
Anda dapat menempatkan kontrol di subkelas dan menyimpan data pengguna dalam kontrol. Anda melakukan ini saat menggunakan versi ComCtl32.dll sebelum versi 6. Ada beberapa kelemahan dalam membuat subkelas dengan versi ComCtl32.dll sebelumnya.
Untuk membuat kontrol baru, yang terbaik adalah memulai dengan salah satu kontrol umum Windows dan memperluasnya agar sesuai dengan kebutuhan tertentu. Untuk memperluas kontrol, buat kontrol dan ganti prosedur jendela yang ada dengan yang baru. Prosedur baru mencegat pesan kontrol dan bertindak atasnya atau meneruskannya ke prosedur asli untuk pemrosesan default. Gunakan fungsi SetWindowLong atau SetWindowLongPtr untuk menggantikan WNDPROC kontrol. Sampel kode berikut menunjukkan cara mengganti WNDPROC.
OldWndProc = (WNDPROC)SetWindowLongPtr (hButton,
GWLP_WNDPROC, (LONG_PTR)NewWndProc);
Menyimpan Data Pengguna
Anda mungkin ingin menyimpan data pengguna dengan jendela individual. Data ini dapat digunakan oleh prosedur jendela baru untuk menentukan cara menggambar kontrol atau tempat mengirim pesan tertentu. Misalnya, Anda dapat menggunakan data untuk menyimpan penunjuk kelas C++ ke kelas yang mewakili kontrol. Sampel kode berikut menunjukkan cara menggunakan SetProp untuk menyimpan data dengan jendela.
SetProp (hwnd, TEXT("MyData"), (HANDLE)pMyData);
Kerugian dari Pendekatan Subkelas Lama
Daftar berikut menunjukkan beberapa kerugian menggunakan pendekatan yang dijelaskan sebelumnya untuk subkelas kontrol.
- Prosedur jendela hanya dapat diganti sekali.
- Sulit untuk menghapus subkelas setelah dibuat.
- Mengaitkan data privat dengan jendela tidak efisien.
- Untuk memanggil prosedur berikutnya dalam rantai subkelas, Anda tidak dapat mentransmisikan prosedur jendela lama dan memanggilnya, Anda harus memanggilnya dengan menggunakan fungsi CallWindowProc.
Kontrol Subkelas Menggunakan ComCtl32.dll versi 6
Catatan
ComCtl32.dll versi 6 hanya Unicode. Kontrol umum yang didukung oleh ComCtl32.dll versi 6 tidak boleh disubkelas (atau diawasi) dengan prosedur jendela ANSI.
ComCtl32.dll versi 6 berisi empat fungsi yang membuat pembuatan subkelas lebih mudah dan menghilangkan kerugian yang sebelumnya dibahas. Fungsi baru merangkum manajemen yang terlibat dengan beberapa set data referensi, oleh karena itu pengembang dapat fokus pada fitur pemrograman dan bukan mengelola subkelas. Fungsi subkelas adalah:
SetWindowSubclass
Fungsi ini digunakan untuk awalnya mensubkelas jendela. Setiap subkelas diidentifikasi secara unik oleh alamat pfnSubclass dan uIdSubclass-nya. Keduanya adalah parameter fungsi SetWindowSubclass. Beberapa subkelas dapat berbagi prosedur subkelas yang sama dan ID dapat mengidentifikasi setiap panggilan. Untuk mengubah data referensi, Anda dapat melakukan panggilan berikutnya ke SetWindowSubclass. Keuntungan pentingnya adalah bahwa setiap instans subkelas memiliki data referensinya sendiri.
Deklarasi prosedur subkelas sedikit berbeda dari prosedur jendela biasa karena memiliki dua bagian data tambahan: ID subkelas dan data referensi. Dua parameter terakhir dari deklarasi fungsi berikut menunjukkan ini.
LRESULT CALLBACK MyWndProc (HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass,
DWORD_PTR dwRefData);
Setiap kali pesan diterima oleh prosedur jendela baru, ID subkelas dan data referensi disertakan.
Catatan
Semua string yang diteruskan ke prosedur adalah string Unicode meskipun Unicode tidak ditentukan sebagai definisi praprosedur.
Contoh berikut menunjukkan implementasi kerangka prosedur jendela untuk kontrol subkelas.
LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_PAINT:
.
.
.
return TRUE;
// Other cases...
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
Prosedur jendela dapat dilampirkan ke kontrol di handler WM_INITDIALOG prosedur dialog, seperti yang ditunjukkan dalam contoh berikut.
case WM_INITDIALOG:
{
HWND button = GetDlgItem(hDlg, IDC_OWNERDRAWBUTTON);
SetWindowSubclass(button, OwnerDrawButtonProc, 0, 0);
return TRUE;
}
GetWindowSubclass
Fungsi ini mengambil informasi tentang subkelas. Misalnya, Anda dapat menggunakan GetWindowSubclass untuk mengakses data referensi.
RemoveWindowSubclass
Fungsi ini menghapus subkelas. RemoveWindowSubclass dalam kombinasi dengan SetWindowSubclass memungkinkan Anda untuk menambahkan dan menghapus subkelas secara dinamis.
DefSubclassProc
Fungsi DefSubclassProc memanggil handler berikutnya dalam rantai subkelas. Fungsi ini juga mengambil ID dan data referensi yang tepat dan meneruskan informasi ke prosedur jendela berikutnya.