Membuat komponen komponen Delphi secara mudah dan cepat dengan pengenalan Object Oriented Programming
Daftar Isi Daftar Isi .................................................. ........................................................ ........................................................................... ................... i Sekapur Sirih...................................................................................................................... 1 1
2
3
4
Mengapa Membuat Membuat Komponen Komponen Sendiri? Sendiri? .................................................. ................ 2 1.1
Apa itu komponen?.......................................................................................................2
1.2
Mengapa Kita Membuat Komponen?.........................................................................3
1.3
Apa saja yang perlu diketahui untuk membuat komponen?....................................5
Object Oriented Programming Programming (OOP) ...................................................................... 7 2.1
Apa itu OOP? ................................. ................ ................................... .................. ................................... ................. .................. ..........................7 ................. .........7
2.2
Apa perbedaan OOP dengan Procedural Procedural Programming .................. ................... .....8
Konsep-konsep Konsep-konsep Dasar OOP ...................................................... ..................................................................................... ............................... 10 3.1
Kelas ................................. ................ ................................... .................. ................................... ................. .................. ................................... ................. .................. ....10
3.2
Enkapsulasi..................................................................................................................11
3.3
Pewarisan.....................................................................................................................12
3.4
Polimorfisme................................................................................................................13
Disain dan Implementasi Pemrograman Berorientasi Object dengan Delphi...... 14 4.1 4.1.1 4.1.2 4.1.3
4.2 4.2.1 4.2.2 4.2.3
5
5.1.1 5.1.2
Studi Kasus – Menganalisis, Mendisain, dan Mengimplementasikan Kelas......... 16 Analisis Analisis ........................... ......................................... ........................... ........................... ............................ ............................ ........................... ........................... .....................16 .......16 Disain.................. Disain................................ ............................ ........................... ........................... ............................ ............................ ........................... ............................ ...................17 ....17 Implemen Implementasi tasi ........................... ......................................... ............................ ............................ ............................ ............................ ............................ ........................20 ..........20
Langkah-langkah Membuat Komponen...................................................................34 Menentukan Menentukan Superclass Superclass dari Komponen Komponen ........................... ......................................... ............................ ............................ ........................34 ..........34 Membuat Komponen Sederhana Langkah demi Langkah.....................................................35
Contoh Komponen-Ko Komponen-Komponen........ mponen............................................................... ........................................................................ ................. 48 6.1 6.1.1 6.1.2
7
Fase Analisis............... Analisis............................. ............................ ............................ ........................... ........................... ............................ ............................ ........................14 ..........14 Fase Disain Disain .......................... ....................................... ........................... ............................ ............................ ........................... ........................... ............................ ................14 ..14 Fase Implement Implementasi asi .......................... ........................................ ............................ ............................ ........................... ........................... ............................ ..................15 ....15
Membuat Komponen Komponen Sederhana.... Sederhana........................................................ ......................................................................... ..................... 33 5.1
6
Bermula dari Masalah, Diakhiri dengan Solusi Program.......................................14
Komponen yang Terhubung ke Basisdata................................................................48 TWWDBNaviga TWWDBNavigator............. tor........................... ............................ ............................ ........................... ........................... ............................ ........................... ................48 ...48 TWWDBDateTimePicker...................................................... Error! Bookmark not defined.
Referensi................................................................................................................... 67
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman i
Sekapur Sirih Saya tertarik untuk membuat buku tentang cara membuat komponen dengan Delphi karena kurangnya buku dalam bahasa Indonesia yang membahas pemrograman berorientasi objek dengan Delphi yang dilengkapi pembuatan komponen. Buku ini ditujukan bagi mereka yang sudah mengenal Delphi secara singkat dan ingin mengenal bagaimana membuat komponen dengan Delphi. Diasumsikan pembaca sudah mengenal bahasa Pascal atau operator, pembuatan fungsi dan prosedur di Delphi. Komponen di Delphi sangat powerful, bahkan dapat dikatakan kekuatan utama pemrograman dalam Delphi adalah pada pemanfaatan komponen, reusability yang sangat tinggi, dan sangat mendukung dalam RAD (Rapid Application Development). Anda akan menemukan bahwa dalam dunia nyata, delivery project tepat pada waktunya sangat ditentukan oleh lamanya pengembangan aplikasi. Ketersediaan komponen dalam framework
yang
dapat
digunakan
berulang
kali
akan
memperpendek
waktu
pengembangan aplikasi. Dengan kata lain, memanfaatkan secara maksimal komponen di Delphi, akan membuat anda benar-benar produktif. Kata kuncinya adalah reusability. Delphi yang saya gunakan dalam buku ini adalah versi 6. Meskipun demikian, konsep pembuatan komponennya dapat digunakan pada versi berikutnya. Ilmu saya dalam menggunakan Borland Delphi masih sangat dangkal. Semakin saya mencoba menyelami, semakin terasa bahwa ilmu yang saya pelajari masih sangat sedikit. Hal ini disebabkan karena selama ini hanya mengerjakan proyek secara komersial dengan menggunakan framework yang tidak terlalu jauh berubah. Selama ini hanya berkisar pada aplikasi client server yang terkoneksi ke database. Kesibukan dalam dunia pekerjaan terkadang melenakan kita untuk mempelajari sisi yang lebih dalam dari suatu bahasa pemrograman. Buku ini ditulis lebih dari tiga tahun lamanya. Komponen yang ada dalam buku ini ditulis oleh pemula untuk pemula. Jika anda adalah programer Delphi yang sangat berpengalaman, terutama dalam pembuatan komponen, anda mungkin akan menemui bahwa komponen yang ditulis dalam buku ini masih sangat mungkin untuk dioptimalkan dari segi algoritma maupun efisiensi kerja program. Kritik dan saran Anda saya nantikan, di
[email protected] atau di blog http://wishknew.modblog.com . Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 1
1 Mengapa Membuat Komponen Sendiri? 1.1 Apa itu komponen?
K
omponen pada dasarnya adalah objek-objek yang dapat dimanipulasi pada saat kita merancang suatu program. Komponen Delphi terdiri dari objekobjek dalam bentuk kode Pascal yang biasanya mempunyai atribut dan fungsi yang dapat menggambarkan tingkah laku dari komponen tersebut.
Komponen tersebut biasanya diletakkan pada palet komponen dan bisa dimanipulasi di atas form designer .
Contoh beberapa komponen di atas form designer Komponen dapat terbentuk dari beberapa komponen lain yang memiliki sifat berbeda-beda dan membentuk suatu sifat gabungan baru yang berbeda dari komponenkomponen pembangunnya. Sebagai ilustrasi kita bisa mengibaratkan objek “rumah” yang dapat terbentuk dari komponen “pintu”, “jendela”, “genting”, “lantai”, dan sebagainya. Komponen “pintu” terdiri dari elemen “kaca”, “kayu”, komponen “pegangan pintu”, dan seterusnya. Seluruh komponen yang bersatu tersebut pada akhirnya membentuk suatu entitas baru yang kita sebut “rumah”.
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 2
1.2 Mengapa Kita Membuat Komponen? Membangun rumah dari nol tanpa ada komponen “pintu”, “jendela”, dan “genting” akan lebih lama daripada jika kesemua komponen itu telah tersedia dan siap untuk kita “manipulasi” sehingga menjadi rumah yang kita inginkan. Tanpa komponen, kita akan membutuhkan waktu yang lama untuk membuat suatu program. Komponen biasanya dibuat karena beberapa alasan. Alasan yang paling penting adalah kita tidak perlu atau tidak mungkin mengetahui (atau bahkan tidak mau tahu) detail semua hal ketika kita akan memprogram. Seperti ketika mengendarai mobil, kita tidak perlu tahu detail bagaimana mesin suatu mobil bekerja. Bagaimana piston bekerja, bahan bakar dicampur, dan seterusnya. Kita hanya perlu tahu bagaimana kita menjalankan mobil itu, atau dengan kata lain kita cukup mengenal behaviour atau perilaku mobil yang akan kita kendarai. Hampir seluruh mobil dijalankan dengan memasukkan kunci dan memutarnya ke ke kanan. Ini adalah salah satu bentuk antarmuka ( interface) antara pengendara dengan mobil. Bagi perusahaan produsen mobil, mereka tidak perlu membuat seluruh komponen yang dipakai. Ada perusahaan lain yang khusus membuat ban, knalpot, radiator, kursi, dan seterusnya. Produsen mobil ( assembler ) tahu bagaimana masing-masing komponen itu bekerja dan berinteraksi dengan komponen lainnya. Pada akhirnya seluruh komponen yang disatukan itu menjadi sebuah komponen atau objek baru, yang dinamakan “mobil”, dengan behaviour yang unik dan berbeda dari komponen-komponen penyusunnya.
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 3
Mengapa kita harus membuat komponen yang rumit kalau kita bisa membuat program dengan memanipulasi komponen yang sudah ada atau membuat kode program yang bisa melakukan apa yang kita inginkan?
− Membuat komponen menjadi penting (dan akan sangat menguntungkan secara ekonomi) bila kita ingin membuat sebuah komponen baru yang akan dipergunakan berkali-kali dalam setiap project yang akan kita buat
− Membuat komponen membuat aplikasi kita menjadi lebih handal, dengan memisahkan elemen-elemen program kita dengan pendekatan logika kelas berorientasi objek Pertanyaan
selanjutnya
adalah
darimana
kita
mendapatkan
komponen?
Jawabannya adalah build or build or buy buy, buat komponen sendiri atau beli. Kita membuat komponen sendiri karena beberapa atau salah satu dari hal berikut :
− Kita tidak mendapatkan penjual komponen itu atau karena memang belum ada yang pernah membuatnya
− Membuat komponen sendiri (sering) lebih murah daripada membelinya (prinsip ekonomi)
− Membuat komponen sendiri lebih memberikan kepuasan batin ( intangible value) kepada seorang programmer
− Kita ingin berbagi kepada programmer lain, dengan harapan programmer lain bisa menggunakan komponen yang sudah kita buat, baik dibagikan secara gratis ataupun dengan lisensi berbayar Kita menggunakan komponen yang sudah ada ketika :
− Kita belum bisa membuatnya (mungkin karena belum membaca buku ini
☺)
− Waktu yang tersisa untuk delivery project tidak memungkinkan kita untuk membuatnya sendiri
− Prinsip “ Don’t reinvent the wheel”. Kalau harganya terjangkau atau bahkan free, mengapa kita membuatnya kalau bisa memakai yang sudah dibuat orang
lain?
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 4
1.3 Apa saja saja yang perlu diketahui diketahui untuk membuat komponen? komponen? Untuk membuat komponen Delphi, pertama-tama kita harus mengenal bagaimana memprogram dengan Delphi. Semua sintaks-sintaks, operator, kata kunci, dan seterusnya harus kita pahami. Buku ini tidak dimaksudkan untuk belajar Delphi dari awal. Jika anda belum terlalu familiar dengan sintaks Pascal / Delphi, saya anjurkan anda untuk membaca buku-buku yang berisi tentang Pemrograman Pascal / Delphi tingkat awal. Berikutnya yang kedua adalah mengenal komponen yang ada pada Delphi. Ada dua jenis komponen yang ada pada Delphi, yaitu komponen nonvisual dan komponen visual. Komponen nonvisual tidak terlihat pada saat program dijalankan, namun dapat dirasakan efeknya. Komponen-komponen ini menyembunyikan suatu atribut tertentu dan memungkinkan programmer untuk mengubah beberapa karakteristiknya melalui Object Inspector pada saat design time dan running time. Contoh komponen nonvisual adalah
TDatasource, TTimer, dan TTable. Berbeda dengan komponen nonvisual, komponen visual dapat dilihat oleh end user ketika program berjalan. Komponen-komponen ini diturunkan dari TControl, sebuah kelas yang memiliki atribut dan fungsi yang berkaitan dengan visualisasi seperti Top, Left, Color, dan seterusnya. Contohnya adalah TMemo, TLabel, TEditBox, dan sebagainya. Beberapa kelas dasar yang sangat penting untuk
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 5
diketahui
adalah
TObject,
Exception,
TPersistent,
TComponent,
TControl,
dan
TWinControl. Dalam implementasi pemrograman, kita akan sering berhubungan dengan kelas-kelas tersebut. TObject merupakan kelas terdasar dan merupakan dasar dari semua kelas yang ada.
Kelas ini mengenkapsulasi tingkah laku fundamental dari seluruh objek VCL/CLX dengan memperkenalkan method yang melakukan fungsi dasar seperti membuat, mengatur, dan menghancurkan instans dari suatu objek dengan cara membebaskan alokasi memori yang digunakan oleh objek tersebut. Exception menentukan kelas dasar untuk semua kelas yang berkaitan dengan exceptions.
Exception menyediakan suatu antarmuka yang konsisten untuk kondisi kesalahan program dan memungkinkan aplikasi menangani kesalahan dengan lebih baik. TPersistent menentukan kelas dasar untuk semua objek yang mengimplementasikan property. Kelas yang mewarisi kelas ini berhubungan dengan pengiriman data melalui stream dan memungkinkan untuk kelas assignment.
TComponent merupakan kelas dasar untuk untuk semua komponen nonvisual, misalnya
TApplication. Kelas ini memungkinkan sebuah komponen tampak pada palet komponen, memungkinkan komponen berada dalam komponen lainnya, dan dapat dimanipulasi langsung di atas form. TControl mewakili kelas dasar untuk semua control atau komponen yang tampak pada
saat program berjalan. TWinControl menentukan kelas dasar untuk semua windows gadget (widget), di mana
semua komponen yang merupakan turunan dari kelas ini dapat menangkap masukan dari keyboard. Faktor ketiga yang harus dikuasai adalah memahami konsep Object Oriented Programming, Programming , pemrograman berorientasi objek. Mengapa? Karena struktur komponen disusun dari kelas-kelas. Karena representasi dari kelas adalah objek, maka ketika kita berbicara mengenai komponen, kita juga berbicara mengenai objek. Jika kita memprogram untuk membuat komponen, maka kita harus menguasai pemrograman yang
berorientasi pada objek.
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 6
2 Object Oriented Programming (OOP) 2.1 Apa itu OOP?
O
OP atau Object Oriented Programming (Pemrograman Berorientasi Objek) merupakan suatu bentuk pemrograman yang memodelkan masalah dengan pendekatan objek. Dalam bukunya yang berjudul An Introduction to
Object Oriented Programming, Timothy Budd mengutip karakteristik fundamental OOP
dari Alan Kay (yang dianggap oleh sebagian orang sebagai bapak OOP), adalah sebagai berikut [Budd]: 1. Semua adalah objek. 2. Komputasi dilakukan dengan komunikasi antarobjek. Setiap objek berkomunikasi dengan objek yang lain melalui pengiriman dan penerimaan pesan. Sebuah pesan merupakan permintaan atas sekumpulan aksi dengan semua argumen yang diperlukan untuk menyelesaikan suatu tugas tertentu. 3. Setiap objek memiliki memori sendiri, yang dapat terdiri dari objek-objek lainnya. 4. Setiap objek adalah wakil atau representasi dari suatu kelas. Sebuah kelas dapat mewakili sekelompok objek yang sama 5. Kelas merupakan kumpulan tingkah laku yang berkaitan dengan sebuah objek. Jadi, semua objek yang merupakan wakil dari kelas yang sama dapat melakukan aksi yang sama pula. 6. Kelas-kelas diorganisasi ke dalam struktur pohon yang berakar tunggal, dinamakan jenjang pewarisan ( inheritance hierarchy). Memori dan tingkah laku yang berkaitan dengan wakil dari sebuah kelas secara otomatis tersedia pada tiap kelas yang berasosiasi dengan sebuah turunan dalam struktur pohon ini. Jenjang ini bisa juga dipandang sebagai jenjang piramida, dengan kelas super atau kelas utama menduduki peringkat teratas dari semua kelas turunannya. Kelas Tertinggi
Kelas Terendah Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 7
Sifat kelas pada tingkat tertinggi terbawa hingga ke kelas pada tingkatan yang paling rendah, yang menunjukkan konsep pewarisan atau inheritance Dengan menginstruksikan tugas khusus dan terbatas pada setiap objek, programmer dapat memecah masalah pemrograman menjadi bagian-bagian kecil sehingga dapat mengatasi kompleksitas permasalahan dengan lebih mudah. Setiap objek pada umumnya memiliki tiga sifat, yaitu keadaan, operasi, dan identitas objek ([Horstmann] hal. 1). Sebuah objek dapat menyimpan informasi sebagai hasil operasi sebelumnya. Informasi tersebut menentukan bagaimana objek melakukan operasi selanjutnya. Koleksi dari seluruh informasi yang dimiliki objek pada suatu saat merupakan keadaan objek pada saat itu. Informasi tersebut pada akhirnya memberikan identitas khusus yang membedakan suatu objek dengan objek lainnya.
2.2 Apa perbedaan OOP dengan Procedural Procedural Programming Programming Menurut Bjarne Stroustrup dalam sebuah papernya yang berjudul What is ‘‘Object Oriented Programming’’? (1991 revised version) [Stroustrup], paradigma dalam
OOP adalah “Tentukan kelas yang kita inginkan; Lengkapi sederetan operasi untuk setiap kelas; Tentukan struktur secara eksplisit dengan pewarisan”. Sedangkan procedural programming berparadigma “Tentukan prosedur yang kita inginkan; Gunakan algoritma
terbaik yang bisa ditemukan.” Procedural programming berorientasi pada aksi, sedangkan object oriented berorientasi pada objek [Deitel]. Pemrograman terstruktur tradisional terdiri atas perancangan struktur data dan memanipulasinya dengan fungsi-fungsi dengan suatu cara tertentu yang secara teori bisa berhenti. Fungsi-fungsi ini yang biasa kita kenal dengan algoritma. Niklaus Wirth, memberikan judul bukunya Algorithms + Data Structures = Programs. Dari judulnya, secara tidak langsung beliau mengatakan bahwa algoritma dahulu, struktur data kemudian. Pada awalnya, pikirkan dahulu bagaimana memanipulasi data, baru menentukan struktur data apa yang tepat digunakan agar manipulasinya menjadi mudah. OOP membalik urutan tersebut dengan merancang struktur data di awal, baru kemudian mencari algoritma terbaik untuk memanipulasi data [Cornell].
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 8
Kata kunci procedural programming adalah dekomposisi masalah menjadi banyak fungsi. Cara ini cukup efektif untuk masalah kecil dan sederhana, namun untuk masalah yang jauh lebih besar, pendekatan dengan kelas / objek memberikan manfaat lebih. Pertama, kelas menyediakan mekanisme pengelompokkan yang memudahkan bagi kita. Sebuah program yang membutuhkan 2000 fungsi mungkin hanya membutuhkan 100 kelas dengan masing-masing kelas memiliki rata-rata 20 operasi. Kelas menyembunyikan (mengenkapsulasi) representasi data dari semua kode program kecuali operasinya saja. Jika sebuah bug program mengacaukan sebuah item data, lebih mudah mencari penyebabnya di antara 20 operasi daripada di antara 2000 fungsi [Horstmann hal. 13].
Global Data
Fungsi
Fungsi
Fungsi Fungsi
Procedural Programming
method
data method
data
method
method
method
data
method
Object Oriented Programming
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 9
3 Konsep-konsep Dasar OOP
K
arena komponen pada dasarnya adalah objek, maka memahami konsep OOP jelas merupakan sesuatu yang esensial. Kita akan membahas secara singkat mengenai hal-hal yang berkaitan dengan OOP sebagai
bekal utama dalam langkah pembuatan komponen yaitu:
− Kelas (class abstraction) − Enkapsulasi ( encapsulation) − Pewarisan (inheritance) − Polimorfisme ( polymorphism)
3.1 Kelas Kelas merupakan deskripsi abstrak informasi dan tingkah laku dari sekumpulan data. Kelas juga dikenal sebagai tipe objek. Karenanya, representasi atau wakil dari suatu kelas
adalah
objek
kelas
tersebut.
Sebuah
kelas
merupakan
tipe
data
yang
mengenkapsulasi data dan operasi pada data dalam suatu unit tunggal. Berbeda dengan procedural programming yang memisahkan antara data dan fungsi sebagai elemen yang
berbeda. Suatu kelas mendifinisikan suatu struktur yang terdiri atas data kelas ( data field ), ), prosedur atau fungsi kelas ( method ), ), dan sifat kelas ( property). Sebuah field pada dasarnya adalah sebuah variabel bagian dari kelas. Method merupakan semua prosedur yang berasosiasi dengan kelas tersebut. Ada method yang dipanggil melalui objek dari kelas, dan ada pula method yang dipanggil melalui kelas itu sendiri (hal ini akan dibahas lebih lanjut kemudian). Property adalah antarmuka untuk data yang berkaitan dengan objek dari kelas. Property memiliki cara khusus untuk mengaksesnya, yang dikenal dengan access specifiers. Di luar objek itu, property tampak pada dasarnya hampir sama seperti field. Istilah-istilah ini akan dijelaskan secara lebih jelas kemudian. Setiap objek secara dinamis mengalokasikan sejumlah memori dengan struktur yang telah ditentukan oleh tipe kelasnya. Setiap objek memiliki salinan yang bersifat tunggal untuk setiap field yang didefinisikan dalam kelas tersebut. Berbeda halnya
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 10
dengan method , semua objek dari kelas itu berbagi method yang sama. Objek diciptakan dan dimusnahkan dengan method khusus yang disebut constructor dan destructor . Variabel bertipe kelas sesungguhnya adalah pointer yang mereferensikan sebuah objek. Jadi ada lebih dari satu variabel yang dapat merujuk pada objek yang sama. Seperti halnya pointer yang lain, variabel bertipe kelas dapat menampung nilai nil. Perbedaannya adalah kita tidak perlu mendereferensikan variabel bertipe kelas untuk mengakses member dari kelas objek tersebut.
3.2 Enkapsulasi Istilah enkapsulasi sebenarnya adalah kombinasi data dan fungsionalitas dalam sebuah unit tunggal sebagai bentuk untuk menyembunyikan detail informasi. Inilah salah satu konsep dalam OOP yang tidak terdapat pada procedural programming. Tipe data record pada Pascal atau struct pada C hanya mengumpulkan data namun tidak untuk
fungsi atau operasi. Kelas menyatukan data dengan operasi dalam satu kesatuan. Sebagai tambahan
dalam
enkapsulasi,
OOP
lebih
dikarakterisasikan
dengan
pewarisan
(inheritance) dan polimorfisme ( polymorphism). Proses enkapsulasi memudahkan kita untuk menggunakan sebuah objek dari suatu kelas karena kita tidak perlu mengetahui segala hal secara rinci. Enkapsulasi menekankan pada antarmuka suatu kelas, atau dengan kata lain bagaimana menggunakan objek kelas tertentu. Sebuah contoh, kelas Mobil menyediakan antarmuka fungsi untuk menjalankan mobil tersebut, tanpa kita perlu tahu komposisi bahan bakar, udara, dan kalor yang diperlukan untuk proses tersebut. Disini terjadi proses enkapsulasi terhadap rincian bagaimana sebuah mobil dijalankan.
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 11
3.3 Pewarisan Sebuah objek dideskripsikan melalui sebuah kelas. Semua perilaku dari sebuah objek, dapat diketahui dengan mengenali kelas dari objek yang bersangkutan. Jika kita tahu bahwa objek “Dodol” adalah sebuah makanan, maka kita tahu bahwa objek itu bisa kita makan, mengandung zat-zat pembentuknya, dengan sejumlah protein atau mineral, misalnya. Contoh lain, jika objek “X” adalah sebuah Telepon, maka kita bisa menduga pasti ada suatu cara yang ada pada objek X tersebut yang dapat kita gunakan untuk menelpon atau menerima telepon dari orang lain. Sistem OOP memungkinkan kita untuk mendefinisikan suatu kelas baru dengan mewarisi sifat dari kelas lain yang sudah ada. Contohnya adalah Dodol Duren, Dodol Melon, dan Dodol Coklat adalah contoh dari beberapa jenis Dodol dengan rasa yang berbeda-beda. Dalam terminologi OOP, kesemua Dodol itu dikatakan mewarisi kelas Dodol pada umumnya, misalnya mewarisi bahan pembuat utama yang sama dengan cara pembuatan yang hampir sama, namun dengan aroma dan citarasa khusus yang ditambahkan untuk membedakan antara Dodol yang satu dengan dodol yang lainnya. Dodol Duren, Dodol Melon, dan Dodol Coklat dikatakan sub kelas dari kelas Dodol, sedangkan kelas Dodol adalah super kelas dari ketiga kelas tersebut. Semua kelas turunan dari kelas Dodol mewarisi sifat-sifat yang ada pada kelas Dodol. Kita bisa menambahkan sifat khusus yang ada pada kelas turunan yang tidak ada pada kelas Dodol itu sendiri. Penurunan sifat ini bisa dilakukan secara bertingkat-tingkat, sehingga semakin ke bawah maka kelas tersebut menjadi semakin spesifik. Misalnya kelas Dodol Duren Bangkok Spesial Keju mungkin berukuran lebih besar daripada kelas Dodol pada umumnya, memiliki rasa Duren Bangkok, dan memiliki rasa keju yang khas di dalamnya. Sub kelas memungkinkan kita untuk melakukan spesifikasi detail dan perilaku khusus dari kelas supernya.
Dengan konsep pewarisan, seorang programmer dapat
menggunakan kode yang telah ditulisnya pada kelas super berulang kali pada kelas-kelas turunannya tanpa harus menulis ulang semua kode-kode itu. Kelas abstrak dapat dibuat sebagai kelas super yang mendefinisikan perilaku umum, misalnya kelas Makanan. Kelas Makanan adalah suatu kelas abstrak, yang mendefinisikan sesuatu yang dapat dimakan. Kelas turunannya misalnya adalah kelas Dodol, kelas Rujak, kelas Nasi Goreng, dan sebagainya. Kelas Makanan tidak mempunyai bentuk, karena ia adalah kelas abstrak. Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 12
Bentuknya menjadi jelas ketika kita membuat kelas turunan yang mewarisi dari kelas Makanan, misalnya kelas Nasi Goreng.
Contoh kelas turunan dari kelas abstrak “Makanan”
3.4 Polimorfisme Polimorfisme merupakan kemampuan objek-objek yang berbeda kelas namun terkait dalam pewarisan untuk merespon secara berbeda terhadap suatu pesan yang sama [Deitel]. Polmorfisme juga dapat dikatakan kemampuan sebuah objek untuk memutuskan method mana yang akan diterapkan padanya, tergantung letak objek tersebut pada jenjang pewarisan [Cornell]. Misalnya kita mempunyai kelas Truk yang memiliki method Jalan, dengan kelas TrukMini yang merupakan turunan dari kelas Truk, yang juga memiliki method Jalan. Sebuah objek yang bertipe TrukMini dan memanggil method Jalan, akan memanggil method Jalan yang terdapat pada kelas TrukMini, dan bukan method Jalan pada kelas Truk. Proses ini termasuk
polimorfisme
murni
karena
berkaitan dengan jenjang pewarisan,
dan dinamakan method overriding.
Polimorfisme yang lain juga dapat
berlaku ketika sebuah kelas memiliki
lebih dari satu method yang sama
namanya,
signaturenya (berbeda pada jenis atau
jumlah
method Jalan bisa dibuat lebih dari satu,
tergantung tipe data parameternya,
namun parameternya).
berbeda Misalnya
misal Jalan dengan parameter kecepatan yang bertipe integer atau bertipe double, atau bahkan bertipe String. Bentuk ini dikenal dengan method name overloading. Horstmann memberikan istilah polimorfisme jenis ini dengan ad hoc polymorphism. Ada beberapa sifat dalam method overriding, yaitu refinement, renaming, dan replacement . Refinement merupakan jenis overriding dimana kode yang ada dalam superclass disatukan dengan kode yang ada pada subclass. Renaming subclass. Renaming merupakan proses Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 13
pengubahan nama dari suatu operasi yang diwarisi tanpa mengubah perilakunya. Sedangkan replacement merupakan jenis overriding di mana kode yang ada pada superclass benar-benar digantikan oleh kode yang ada pada turunannya.
4 Disain dan Implementasi Implementasi Pemrograman Berorientasi Object dengan Delphi 4.1 Bermula dari Masalah, Masalah, Diakhiri Diakhiri dengan dengan Solusi Program
S
emuanya bermula dari permasalahan. Sebelum membuat program, ada tiga langkah utama yang bisa terjadi secara berkesinambungan dan membentuk daur tertentu setelah kita mendapatkan suatu masalah untuk dipecahkan
dengan program. Pertama, adalah analisis permasalahan itu sendiri. Kedua, kita melakukan disain bagaimana kita akan memecahkan masalah tersebut. Ketiga, adalah implementasi disain yang telah kita buat. Terkadang, kita harus kembali ke tahap pertama dan tahap kedua jika memang diperlukan.
4.1.1 Fase Analisis Pada fase ini biasanya pemahaman masalah yang masih samar-samar diubah menjadi deskripsi spesifik yang berisi tentang masalah-masalah yang akan dipecahkan. Misalnya kita akan membuat sebuah program permainan Halma. Pada fase ini, harus dijelaskan aturan permainan yang tepat dan tidak mengandung kontradiksi. Jika beberapa daerah mempunyai aturan permainan Halma yang berbeda-beda, fase ini harus menghasilkan aturan yang baku dan dijadikan suatu panduan untuk fase selanjutnya. Hal lain yang harus didokumentasikan adalah bagaimana pemain akan berinteraksi dengan program. Bagaimana bila akan dibuat versi jaringan, dan bagaimana pula jika dilengkapi dengan pemain komputer dengan menggunakan teknologi kecerdasan buatan, dan sebagainya. [Horstmann] pada halaman 5 menekankan bahwa fase ini adalah penjelasan apa yang harus dilakukan dan bukan bagaimana sesuatu harus dilakukan.
4.1.2 Fase Disain
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 14
Perancang program mulai memecahkan masalah dengan pendekatan objek, yaitu memetakan permasalahan ke dalam kelas-kelas dan pengelompokkan kelas. Setiap kelas dinyatakan secara tepat yang berisi atribut-atribut dan semua fungsi yang berkaitan hanya dengan kelas tersebut. Pada fase ini, detail implementasi belum diputuskan secara pasti. Misalnya kelas yang bertipe kumpulan, tidak perlu diputuskan apakah nantinya akan menggunakan HashTable atau Tree tertentu. Bahkan pemilihan bahasa pemrograman juga bukan masalah yang harus diputuskan pada fase ini. Hasil utama dalam fase ini adalah rancangan interaksi antarkelas yang mendukung pemrograman berorientasi objek yang harus dapat diimplementasikan dengan semua bahasa pemrograman apapun yang mendukung OOP.
4.1.3 Fase Implementasi Pada fase ini programmer mengubah disain kelas-kelas menjadi untain kode program ke dalam bahasa pemrograman tertentu yang telah ditentukan. Setelah itu kodekode tersebut diuji dan pada akhirnya diintegrasikan menjadi satu solusi program akhir. Pada beberapa permasalahan yang cukup kompleks untuk dimengerti, adanya sebuah prototipe program akan sangat membantu bahkan pada fase disain maupun analisis sekalipun. Dengan adanya prototipe ini, diharapkan banyak gagasan akan muncul sehingga solusi yang diinginkan benar-benar dapat tercapai. [Horstmann] mengingatkan agar kita tidak terburu-buru dalam fase analisis dan disain semata-mata hanya untuk mengejar pembuatan prototipe. Sebaliknya jangan pula kita ragu-ragu untuk kembali ke fase sebelumnya apabila prototipe benar-benar memberikan kita gagasan baru dalam memecahkan masalah.
Analisis
Disain
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 15
Implementasi
4.2 Studi Kasus Kasus – Menganalisis, Mendisain, dan Mengimplementasikan Kelas Berikut ini kita akan coba untuk membuat kelas-kelas yang berkaitan dengan bangun datar, seperti persegi panjang, lingkaran, dan segitiga dan semuanya dapat digunakan untuk menghitung luas dan panjang kelilingnya. Kita akan mencoba untuk menganalisis, mendisain, dan mengimplementasikan ketiga kelas di atas.
4.2.1 Analisis − Persegi panjang memiliki atribut Persegi Panjang
−
−
panjang dan lebar Luas persegi panjang dihitung dengan jalan mengalikan panjang dan lebarnya Keliling dihitung dari penjumlahan semua sisinya, yaitu 2 x (panjang + lebar)
− Lingkaran memiliki atribut jari-
Lingkaran
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 16
jari yang merupakan separuh dari diameternya − Luas lingkaran dihitung dengan jalan mengalikan konstanta Pi yang nilainya didekati oleh 22/7 dengan kuadrat jari-jarinya − Keliling dihitung dengan mengalikan konstanta Pi dengan diameternya
− Segitiga memiliki atribut 3 sisi
Segitiga
−
−
berupa garis lurus yang membentuk kurva sederhana tertutup Luasnya dihitung dengan nilai akar dari hasil kali setengah keliling segitiga yang dikalikan dengan semua selisih setengah keliling itu dengan masingmasing sisinya Keliling dihitung dengan menjumlahkan ketiga sisinya
4.2.2 Disain Jika kita daftarkan semua operasi dan atribut yang berkaitan dengan masing-masing bangun datar tersebut maka kita akan dapatkan tabel berikut ini:
Kelas
Kelas PersegiPanjang
Operasi
− LuasPersegiPanjang (menghitung luas persegi
Atribut
− panjang − lebar
panjang)
− KelilingPersegiPanjang (menghitung keliling persegi panjang) Kelas Lingkaran
− LuasLingkaran (menghitung luas
− jarijari
lingkaran)
− KelilingLingkaran (menghitung keliling lingkaran) Kelas Segitiga
− LuasSegitiga (menghitung luas segitiga)
− KelilingSegitiga (menghitung keliling segitiga) Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 17
− sisi1 − sisi2 − sisi3
Jika kita pisahkan ketiga entitas tersebut, kita akan dapatkan daftar berikut: Class PersegiPanjang
Attribute panjang lebar Method cariLuas cariKeliling
Class Lingkaran
Class Segitiga
Attribute jarijari
Attribute sisiA, sisiB, sisiC
Method cariLuas cariKeliling
Method cariLuas cariKeliling
Setelah kita perhatikan, ternyata ditemukan bahwa ketiga kelas tersebut memiliki dua method yang selalu muncul, yaitu cariLuas dan cariKeliling.
Kita bisa
menggunakan konsep inheritance dan generalisation (pewarisan dan generalisasi) untuk ketiga kelas tersebut. Ketiganya adalah merupakan bangun datar. Kelas yang akan ditambahkan adalah kelas BangunDatar yang dapat dijadikan kelas dasar untuk ketiga kelas tersebut. Karena kelas bangun datar sangat luas, dan tidak dapat diketahui bentuknya, maka kelas bangun datar dapat digolongkan sebagai kelas abstrak. Kelas ini tidak berguna untuk diinstantiasikan diinstantias ikan atau dibuat objeknya (jika kita memanggil member dari kelas abstrak, akan menimbulkan exception EAbstractError) untuk komponen yang mengandung method abstract tidak bisa dibuat instancenya. Kelas ini harus diturunkan terlebih dahulu menjadi kelas yang lebih kongkrit, misalnya kelas Lingkaran, PersegiPanjang, Segitiga, atau misalnya kelas JajaranGenjang. Pada diagram berikut ini kita bisa melakukan pull up method , yaitu menarik method yang ada pada suatu kelas dan meletakkannya pada kelas supernya. Dengan menggunakan kelas abstrak ini, jika suatu waktu kita akan membuat kelas yang merupakan bangun datar, maka kita dapat menurunkannya langsung dari kelas abstrak BangunDatar yang telah kita buat. Dan jika kita tahu ada sebuah kelas merupakan turunan dari kelas BangunDatar, maka kita tahu persis bahwa kelas tersebut pasti memiliki method/fungsi/operasi
cariLuas dan
cariKeliling. Artinya, ada semacam kontrak yang mengatakan bahwa jika sebuah kelas
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 18
mengimplementasikan suatu kelas abstrak, maka kelas tersebut harus memiliki implementasi dari semua operasi abstrak yang ada pada kelas abstrak yang akan diimplementasikan. Abstract Class BangunDatar Method cariLuas cariKeliling Lambang pewarisan
Class PersegiPanjang
Attribute panjang lebar Method cariLuas cariKeliling
Class Lingkaran
Class Segitiga
Attribute jarijari
Attribute sisiA, sisiB, sisiC
Method cariLuas cariKeliling
Method cariLuas cariKeliling
Karena semua method pada kelas BangunDatar bersifat abstract, maka kita juga bisa membuat BangunDatar sebagai interface. Interface dikenal juga sebagai kelas abstrak murni. Jika kelas abstrak bisa memiliki sebagian method yang kongkrit dan abstrak, maka interface hanya memiliki method yang dideklarasikan sebagai abstrak.
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 19
4.2.3 Implementasi Ketika kita jalankan Delphi akan tampak tampilan berikut.
Component Palette
Object TreeView
Form Designer Object Inspector
Keterangan: 1. Form Designer merupakan wadah ( container ) yang dijadikan sebagai tempat untuk meletakkan semua komponen visual yang akan tampak pada program yang akan kita buat. Pada saat kita buka Delphi pertama kali, otomatis kita akan mendapatkan sebuah objek dari kelas TForm 2. Component Palette merupakan tempat untuk meletakkan semua komponen yang siap digunakan pada program delphi kita 3. Object Inspector merupakan panel untuk menginspeksi objek, dengan kata lain melihat atribut-atribut dari sebuah objek sehingga kita bisa mengubahnya pada saat design time 4. Object Tree View merupakan panel untuk melihat hirarki objek-objek yang diletakkan pada form kita. Hal ini akan memudahkan kita untuk memilih objek yang sulit untuk diklik ketika akan dipilih, dan melihat parent dari sebuah objek. Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 20
Untuk membuat kelas-kelas di atas, kita perlu membuat sebuah unit. Langkahnya adalah sebagai berikut : 1. Klik menu File New Unit
Sebuah program dibangun dari modul-modul kode program yang disebut unit. Setiap unit disimpan dalam sebuah file terpisah, dan dikompilasi secara terpisah pula. Dengan unit, kita dapat :
−
Membagi program yang besar ke dalam modul-modul, sehingga bisa diedit secara terpisah
−
Membuat library yang bisa digunakan oleh banyak program
−
Library yang telah dikompilasi dapat didistribusikan kepada programmer lain, tanpa harus
menyertakan kode program yang kita buat
Pada gambar di atas, pada waktu kita membuat sebuah unit, akan tampak bagian unit (unit merupakan reserved word atau kata kunci) , interface, implementation, dan end.
Nama unit tersebut secara default diberi nama Unit1, yang otomatis akan disimpan dalam file Unit1.PAS dan setelah dikompilasi akan menghasilkan file Unit1.DCU (delphi compiled unit). Nama unit harus unik dalam sebuah program, artinya tidak boleh ada dua unit yang memiliki nama yang sama, meskipun diletakkan dalam folder yang berbeda. Bagian interface dimulai dari kata kunci interface dan diakhir pada kata kunci implementation. Dalam bagian ini, kita bisa mendeklarasikan konstanta, tipe data, Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 21
variabel, prosedur, dan fungsi yang tersedia bagi unit lain yang akan menggunakan unit ini. Bagian interface hanya menyebutkan deklarasi atau prototipenya saja, sedangkan implementasi dari fungsi atau prosedur diletakkan setelah kata kunci implementation. Untuk membuat kelas BangunDatar, pertama-tama kita simpan unit1 menjadi classBangunDatar.PAS, sehingga nama unitnya menjadi classBangunDatar. Konvensi ini saya pilih untuk menunjukkan bahwa file classBangunDatar.PAS akan berisi kelas TBangunDatar.
Penjelasan:
− File classBangunDatar.PAS memiliki
unit classBangunDatar
− Unit tersebut memiliki sebuah kelas bernama turunan dari kelas di atas dengan
TObject.
class
TBangunDatar
Kita bisa saja menuliskan
yang merupakan
class (TObject )
pada contoh
saja. Sebab jika kita hanya memberikan kata
secara default kelas tersebut merupakan turunan dari kelas kejelasan, saya sengaja selalu menggunakan
TObject
class ,
TObject.
Untuk
untuk semua kelas turunan
dari kelas TObject
− Kata
kunci
cariKeliling
public
menunjukkan
dapat diakses semua unit
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 22
bahwa
function
cariLuas
dan
−
cariLuas double,
dan
cariKeliling
dideklarasikan
adalah fungsi yang mengembalikan tipe data
virtual,
artinya dapat dioverride atau implementasinya
dapat diubah oleh kelas turunannya, dan dideklarasikan ada implementasinya pada kelas
TBangunDatar,
abstract,
artinya tidak
dan implementasinya diserahkan
pada kelas turunannya Perbandingan pada
public abstract class BangunDatar extends Object { public abstract double cariLuas();
pemrograman Java (disimpan pada file
public abstract double cariKeliling();
}
BangunDatar.java)
− jika kita mengimplementasikan kedua fungsi pada kita akan mendapatkan pesan kesalahan
unit classBangunDatar, maka
:
Kelas pada Delphi hampir sama dengan Java, pada dasarnya adalah pointer. Compiler secara otomatis menyembunyikannya, sehingga kita tidak perlu menggunakan operator pointer. Mengetahui status kelas sebagai pointer pada dasarnya penting ketika kita membuat fungsi dengan parameter sebuah kelas. Pada umumnya, kita seharusnya
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 23
melalukan kelas by value daripada by reference. Alasannya adalah kelas sudah merupakan pointer, yang merupakan reference. Melalukan sebuah kelas by reference sama saja melakukan reference ke reference lainnya. Hal ini berbeda dengan class pada C++ yang lebih mirip pada tipe data structnya atau seperti record pada pascal, hanya saja dilengkapi dengan method. Untuk membuat kelas bertipe pointer kita harus menggunakan operator pointer *.
Untuk menghasilkan kode pada bagian implementasi, kita dapat mengetikkan secara manual atau meletakkan kursor pada akhir baris prototipe fungsinya, dan menekan tombol CTRL + SHIFT + C. Untuk menambahkan akses pada panjang dan lebar dari persegi panjang, kita perlu memberikan aksesor dan mutator pada variabel panjang dan lebar. Kedua variabel itu tetap dalam batasan private artinya hanya bisa diakses dari dalam unit tersebut. Ada dua cara untuk melakukannya di Delphi, yaitu dengan public method untuk aksesor dan Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 24
mutator, atau dengan menggunakan property. Dengan property, kita seolah-olah memiliki variabel bertipe public, padahal nama property tersebut hanyalah antarmuka untuk variabel yang bersifat private atau bahkan method yang sifatnya private. Kita lihat perbedaannya pada contoh berikut: unit classPersegiPanjang; interface uses classBangunDatar; type TPersegiPanjang = class(TBangunDatar) private FPanjang: double; // Konvensi variable private pada Delphi diawali dengan F FLebar: double; public function cariLuas:double; override; function cariKeliling:double; override; //dengan menggunakan property property Panjang:double read FPanjang write FPanjang; property Lebar:double read FLebar write FLebar; end; implementation
{ TPersegiPanjang } function TPersegiPanjang.cariKeliling: double; begin Result := 2 * (FPanjang + FLebar); end; function TPersegiPanjang.cariLuas: double; begin Result := FPanjang * FLebar; end; end.
Versi lainnya adalah :
unit classPersegiPanjang; interface uses classBangunDatar; type TPersegiPanjang = class(TBangunDatar) private FPanjang: double; FLebar: double; public function cariLuas:double; override; function cariKeliling:double; override; function getPanjang:double; function getLebar:double; procedure setPanjang(panjang:double); procedure setLebar(lebar:double); end; implementation
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 25
{ TPersegiPanjang } function TPersegiPanjang.cariKeliling: double; begin Result := 2 * (FPanjang + FLebar); end; function TPersegiPanjang.cariLuas: double; begin Result := FPanjang * FLebar; end; function TPersegiPanjang.getLebar: double; begin Result := FLebar; end; function TPersegiPanjang.getPanjang: double; begin Result := FPanjang; end; procedure TPersegiPanjang.setLebar(lebar: double); begin FLebar := lebar; end; procedure TPersegiPanjang.setPanjang(panjang: double); begin FPanjang := panjang; end; end.
Alternatif lainnya adalah melakukan kombinasi antara pemanfaatan variabel private dan method private pada penggunaan property : type TPersegiPanjang = class(TBangunDatar) private FPanjang: double; FLebar: double; procedure setPanjang(panjang:double); procedure setLebar(lebar:double); public function cariLuas:double; override; function cariKeliling:double; override; property Panjang:double read FPanjang write setPanjang; property Lebar:double read FLebar write setLebar; end;
Keuntungan menggunakan property adalah :
− Pengembang aplikasi dapat mengubah nilai property pada saat design time, tidak seperti method yang hanya tersedia pada saat run time. Property bisa muncul pada object inspector, dan nilainya bisa divalidasi begitu diubah, karena read dan write bisa diikuti method yang bisa memvalidasi nilai yang diberikan pada property tersebut
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 26
− Property bisa menyembunyikan detail implementasi, hanya dengan melakukan assignment seperti pada data field biasa, sebenarnya kita bisa melakukan perhitungan sangat kompleks, yang tersembunyi dari user
− Property bisa virtual, dapat diimplementasikan secara berbeda pada komponen yang berbeda Perbandingan pada pemrograman Java
public class PersegiPanjang extends BangunDatar { private double panjang; private double lebar; public PersegiPanjang(double panjang, double lebar) { this.panjang = panjang; this.lebar = lebar; } public double cariLuas() { return panjang * lebar; } public double cariKeliling() { return 2 * (panjang + lebar); } public double getLebar() { return lebar; } public void setLebar(double lebar) { this.lebar = lebar; } public double getPanjang() { return panjang; } public void setPanjang(double panjang) { this.panjang = panjang; }
(disimpan pada file PersegiPanjang.java)
}
Saya sendiri lebih menyukai versi final dari kelas PersegiPanjang berikut ini, yang dilengkapi dengan constructor. Constructor merupakan method khusus yang digunakan untuk menciptakan dan menginisialisasikan sebuah objek. Deklarasinya hampir sama dengan procedure atau function,
hanya
saja
keyword
pendahulunya
adalah
constructor .
Meskipun
deklarasinya tidak mengembalikan nilai, namun sebuah constructor mengembalikan sebuah reference ke objek yang dibuat. Secara konvensional, nama constructor adalah (tidak seperti pada Java atau C++ yang mengharuskan nama constructor sama
Create
dengan nama kelasnya). Semua data field otomatis akan bernilai 0 untuk tipe ordinal, kosong untuk String, unsassigned untuk Variant, dan nil untuk pointer atau tipe kelas. Jadi tidak perlu melakukan inisialisasi dengan nilai tersebut pada constructor. Self
adalah pointer ke objek kelas yang bersangkutan, pada C++ dan Java
dikenal dengan
this.
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 27
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 28
Versi untuk kelas lingkaran adalah sebagai berikut :
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 29
Versi untuk kelas Segitiga adalah sebagai berikut :
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 30
Mari kita lihat contoh penggunaan kelas-kelas tersebut pada Delphi. Buat sebuah form dengan tampilan secara teks (View as Text) adalah sebagai berikut: object formBangunDatar: TformBangunDatar Left = 223 Top = 264 Width = 600 Height = 188 Caption = 'Percobaan Bangun Datar' Color = clBtnFace Font.Charset = ANSI_CHARSET Font.Color = clWindowText Font.Height = -13 Font.Name = 'Courier New' Font.Style = [] OldCreateOrder = False OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 16 object memoOutput: TMemo Left = 4 Top = 8 Width = 577 Height = 137 TabOrder = 0 end end
Tampilan secara visual (View as Form) adalah
:
unit FormUtama; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TformBangunDatar = class(TForm) memoOutput: TMemo; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var formBangunDatar: TformBangunDatar;
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 31
implementation uses classBangunDatar, classPersegiPanjang, classLingkaran, classSegitiga;
{$R *.dfm} procedure TformBangunDatar.FormCreate(Sender: TObject); var bangunDatar:TBangunDatar; begin bangunDatar := TPersegiPanjang.Create(10, 5); memoOutput.Lines.Add(Format('Keliling persegi panjang dengan panjang = %d ' + 'dan lebar = %d adalah %g', [10, 5, bangunDatar.cariKeliling])); memoOutput.Lines.Add(Format('Luas persegi panjang dengan panjang = %d ' + 'dan lebar = %d adalah %g', [10, 5, bangunDatar.cariLuas]));
bangunDatar := TLingkaran.Create(7); memoOutput.Lines.Add(Format('Keliling lingkaran dengan jarijari = %d ' + 'adalah %g', [7, bangunDatar.cariKeliling])); memoOutput.Lines.Add(Format('Luas lingkaran dengan jarijari = %d ' + 'adalah %g', [7, bangunDatar.cariLuas])); bangunDatar := TSegitiga.Create(3, 4, 5); memoOutput.Lines .Add(Format('Keli ling segitiga dengan sisi %d, %d, dan %d ' + 'adalah %g', [3, 4, 5, bangunDatar.cariKeliling])); memoOutput.Lines .Add(Format('Luas segitiga dengan sisi %d, %d, dan %d ' + 'adalah %g', [3, 4, 5, bangunDatar.cariLuas])); end; end.
Ketika program dijalankan, akan tampil seperti berikut:
Sampai tahap ini kita telah mencoba memulai untuk membuat aplikasi di Delphi dengan pendekatan berorientasi pada Objek. Masih banyak konsep OOP lainnya yang belum ditemui, dan akan saya jelaskan sedikit demi sedikit sambil learning by example. Jadi penjelasan akan diberikan ketika dibutuhkan pada saat studi kasus dan ketika dibutuhkan.
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 32
5 Membuat Komponen Sederhana
K
ini saatnya kita mencoba untuk membuat komponen sederhana dengan Delphi. Ada beberapa hal yang perlu kita ketahui dalam pembuatan komponen. Pertama-
tama kita perlu tahu bahwa ada beberapa struktur dalam sebuah komponen.
Kita harus dapat membedakan antara kelas dengan komponen. Kelas adalah struktur atau tipe data dalam Object Pascal, sedangkan komponen adalah sebuah kelas yang dapat dimanipulasi dalam Delphi Environment.
Struktur dalam sebuah komponen adalah sebagai berikut:
− Properties (seperti yang sudah kita bahas pada bab sebelumnya) dalam sebuah komponen jika dimasukkan ke dalam seksi published (dalam struktur kelas), akan muncul pada Object Inspector. Properties ini memungkinkan kita mengakses field pada objek dari komponen yang bersangkutan, baik secara design time ataupun run time.
− Method (fungsi atau prosedur dari suatu kelas) − Events (terjadinya serangkaian aksi yang terjadi sebagai akibat terjadinya suatu aksi lainnya). Pada dasarnya, events adalah pointer ke sebuah method. Hal ini memungkinkan kita untuk melakukan assignment pada sebuah event dengan prosedur yang kita miliki pada saat program sedang berjalan ( run time).
Selain itu kita perlu tahu mengenai konsep kepemilikan ( ownership) dan juga pewadahan ( parenthood parenthood ). ). Sebuah komponen bisa memiliki komponen lainnya. Pemilik sebuah komponen ditentukan dengan property Owner. Ketika sebuah komponen memiliki komponen lainnya, komponen tersebut bertanggungjawab membebaskan alokasi memori komponen yang dimilikinya ketika komponen itu juga sedang dibebaskan alokasi memorinya. Parenthood hanya dimungkinkan pada komponen turunan dari TWinControl yang bisa berfungsi sebagai parent (wadah). Komponen parent bertangunggjawab untuk untuk memanggil method komponen anaknya untuk memaksa mereka menggambar diri Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 33
mereka sendiri. Konsep ini ditentukan melalui property Parent. Sebuah komponen bisa memiliki Owner dan Parent yang berbeda.
5.1 Langkah-langkah Membuat Komponen Ada beberapa check list yang perlu kita perhatikan ketika kita membuat komponen sendiri:
− Apakah komponen yang akan kita buat cukup unik dan akan berguna untuk kita sendiri atau programmer lain?
− Sudah jelaskah algoritma yang akan kita gunakan nantinya? − Sudahkah saya melakukan testing untuk komponen tersebut sebelum diletakkan dalam Palet Komponen?
Lima langkah dasar ketika kita akan membuat komponen di Delphi: 1. Tentukan superclass dari komponen 2. Buat sebuah unit untuk komponen tersebut 3. Tambahkan method, properties, dan event (jika perlu) 4. Uji coba komponen tersebut 5. Daftarkan komponen tersebut ke Delphi Environment Adalah hal yang tidak kalah pentingnya bagi kita untuk membuat help file untuk komponen kita. Dalam help tersebut setidaknya ada daftar Properties, Method, dan Event yang ada dalam komponen yang kita buat, termasuk cara menggunakannya dengan contoh yang jelas dan mudah. Semakin baik dan lengkap help file yang dibuat untuk sebuah komponen, maka semakin mudah programmer lain akan menggunakan komponen tersebut (bukankah itu salah satu tujuan kita ketika membuat komponen sendiri?).
5.1.1 Menentukan Superclass dari Komponen Jika kita ingin membuat komponen 1. nonvisual (contohnya
TTimer),
kita membutuhkan superclass
2. yang tidak memiliki window handle (contohnya adalah
TGraphicControl
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 34
TComponent
TPaintBox),
superclassnya
3. yang
memiliki
window
superclassnya adalah
handle
(contohnya
TCheckBox ,
TComboBox ),
TWinControl
4. yang memiliki window handle dan mempunyai kemampuan khusus untuk menggambar
dalam
canvas
dan
memiliki
method
paint()
untuk
menggambarkan penampilan komponen secara khusus, gunakan superclass TCustomControl
5. untuk memiliki karakteristik dari komponen yang sudah ada, gunakan komponen dalam
komponen
palette
seperti
TEdit,
TPanel,
TScrollBox,
dan
sebagainya.
5.1.2 Membuat Komponen Sederhana Langkah demi Langkah Sebagai contoh, kita akan membuat komponen yang sangat sederhana, yaitu sebuah komponen non visual. Idenya adalah membuat sebuah komponen yang:
− bernama TPersegiPanjangSederhana − memanfaatkan kelas TPersegiPanjang yang sudah dibuat pada bab sebelumnya − tidak memiliki visualisasi di atas form − property Panjang dan Lebar harus bisa diakses dari Object Inspector − Panjang dan Lebar harus lebih dari 0, jika tidak akan berubah secara otomatis menjadi masing-masing 1 satuan panjang
− Memiliki fungsi untuk mencari luas dan keliling yang bisa digunakan pada saat run time
Langkah-langkahnya adalah sebagai berikut :
− Buat sebuah project baru, File
New Application
− Simpan Project dengan nama KomponenPersegiPanjangSederhana − Simpan File dengan nama TestForm − Tambahkan unit
classPersegiPanjang
dan classBangunDatar yang
sudah dibuat pada bab sebelumnya dengan cara menekan tombol Shift + F11 atau menu Project Add to Project
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 35
− atau jika anda tidak ingin melakukan langkah pada nomor 4, anda bisa membuat dua unit baru dengan jalan memilih menu File New Unit dan dibuat persis seperti pada contoh bab sebelumnya dan simpan dengan nama
classPersegiPanjang
dan
classBangunDatar
(salin
isinya persis pada contoh)
− Buat sebuah unit baru, simpan dengan nama classPersegiPanjangSederhana
− Ketikkan pada unit tersebut kode program berikut: unit classPersegiPanjangSederhana; interface uses Classes, classPersegiPanjang;
{ Kita membutuhkan unit Classes karena kita menggunakan TComponent sebagai superclass komponen TPersegiPanjangSederhana dan membutuhkan classPersegiPanjang karena kita membutuhkan sebuah variabel private bertipe TPersegiPanjang yang dideklarasikan pada unit classPersegiPanjang. } type
TPersegiPanjangSederhana = class (TComponent) private persegiPanjang:TPersegiPanjang;
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 36
function GetLebar: double; function GetPanjang: double; procedure SetLebar(const Value: double); procedure SetPanjang(const Value: double); public constructor Create(AOwner:TComponent); override; destructor Destroy; override; function cariLuas:double; function cariKeliling:double; published property Panjang:double read GetPanjang write SetPanjang; property Lebar:double read GetLebar write SetLebar; end; procedure Register; { Prosedure ini digunakan ketika kita akan mendaftarkan komponen ini ke Palet Komponen
Nama procedure ini harus persis sama dengan di atas, diawali huruf besar, untuk kompatibilitas dengan C++ Builder yang case sensitive agar VCL yang dibuat di Delphi bisa digunakan pada C++ Builder Deklarasi prosedur ini WAJIB diletakkan pada bagian interface } implementation uses Dialogs; procedure Register; begin RegisterComponents('Wisnu Widiarta', [TPersegiPanjangSederhana]);
{ Komponen TPersegiPanjang akan didaftarkan pada komponen palet pada halaman dengan nama Wisnu Widiarta } end;
{ Kita menggunakan unit Dialogs karena kita menggunakan fungsi showMessage pada implementasi. Perhatikan bahwa uses pada bagian interface biasanya mengacu pada unit yang mengandung tipe data yang diperlukan pada waktu deklarasi tipe data, sedangkan uses setelah implementation mengacu pada pemanggilan fungsi atau prosedur pada implementasi kelas } { TPersegiPanjangSederhana } function TPersegiPanjangSederhana.cariKeliling: double; Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 37
begin
Result := persegiPanjang.cariKeliling; end; function TPersegiPanjangSederhana.cariLuas: double; begin Result := persegiPanjang.cariLuas; end; constructor TPersegiPanjangSederhana.Create(AOwner: TComponent); var lebarDefault, panjangDefault:double; begin inherited Create(AOwner);
{ Pada umumnya pemanggilan inherited Create di atas Selalu dilakukan sebelum kita melakukan inisialisasi data field. Dengan melakukannya, kita memanggil constructor Create pada superclass, dan memastikan bahwa semua data pada superclass telah terinisialisasi dengan baik } lebarDefault := 1.0; panjangDefault := 1.0; persegiPanjang := TPersegiPanjang.Create(panjangDefault, lebarDefault); end; destructor TPersegiPanjangSederhana.Destroy; begin persegiPanjang.Free; inherited ; { Pada umumnya pemanggilan inherited pada destructor Dilakukan setelah kita membebaskan alokasi memori untuk semua data field kelas kita sendiri } end; function TPersegiPanjangSederhana.GetLebar: double; begin Result := persegiPanjang.Lebar; end; function TPersegiPanjangSederhana.GetPanjang: double; begin Result := persegiPanjang.Panjang; end; procedure TPersegiPanjangSederhana.SetLebar( const Value: double); begin if Value <= 0 then begin Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 38
showMessage('Lebar harus lebih dari 0'); persegiPanjang.Lebar := 1; end else
persegiPanjang.Lebar := Value; end; procedure TPersegiPanjangSederhana.SetPanjang( const Value: double); begin if Value <= 0 then begin showMessage('Panjang harus lebih dari 0'); persegiPanjang.Panjang := 1; end else persegiPanjang.Panjang := Value; end; end.
− Berikutnya kita lakukan uji coba dengan menggunakan FormTest
Rename form dari Form1 menjadi formTest
Letakkan 6 instance dari TLabel ke atas form, 2 TEdit, dan 1 TButton
Tampilan secara teks dari form tersebut adalah : object formTest: TformTest Left = 381 Top = 286 Width = 381 Height = 170 Caption = 'Test Persegi Panjang' Color = clBtnFace Font.Charset = ANSI_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [fsBold] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object Label1: TLabel Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 39
Left = 20 Top = 31 Width = 46 Height = 13 Caption = 'Panjang' end object Label2: TLabel Left = 20 Top = 55 Width = 32 Height = 13 Caption = 'Lebar' end object Label3: TLabel Left = 192 Top = 32 Width = 91 Height = 13 Caption = 'Luasnya adalah ' end object lblLuas: TLabel Left = 292 Top = 32 Width = 7 Height = 13 Caption = '1' end object Label4: TLabel Left = 192 Top = 60 Width = 61 Height = 13 Caption = 'Kelilingnya' end object lblKeliling: TLabel Left = 292 Top = 60 Width = 7 Height = 13 Caption = '4' end object btnTest: TButton Left = 20 Top = 88 Width = 141 Height = 25 Caption = 'Buat Persegi Panjang' TabOrder = 0 OnClick = btnTestClick end object edPanjang: TEdit Left = 76 Top = 28 Width = 81 Height = 21 TabOrder = 1 Text = '1' Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 40
end object edLebar: TEdit Left = 76 Top = 52 Width = 81 Height = 21 TabOrder = 2 Text = '1' end end
− Pastikan isi dari form test di atas adalah sebagai berikut : unit TestForm; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TformTest = class(TForm) btnTest: TButton; edPanjang: TEdit; Label1: TLabel; edLebar: TEdit; Label2: TLabel; Label3: TLabel; lblLuas: TLabel; Label4: TLabel; lblKeliling: TLabel; procedure btnTestClick(Sender: TObject); private { Private declarat0ions } public { Public declarations } end; var formTest: TformTest; implementation uses classPersegiPanjangSederhana;
{$R *.dfm} procedure TformTest.btnTestClick(Sender: TObject); var persegiPanjang:TPersegiPanjangSederhana; begin persegiPanjang := TPersegiPanjangSederhana.Create(Self); persegiPanjang.Panjang := StrToFloatDef(edPanjang.Text, 1.0); persegiPanjang.Lebar := StrToFloatDef(edLebar.Text, 1.0);
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 41
lblLuas.Caption := Format('%g', [persegiPanjang.cariLuas]); lblKeliling.Caption := Format('%g', [persegiPanjang.cariKeliling]); persegiPanjang.free; end; end.
− Setelah kita merasa bahwa uji coba terhadap komponen secara dynamic seperti yang kita lakukan di atas telah cukup, sekarang kita
coba untuk menginstal komponen ini ke Palet Komponen. Untuk melakukannya, kita perlu sebuah Package
− Buat sebuah package, Pilih menu File
New Other Package
− Simpan (File Save As) dengan nama PersegiPanjangSederhanaPackage
− Kita perlu membuat ICON untuk komponen ini. Cara yang paling mudah adalah menggunakan Image Editor (Klik menu Tools Image Editor)
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 42
− Buat sebuah Component Resource File (DCR) dengan jalan memilih menu File New Component Resource File (.dcr)
− Pada menu contents, klik kanan dan pilih New Bitmap
− Selalu pilih ukuran 24 x 24 dan VGA (16 Colors) untuk hasil terbaik di semua komputer
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 43
− Rename nama bitmap menjadi nama komponen yaitu TPERSEGIPANJANGSEDERHANA (wajib sama!)
− Double klik pada TPERSEGIPANJANGSEDERHANA dan gambar bitmap untuk komponen ini. Perbesar tampilannya dengan menekan Ctrl + I atau melakukan Zoom In pada menu View
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 44
− Simpan DCR ini PERSIS SAMA dengan nama unit komponennya, yaitu classPersegiPanjangSederhana.dcr
Jika nama komponennya TAbc, maka nama bitmap harus TABC Jika nama unitnya UNITABC.PAS, maka nama file DCRnya harus UNITABC.DCR
− Kembali pada window PACKAGE, tekan tombol Add
− Tekan tombol Browse dan pilih classPersegiPanjangSederhana.pas
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 45
Secara otomatis classPersegiPanjang.dcr akan otomatis ditambahkan.
− Lakukan hal yang sama untuk classBangunDatar.pas dan classPersegiPanjang.pas, lalu tekan tombol Compile
Setelah menekan tombol Compile, maka akan tampil konfirmasi sebagai berikut:
− Tekan tombol install, dan tekan OK
− Selesai, hasilnya bisa dilihat pada palet komponen, pada Page Wisnu Widiarta
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 46
Berikutnya kita bisa melakukan uji coba pada FormTest seperti kita lihat pada gamber berikut:
Jika kita memberi nilai negatif pada property Lebar, maka akan muncul pesan bahwa Lebar harus lebih dari 0, dan property Lebar ini akan diberi nilai 1. Hal yang sama berlaku untuk property Panjang. Sebagian besar upaya untuk membuat komponen lebih kurang seperti pada langkah-langkah di atas. Berikutnya kita akan lihat pembuatan komponen-komponen lainnya sebagai bahan latihan. Beberapa materi dan informasi baru akan disertakan setahap demi setahap.
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 47
6 Contoh Komponen-Komponen 6.1 Komponen yang Terhubung ke Basisdata 6.1.1 TWWDBNavigator Ketika membuat aplikasi basisdata, kita sering menggunakan komponen data aware, yang biasanya terletak pada palet komponen bagian Data Control. Salah satu komponen yang paling sering digunakan adalah TDBNavigator, digunakan untuk menavigasi ketika kita akan memanipulasi suatu tabel. Waktu saya menggunakan komponen ini, terkadang ingin sekali bisa mengganti icon yang ada dengan icon yang saya miliki sendiri. Kadang pula saya menginginkan komponen navigasi tersebut dapat memiliki Caption sehingga lebih memudahkan bagi pengguna dalam menggunakan komponen tersebut. Dengan berbekal nekad dan tekad bulat, akhirnya saya memberanikan diri untuk mempelajari kode program TDBNavigator, dan berusaha memodifikasinya. Tentu saja hasilnya masih bisa untuk disempurnakan. Idenya adalah sebagai berikut:
− Membuat TDBNavigator yang bisa diganti-ganti iconnya − Bisa diberi Caption, dalam bahasa Indonesia maupun bahasa Inggris − Caption bisa muncul bisa tidak, seperti halnya dengan icon − Ketika menekan tombol tambah atau hapus, harus ada event yang tertrigger sebelum perintah insert atau delete dilakukan ke tabel (karena event OnClick pada TDBNavigator bawaan Delphi terpicu setelah perintah tersebut dilakukan. Dan terkadang, kita perlu melakukan sesuatu sebelum benar-benar menghapus atau menambah data. Misalnya untuk memeriksa apakah boleh menghapus atau menambah data)
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 48
Kita lihat pada gambar sebelumnya, enam komponen navigasi di atas menunjukkan: 1. Navigator berbahasa Indonesia 2. Navigator berbahasa Inggris 3. Navigator tanpa caption, hanya icon 4. Navigator dengan caption dan icon, posisi caption di sebelah kanan 5. Navigator dengan caption dan icon, posisi caption di sebelah bawah 6. Navigator bawaan Delphi (TDBNavigator)
Berikut ini adalah listing program dari TWWDBNavigator:
unit classWWDBNavigator;
{********************************************************************* * Nama program : WWDBNavigator * * Deskripsi : Membuat komponen yang mirip dengan DBNavigator * * dilengkapi dengan Caption dan Glyph sekaligus * * Tanggal : 14 September 2002 * * Revisi akhir : 24 Oktober 2005 * * Programmer : Wisnu Widiarta * * * **********************************************************************}
interface uses Windows, Messages, SysUtils, Classes, Controls, ExtCtrls, Buttons, Dialogs, Variants, ImgList, Db; type TWWBtnKind = (wbkFirst, wbkPrior, wbkNext, wbkLast, wbkInsert, wbkDelete, wbkEdit, wbkPost, wbkCancel, wbkRefresh); { TWWBtnKind merupakan tipe enumerasi yang mewakili fungsi masingmasing tombol }
TBtnNavigator = array[TWWBtnKind] of TSpeedButton; { array yang terdiri dari TSpeedButton untuk navigasi } TVisibleButtons = set of TWWBtnKind; { himpunan tombol yang akan dimunculkan } TNavigatorEventClick = procedure (Sender:TObject; wbtnKind:TWWBtnKind) of Object ; Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 49
{ event yang akan ditrigger ketika tombol diklik } TWWDBNavigator = class; { forward declaration, untuk menunjukkan bahwa TWWDBNavigator adalah sebuah kelas } { TWWDataLink } TWWDataLink = class(TDataLink) private FNavigator: TWWDBNavigator; protected procedure EditingChanged; override ; procedure DataSetChanged; override ; procedure ActiveChanged; override ; public constructor Create(ANav: TWWDBNavigator); destructor Destroy; override ; end; { kelas TDataLink merupakan kelas pembantu yang digunakan objek untuk database agar terbentuk koordinasi antara aksi pada TDataSource dan TDataSet, dan tanggap untuk event data } { TWWDBnavigator } TWWDBNavigator = class(TPanel) private { Private declarations } FBtnNavigators:TBtnNavigator; { tombol yang dipakai } FButtonHeight:integer; { tinggi masing-masing tombol } FButtonWidth:integer; { lebar masing-masing tombol } FCaptions:TStrings; { caption untuk masing-masing tombol } FConfirmDelete:Boolean; { apakah ada konfirmasi ketika akan menghapus data } FDataLink:TWWDataLink; { untuk mengatur data link } FDeleteRecordQuestion: String ; { pertanyaan untuk konfirmasi ketika akan menghapus } FHeight:integer; { tinggi panel tempat tombol } FHints:TStrings; { Tool tip untuk masing-masing tombol } FImageChangeLink: TChangeLink; { Perubahan pada gambar } FImages:TCustomImageList; { Kumpulan gambar / glyph untuk icon } FLayout:TButtonLayout; { layout dari masing-masing tombol } FOnNavigatorClick:TNavigatorEventClick; { event yang akan dipicu } FWidth:integer; { lebar panel } FVisibleButtons:TVisibleButtons; { tombol yang tampil } FFlat: boolean; { apakah tombol bersifat flat atau tidak } FOnBeforeDatabaseEvent: TNavigatorEventClick; { event sebelum aksi database dilakukan } FIndonesianLanguage: boolean; { apakah menggunakan bahasa Indonesia / Inggris } FCaptionEnabled: boolean; { apakah caption digunakan atau tidak } procedure ImageListChange(Sender: TObject); { ketika gambar diubah } Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 50
procedure ClearButton; { menghapus semua tombol } procedure CMEnabledChanged( var Message : TMessage); message CM_ENABLEDCHANGED; {ketika enabled berubah } procedure DoNavigatorClick(Sender:TObject; btnKind:TWWBtnKind); { prosedur untuk menjalankan event } procedure DoNavigatorResize(Sender:TObject); { prosedur ketika navigator berubah ukuran } procedure RedrawButton; { menggambar ulang tombol } procedure SetButtonHeight(aHeight:integer); { mengatur tinggi tombol
} procedure SetButtonWidth(aWidth:integer); { mengatur lebar tombol } procedure SetCaptions(value:TStrings); { mengatur caption tombol } procedure SetDeleteRecordQuestion(aQuestion: String ); { mengatur pertanyaan ketika akan menghapus } procedure SetHeight(aHeight:integer); { mengatur tinggi panel } procedure SetHints(value:TStrings); { mengatur tool tip } procedure SetImages(Value: TCustomImageList); { mengatur icon } procedure SetLayout(aLayout:TButtonLayout); { mengatur layout } procedure SetDataSource(aDataSource:TDataSource); { mengatur DataSource } procedure SetVisibleButtons(value:TVisibleButtons); { mengatur tombol yang muncul } procedure SetWidth(aWidth:integer); { mengatur lebar panel } function VisibleButtonCount:integer; { menghitung jumlah tombol yang tampil } function GetDataSource:TDataSource; { menentukan data source } procedure OnButtonClick(Sender:TObject); { event ketika tombol diklik } procedure OnCaptionsChange(Sender:TObject); { ketika caption diubah } procedure OnHintsChange(Sender:TObject); { ketika tool tip diubah } procedure SetFlat( const Value: boolean); { mengatur tombol flat atau tidak } procedure SetIndonesianLanguage( const Value: boolean); { mengatur bahasa } procedure SetCaptionEnabled( const Value: boolean); { mengatur caption akan dimunculkan atau tidak } protected { Protected declarations } procedure ActiveChanged; procedure EditingChanged; procedure DataChanged; procedure Notification(AComponent: TComponent; Operation: TOperation); override ; { keempat prosedur di atas diadaptasi dari versi TDBNavigator untuk menangkap perubahan data dan Notification (turunan dari TComponent) } public { Public declarations } constructor Create(AOwner: TComponent); override ; destructor Destroy; override ; published Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 51
{ Published declarations } property ButtonHeight : integer read FButtonHeight write SetButtonHeight; property ButtonWidth : integer read FButtonWidth write SetButtonWidth; property Caption : TStrings read FCaptions write SetCaptions; property ConfirmDelete : boolean read FConfirmDelete write FConfirmDelete; property DataSource : TDataSource read GetDataSource write SetDataSource; property DeleteRecordQuestion : String read FDeleteRecordQuestion write SetDeleteRecordQuestion; property Flat : boolean read FFlat write SetFlat; property Height : integer read FHeight write SetHeight; property Hints : TStrings read FHints write SetHints; property Images : TCustomImageList read FImages write SetImages; property Layout : TButtonLayout read FLayout write SetLayout; property VisibleButtons:TVisibleButtons read FVisibleButtons write SetVisibleButtons; property Width : integer read FWidth write SetWidth; property IndonesianLanguage : boolean read FIndonesianLanguage write SetIndonesianLanguage; property CaptionEnabled : boolean read FCaptionEnabled write SetCaptionEnabled; property OnClick : TNavigatorEventClick read FOnNavigatorClick write FOnNavigatorClick; property OnBeforeDatabaseEvent : TNavigatorEventClick read FOnBeforeDatabaseEvent write FOnBeforeDatabaseEvent; { ditrigger sebelum aksi database dilakukan } end; procedure Register ; implementation
uses StdCtrls, classIndonesianDialog { untuk menampilkan konfirmasi berbahasa Indonesia }; };
procedure Register ; begin RegisterComponents('Wisnu RegisterComponents( 'Wisnu Widiarta', Widiarta', [TWWDBNavigator]); end; Constructor TWWDBNavigator.Create(AOwner:TComponent); var i:integer; msg:array[TWWBtnKind] of String ; begin inherited Create(AOwner);
ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] + [csOpaque]; { - Kita tidak ingin ada komponen yang bisa diletakkan di atas Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 52
DBNavigator, jadi control stylenya kita hilangkan yaitu csAcceptsControls - csSetCaption kita hilangkan karena kita tidak ingin nama komponen menjadi caption - csOpaque kita masukkan karena kita ingin control memenuhi kotak client } FHints := TStringList.Create; if Fhints.Count = 0 then with FHints do begin Add('First Add('First record'); record'); Add('Previous Add('Previous record'); record' ); Add('Next Add('Next record'); record'); Add('Last Add('Last record'); record'); Add('Insert Add('Insert record'); record'); Add('Delete Add('Delete record'); record'); Add('Edit Add('Edit record'); record'); Add('Save Add('Save record'); record'); Add('Cancel Add('Cancel record'); record'); Add('Refresh Add('Refresh record'); record'); end; TStringList(FHints).OnChange := OnHintsChange; { melakukan assignment event saat run time } FCaptions := TStringList.Create; if FCaptions.Count = 0 then begin msg[wbkFirst] := 'First' 'First'; ; msg[wbkPrior] := 'Prior' 'Prior'; ; msg[wbkNext] := 'Next' 'Next'; ; msg[wbkLast] := 'Last' 'Last'; ; msg[wbkInsert] := 'Insert' 'Insert'; ; msg[wbkDelete] := 'Delete' 'Delete'; ; msg[wbkPost] := 'Save' 'Save'; ; msg[wbkCancel] := 'Cancel' 'Cancel'; ; msg[wbkRefresh] := 'Refresh' 'Refresh'; ; msg[wbkEdit] := 'Edit' 'Edit'; ; for i:=Ord(Low(FBtnNavigators)) to Ord(High(FBtnNavigators)) do FCaptions.Add(msg[TWWBtnKind(i)]); end; TStringList(FCaptions).OnChange := OnCaptionsChange; for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin FBtnNavigators[TWWBtnKind(i)] := TSpeedButton.Create(Self); with FBtnNavigators[TWWBtnKind(i)] do begin Parent := Self; Left := i * Width; Top := 0; TabStop := False; Tag := i; Caption := FCaptions[i]; Hint := FHints.Strings[i]; Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 53
OnClick := OnButtonClick; end; end; if (csDesigning in ComponentState) then begin FVisibleButtons := [wbkFirst, wbkPrior, wbkNext, wbkLast, wbkInsert, wbkDelete, wbkEdit, wbkPost, wbkCancel, wbkRefresh]; { ketika komponen sedang berada pada form dan dimanipulasi, yang tampak adalah semua tombol } end;
OnResize := DoNavigatorResize; BevelInner := bvNone; BevelOuter := bvNone; FImageChangeLink := TChangeLink.Create; FImageChangeLink.OnChange := ImageListChange; FDataLink := TWWDataLink.Create(Self); FCaptionEnabled := True; end; procedure TWWDBNavigator.ActiveChanged; var I: TWWBtnKind; begin if not (Enabled and FDataLink.Active) then for I := Low(FBtnNavigators) to High(FBtnNavigators) do FBtnNavigators[I].Enabled := False else begin DataChanged; EditingChanged; end; end; procedure TWWDBNavigator.CMEnabledChanged( var Message : TMessage); begin inherited ; if not (csLoading in ComponentState) then ActiveChanged; { csLoading terjadi ketika komponen sedang di-load } end; procedure TWWDBNavigator.DataChanged; var UpEnable, DnEnable: Boolean; begin UpEnable := Enabled and FDataLink.Active and not FDataLink.DataSet.BOF; DnEnable := Enabled and FDataLink.Active and not FDataLink.DataSet.EOF; FBtnNavigators[wbkFirst].Enabled := UpEnable; FBtnNavigators[wbkPrior].Enabled := UpEnable; Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 54
FBtnNavigators[wbkNext].Enabled := DnEnable; FBtnNavigators[wbkLast].Enabled := DnEnable; FBtnNavigators[wbkDelete].Enabled := Enabled and FDataLink.Active and
FDataLink.DataSet.CanModify and not (FDataLink.DataSet.BOF and FDataLink.DataSet.EOF); end; procedure TWWDBNavigator.DoNavigatorClick(Sender:TObject; btnKind:TWWBtnKind); begin if Assigned(FOnNavigatorClick) then FOnNavigatorClick(Self, btnKind); { ketika tombol diklik } end; procedure TWWDBNavigator.EditingChanged; var CanModify: Boolean; begin CanModify := Enabled and FDataLink.Active and FDataLink.DataSet.CanModify; FBtnNavigators[wbkInsert].Enabled := CanModify; FBtnNavigators[wbkEdit].Enabled := CanModify and not FDataLink.Editing; FBtnNavigators[wbkPost].Enabled := CanModify and FDataLink.Editing; FBtnNavigators[wbkCancel].Enabled := CanModify and FDataLink.Editing; FBtnNavigators[wbkRefresh].Enabled := CanModify; end; function TWWDBNavigator.GetDataSource:TDataSource; begin Result := FDataLink.DataSource; end; procedure TWWDBNavigator.SetDataSource(aDataSource:TDataSource); begin FDataLink.DataSource := aDataSource; if not (csLoading in ComponentState) then ActiveChanged; if aDataSource <> nil then aDataSource.FreeNotification(Self); end; procedure TWWDBNavigator.ImageListChange(Sender: TObject); begin ClearButton; RedrawButton; { ketika image icon diubah, buang semua gambar, lalu gambar ulang } end; procedure TWWDBNavigator.Notification(AComponent: TComponent; Operation: TOperation); begin inherited Notification(AComponent, Operation); if (Operation = opRemove) and (FDataLink <> nil) and (AComponent = DataSource) then Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 55
DataSource := nil; end; procedure TWWDBNavigator.OnButtonClick(Sender:TObject); var index:TWWBtnKind; begin Self.SetFocus; index := TWWBtnKind((Sender as TSpeedButton).Tag); if (DataSource <> nil) and (DataSource.State <> dsInactive) then begin if not (csDesigning in ComponentState) and Assigned(FOnBeforeDatabaseEvent) then FOnBeforeDatabaseEvent(Self, index); { picu event OnBeforeDatabaseEvent sebelum melakukan suatu aksi apapun } with DataSource.DataSet do begin case Index of wbkPrior: Prior; wbkNext: Next; wbkFirst: First; wbkLast: Last; wbkInsert: Insert; wbkEdit: Edit; wbkCancel: Cancel; wbkPost: Post; wbkRefresh: Refresh; wbkDelete: if FIndonesianLanguage then begin if (not FConfirmDelete) or
(TIndonesianDialog.MessageDlg(FDeleteRecordQuestion, mtConfirmation, mbOKCancel) <> mrCancel) then Delete; end else begin if (not FConfirmDelete) or (MessageDlg(FDeleteRecordQuestion, mtConfirmation, mbOKCancel, 0) <> mrCancel) then Delete; end; end; end; end; if not (csDesigning in ComponentState) and Assigned(FOnNavigatorClick) then DoNavigatorClick(Self, index); { baru lakukan aksi ketika diklik } end; procedure TWWDBNavigator.OnHintsChange(Sender:TObject); var i:integer; Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 56
begin for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin with FBtnNavigators[TWWBtnKind(i)] do if i < FHints.Count then Hint := FHints.Strings[i] else Hint := '' ''; ; end; end; procedure TWWDBNavigator.OnCaptionsChange(Sender:TObject); var i:integer; begin for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin with FBtnNavigators[TWWBtnKind(i)] do if i < FCaptions.Count then begin if FCaptionEnabled then Caption := FCaptions.Strings[i] else Caption := '' ''; ; end else Caption := '' ''; ; end; end; function TWWDBNavigator.VisibleButtonCount:integer; var i:TWWBtnKind; begin Result := 0; for i:=wbkFirst to wbkRefresh do if i in FVisibleButtons then Inc(Result); end; procedure TWWDBNavigator.SetButtonWidth(aWidth:integer); var i, leftPos:integer; begin if VisibleButtonCount > 0 then aWidth := inherited Width div VisibleButtonCount else aWidth := inherited Width div 10 10; ; if aWidth < 1 then Raise Exception.Create( Exception.Create('TWWDBNavigator: 'TWWDBNavigator: minimum value for this property is 1.') 1.' ) else begin leftPos := 0; for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 57
with FBtnNavigators[TWWBtnKind(i)] do begin Visible := TWWBtnKind(i) in FVisibleButtons; if Visible then begin Width := aWidth;
Left := LeftPos; LeftPos := LeftPos + aWidth; end; end; end;
FButtonWidth := aWidth; if Self.VisibleButtonCount > 0 then Width := FBtnNavigators[TWWBtnKind(0 FBtnNavigators[TWWBtnKind( 0)].Width * Self.VisibleButtonCount; end; end; procedure TWWDBNavigator.SetButtonHeight(aHeight:integer); var i:integer; begin if aHeight < 1 then Raise Exception.Create( Exception.Create('TWWDBNavigator: 'TWWDBNavigator: minimum value for this property is 1.') 1.' ) else begin for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin with FBtnNavigators[TWWBtnKind(i)] do begin Visible := TWWBtnKind(i) in FVisibleButtons; Height := aHeight; end; end;
FButtonHeight := aHeight; Height := aHeight; end; end; procedure TWWDBNavigator.SetCaptions(value:TStrings); var i:integer; begin FCaptions.Assign(value); if value <> nil then begin for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin with FBtnNavigators[TWWBtnKind(i)] do if i < FCaptions.Count then Caption := FCaptions.Strings[i] else Caption := '' ''; ; Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 58
end; end; end; procedure TWWDBNavigator.SetDeleteRecordQuestion(aQuestion: String ); begin if Trim(aQuestion) = '' then begin if ConfirmDelete = True then FDeleteRecordQuestion := 'Do you want to delete this record?' else FDeleteRecordQuestion := '' ''; ; end else FDeleteRecordQuestion := aQuestion; end; procedure TWWDBNavigator.SetHints(value:TStrings); var i:integer; begin FHints.Assign(value); if value <> nil then begin for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin with FBtnNavigators[TWWBtnKind(i)] do if i < FHints.Count then Hint := FHints.Strings[i] else Hint := '' ''; ; end; end; end; procedure TWWDBNavigator.SetWidth(aWidth:integer); var i, leftPos:integer; begin if aWidth < 1 then Exception.Create('TWWDBNavigator: 'TWWDBNavigator: minimum value for this Raise Exception.Create( property is 1.') 1.' ) else begin leftPos := 0; for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin with FBtnNavigators[TWWBtnKind(i)] do begin Visible := TWWBtnKind(i) in FVisibleButtons; if Visible then begin Left := leftPos; Width := aWidth div Self.VisibleButtonCount; leftPos := leftPos + Width; end; Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 59
end; end; if Self.VisibleButtonCount > 0 then begin FButtonWidth := aWidth div Self.VisibleButtonCount; FWidth := FButtonWidth * Self.VisibleButtonCount; inherited width := FWidth; end else begin inherited width := aWidth; FWidth := aWidth; end; end; end; procedure TWWDBNavigator.SetHeight(aHeight:integer); var i:integer; begin if aHeight < 1 then Raise Exception.Create( Exception.Create('TWWDBNavigator: 'TWWDBNavigator: minimum value for this property is 1.') 1.' ) else begin for i:=Ord(wbkFirst) to Ord(wbkRefresh) do with FBtnNavigators[TWWBtnKind(i)] do begin Visible := TWWBtnKind(i) in FVisibleButtons; Height := aHeight; end;
FHeight := aHeight; FButtonHeight := aHeight; inherited Height := aHeight; end; end; procedure TWWDBNavigator.SetVisibleButtons(value:TVisibleButtons); var i, leftPos, shouldBeVisibleCount:integer; begin leftPos := 0; FVisibleButtons := value;
shouldBeVisibleCount := 0; for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin if TWWBtnKind(i) in value then inc(shouldBeVisibleCount); end; for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin with FBtnNavigators[TWWBtnKind(i)] do Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 60
begin
Visible := TWWBtnKind(i) in value; if Visible then begin Width := inherited width div shouldBeVisibleCount; Height := FButtonHeight; Left := LeftPos; LeftPos := LeftPos + FButtonWidth; if (csDesigning in ComponentState) then begin Top := 0; BringToFront; end; end else begin if (csDesigning in ComponentState) then begin Top := FButtonHeight; SendToBack; end; end; end; end; if Self.VisibleButtonCount > 0 then Width := ( inherited width div shouldBeVisibleCount) * shouldBeVisibleCount else inherited Width := FButtonWidth; if Not (csDesigning in ComponentState) then Invalidate; end; procedure TWWDBNavigator.RedrawButton; var i:integer; begin if Assigned(FImages) then begin i := 0; while (i <= ord(wbkRefresh)) and (i < FImages.Count) do begin FImages.GetBitmap(i, FBtnNavigators[TWWBtnKind(i)].Glyph); Inc(i); end; Self.Invalidate; end else ClearButton; end; procedure TWWDBNavigator.ClearButton; var Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 61
i:integer; begin i := 0; while (i <= ord(wbkRefresh)) do begin FBtnNavigators[TWWBtnKind(i)].Glyph := Nil; Inc(i); end; Invalidate; end; procedure TWWDBNavigator.SetImages(Value: TCustomImageList); begin if FImages <> nil then FImages.UnRegisterChanges(FImageChangeLink); FImages := Value; if FImages <> nil then begin ClearButton; FImages.RegisterChanges(FImageChangeLink); FImages.FreeNotification(Self); RedrawButton; end else ClearButton; end; procedure TWWDBNavigator.SetLayout(aLayout:TButtonLayout); var i:TWWBtnKind; begin for i:=Low(FBtnNavigators) to High(FBtnNavigators) do FBtnNavigators[i].Layout := aLayout; FLayout := aLayout; end; procedure TWWDBNavigator.DoNavigatorResize(Sender:TObject); vaR leftPos, i:integer; begin Width := inherited Width; Height:= inherited Height;
leftPos := 0; for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin with FBtnNavigators[TWWBtnKind(i)] do begin Visible := TWWBtnKind(i) in FVisibleButtons; if Visible then begin Width := FButtonWidth; Height := FButtonHeight;
Left := LeftPos; LeftPos := LeftPos + FButtonWidth; end Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 62
end; end; end; destructor TWWDBNavigator.Destroy; var i:integer; begin for i:=Ord(wbkFirst) to Ord(wbkRefresh) do FBtnNavigators[TWWBtnKind(i)].Free;
FHints.Free; FCaptions.Free; FDataLink.Free; FDataLink := Nil; inherited Destroy; end;
{ TWWDataLink } constructor TWWDataLink.Create(ANav: TWWDBNavigator); begin inherited Create; FNavigator := ANav; VisualControl := True; end; procedure TWWDataLink.EditingChanged; begin if FNavigator <> nil then FNavigator.EditingChanged; end; procedure TWWDataLink.DataSetChanged; begin if FNavigator <> nil then FNavigator.DataChanged; end; procedure TWWDataLink.ActiveChanged; begin if FNavigator <> nil then FNavigator.ActiveChanged; end; destructor TWWDataLink.Destroy; begin FNavigator := nil; inherited Destroy; end; procedure TWWDBNavigator.SetFlat( const Value: boolean); var i:TWWBtnKind; begin FFlat := Value; for i:=Low(FBtnNavigators) to High(FBtnNavigators) do FBtnNavigators[i].Flat := Value; end; procedure TWWDBNavigator.SetIndonesianLanguage( Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 63
const Value: boolean); var msg:array[TWWBtnKind] of String ; newHints:TStringList; i:integer; begin FIndonesianLanguage := Value;
newHints := TStringList.Create; if value then begin with newHints do begin Add('Awal Add('Awal data'); data'); Add('Data Add('Data sebelumnya'); sebelumnya' ); Add('Data Add('Data berikutnya'); berikutnya' ); Add('Akhir Add('Akhir data'); data'); Add('Tambah Add('Tambah data'); data'); Add('Hapus Add('Hapus data'); data'); Add('Edit Add('Edit data'); data'); Add('Simpan Add('Simpan data'); data'); Add('Batalkan Add('Batalkan perubahan'); perubahan'); Add('Baca Add('Baca ulang data'); data' ); end; SetHints(newHints); msg[wbkFirst] := 'Awal' 'Awal'; ; msg[wbkPrior] := 'Maju' 'Maju'; ; msg[wbkNext] := 'Mundur' 'Mundur'; ; msg[wbkLast] := 'Akhir' 'Akhir'; ; msg[wbkInsert] := 'Tambah' 'Tambah'; ; msg[wbkDelete] := 'Hapus' 'Hapus'; ; msg[wbkPost] := 'Simpan' 'Simpan'; ; msg[wbkCancel] := 'Batal' 'Batal'; ; msg[wbkRefresh] := 'Baca Ulang'; Ulang'; msg[wbkEdit] := 'Edit' 'Edit'; ; end else begin with newHints do begin Add('First Add('First record'); record'); Add('Previous Add('Previous record'); record' ); Add('Next Add('Next record'); record'); Add('Last Add('Last record'); record'); Add('Insert Add('Insert record'); record'); Add('Delete Add('Delete record'); record'); Add('Edit Add('Edit record'); record'); Add('Save Add('Save record'); record'); Add('Cancel Add('Cancel record'); record'); Add('Refresh Add('Refresh record'); record'); end;
SetHints(newHints); msg[wbkFirst] := 'First' 'First'; ; Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 64
msg[wbkPrior] := 'Prior' 'Prior'; ; msg[wbkNext] := 'Next' 'Next'; ; msg[wbkLast] := 'Last' 'Last'; ; msg[wbkInsert] := 'Insert' 'Insert'; ; msg[wbkDelete] := 'Delete' 'Delete'; ; msg[wbkPost] := 'Save' 'Save'; ; msg[wbkCancel] := 'Cancel' 'Cancel'; ; msg[wbkRefresh] := 'Refresh' 'Refresh'; ; msg[wbkEdit] := 'Edit' 'Edit'; ; end;
FCaptions.Clear; if FCaptionEnabled then begin for i:=Ord(Low(FBtnNavigators)) to Ord(High(FBtnNavigators)) do
FCaptions.Add(msg[TWWBtnKind(i)]); end; end; procedure TWWDBNavigator.SetCaptionEnabled( const Value: boolean); begin FCaptionEnabled := Value; if Value = False then FCaptions.Clear else begin if FCaptions.Count = 0 then SetIndonesianLanguage(FIndonesianLanguage); end; end; end.
Bagaimana Cara Membuat Event? Membuat event seperti pada contoh di atas sebenarnya cukup mudah. Jika masih belum terlalu jelas dengan contoh di atas, mari kita lihat contoh pembuatan event yang lebih sederhana. Event sebenarnya merupakan pointer ke method / prosedure. Pada contoh unit classPersegiPanjang, misalkan kita akan membuat event SebelumPanjangBerubah, yang akan terpicu sebelum panjang persegi panjang diubah. Pertama kita harus membuat tipe data untuk event yang akan ditrigger, dan parameter yang akan muncul pada event tersebut. Misal kita hanya akan mengirimkan objek persegi panjang yang dibuat dan panjangnya. Maka kita membuat signature dari event yang akan kita buat terdiri atas Sender dengan tipe
TObject.
TPersegiPanjangEvent = procedure (Sender:TObject; Panjang:double) of Object ;
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 65
Berikutnya kita perlu variabel private yang tipenya
TPersegiPanjangEvent
dan
membuat satu property yang namanya akan muncul di Event pada Object Inspector. published property SebelumPanjangBerubah:TPersegiPanjangEvent read FPersegiPanjangEvent write FPersegiPanjangEvent;
Berikutnya kita perlu memanggil event ini, persis sebelum panjang diubah. Dengan catatan kalau programmer yang menggunakan komponen kita sudah memasukkan kode dalam event SebelumPanjangBerubah. Jika tidak, tidak usah dipanggil. procedure TPersegiPanjang.SetPanjang( const Value: double); begin if Assigned(FPersegiPanjangEvent) then FPersegiPanjangEvent(Self, Value); FPanjang := Value; end;
Pada saat digunakan pada formTest, contohnya adalah sebagai berikut : begin
pp := TPersegiPanjang.Create(1 TPersegiPanjang.Create( 1, 1); pp.SebelumPanjangBerubah := Self.TestEvent; pp.Panjang := 10 10; ; pp.Free; end; procedure TformTest.TestEvent(Sender: TObject; Panjang: double); begin showMessage('Panjang showMessage( 'Panjang akan diubah menjadi ' + VarToStr(Panjang)); end;
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 66
7 Referensi [Budd] Timothy Budd, An Introduction to Object-Oriented Programming, AddisonWesley, 1991 [Cornell] Gary Cornell and Cay S. Horstmann, Core Java, SunSoft Press A Prentice Hall Title, 1996 [Deitel] Harvey M. Deitel, Paul J. Deitel, C++ How to Program, Deitel & Associates, Inc, 1998 [Horstmann], Cay S Horstmann, Mastering Object Oriented Design in C++, John Wiley & Sons, Inc., 1995 [Stroustrup], Bjarne Stroustrup, What is ‘‘ObjectOriented Programming’’? (1991 revised version), 1991
[Teixeira], Steve Teixeira, Xavier Pacheco, Borland® Delphi™ 6 Developer’s Guide
Membuat Komponen Sendiri dengan dengan Delphi – Wisnu Widiarta Halaman 67