Download - Membuat Komponen Sendiri Dengan Delphi 6
Buat Komponen Delphi Anda Sendiri!
Membuat komponen Delphi secara mudah dan cepat dengan pengenalan Object Oriented Programming
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman i
Daftar Isi
Daftar Isi ............................................................................................................................. i
Sekapur Sirih...................................................................................................................... 1
1 Mengapa Membuat Komponen 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
2 Object Oriented Programming (OOP) ...................................................................... 7 2.1 Apa itu OOP? ................................................................................................................7 2.2 Apa perbedaan OOP dengan Procedural Programming ..........................................8
3 Konsep-konsep Dasar OOP ..................................................................................... 10 3.1 Kelas .............................................................................................................................10 3.2 Enkapsulasi..................................................................................................................11 3.3 Pewarisan.....................................................................................................................12 3.4 Polimorfisme................................................................................................................13
4 Disain dan Implementasi Pemrograman Berorientasi Object dengan Delphi...... 14 4.1 Bermula dari Masalah, Diakhiri dengan Solusi Program.......................................14
4.1.1 Fase Analisis..........................................................................................................................14 4.1.2 Fase Disain ............................................................................................................................14 4.1.3 Fase Implementasi .................................................................................................................15
4.2 Studi Kasus – Menganalisis, Mendisain, dan Mengimplementasikan Kelas.........16 4.2.1 Analisis ..................................................................................................................................16 4.2.2 Disain.....................................................................................................................................17 4.2.3 Implementasi .........................................................................................................................20
5 Membuat Komponen Sederhana ............................................................................. 33 5.1 Langkah-langkah Membuat Komponen...................................................................34
5.1.1 Menentukan Superclass dari Komponen ...............................................................................34 5.1.2 Membuat Komponen Sederhana Langkah demi Langkah .....................................................35
6 Contoh Komponen-Komponen................................................................................ 48 6.1 Komponen yang Terhubung ke Basisdata................................................................48
6.1.1 TWWDBNavigator................................................................................................................48 6.1.2 TWWDBDateTimePicker...................................................... Error! Bookmark not defined.
7 Referensi................................................................................................................... 67
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 1
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 Delphi – Wisnu Widiarta Halaman 2
1 Mengapa Membuat Komponen Sendiri?
1.1 Apa itu komponen?
omponen pada dasarnya adalah objek-objek yang dapat dimanipulasi pada
saat kita merancang suatu program. Komponen Delphi terdiri dari objek-
objek 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 komponen-
komponen 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”.
K
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 3
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 Delphi – Wisnu Widiarta Halaman 4
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 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 Delphi – Wisnu Widiarta Halaman 5
1.3 Apa saja yang perlu diketahui untuk membuat 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 Delphi – Wisnu Widiarta Halaman 6
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, 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 Delphi – Wisnu Widiarta Halaman 7
2 Object Oriented Programming (OOP)
2.1 Apa itu OOP?
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.
O
Kelas Tertinggi
Kelas Terendah
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 8
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 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 Delphi – Wisnu Widiarta Halaman 9
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
data
method
method
data
method
method
data
method
method
Object Oriented Programming
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 10
3 Konsep-konsep Dasar OOP
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
K
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 11
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 Delphi – Wisnu Widiarta Halaman 12
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 Delphi – Wisnu Widiarta Halaman 13
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, namun berbeda
signaturenya (berbeda pada jenis atau jumlah parameternya). Misalnya
method Jalan bisa dibuat lebih dari satu, tergantung tipe data parameternya,
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 merupakan proses
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 14
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 Pemrograman Berorientasi Object dengan Delphi
4.1 Bermula dari Masalah, Diakhiri dengan Solusi Program
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
S
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 15
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 kode-
kode 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 Implementasi
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 16
4.2 Studi 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
− Persegi panjang memiliki atribut 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
− Lingkaran memiliki atribut jari-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
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 17
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 Operasi Atribut
Kelas PersegiPanjang − LuasPersegiPanjang
(menghitung luas persegi
panjang)
− KelilingPersegiPanjang
(menghitung keliling persegi
panjang)
− panjang
− lebar
Kelas Lingkaran − LuasLingkaran (menghitung luas
lingkaran)
− KelilingLingkaran (menghitung
keliling lingkaran)
− jarijari
Kelas Segitiga − LuasSegitiga (menghitung luas
segitiga)
− KelilingSegitiga (menghitung
keliling segitiga)
− sisi1
− sisi2
− sisi3
Segitiga
− Segitiga memiliki atribut 3 sisi 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 masing-masing sisinya
− Keliling dihitung dengan menjumlahkan ketiga sisinya
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 18
Jika kita pisahkan ketiga entitas tersebut, kita akan dapatkan daftar berikut:
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 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
Attribute panjang lebar Method cariLuas cariKeliling
Class PersegiPanjang Attribute jarijari Method cariLuas cariKeliling
Class Lingkaran
Attribute sisiA, sisiB, sisiC Method cariLuas cariKeliling
Class Segitiga
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 19
mengimplementasikan suatu kelas abstrak, maka kelas tersebut harus memiliki
implementasi dari semua operasi abstrak yang ada pada kelas abstrak yang akan
diimplementasikan.
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.
Method cariLuas cariKeliling
Abstract Class BangunDatar
Attribute panjang lebar Method cariLuas cariKeliling
Class PersegiPanjang Attribute jarijari Method cariLuas cariKeliling
Class Lingkaran
Attribute sisiA, sisiB, sisiC Method cariLuas cariKeliling
Class Segitiga
Lambang pewarisan
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 20
4.2.3 Implementasi
Ketika kita jalankan Delphi akan tampak tampilan berikut.
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.
Object Inspector
Object TreeView
Form Designer
Component Palette
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 21
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 Delphi – Wisnu Widiarta Halaman 22
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 TBangunDatar yang merupakan
turunan dari kelas TObject. Kita bisa saja menuliskan class(TObject) pada contoh
di atas dengan class saja. Sebab jika kita hanya memberikan kata class,
secara default kelas tersebut merupakan turunan dari kelas TObject. Untuk
kejelasan, saya sengaja selalu menggunakan TObject untuk semua kelas turunan
dari kelas TObject
− Kata kunci public menunjukkan bahwa function cariLuas dan
cariKeliling dapat diakses semua unit
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 23
− cariLuas dan cariKeliling adalah fungsi yang mengembalikan tipe data
double, dideklarasikan virtual, artinya dapat dioverride atau implementasinya
dapat diubah oleh kelas turunannya, dan dideklarasikan abstract, artinya tidak
ada implementasinya pada kelas TBangunDatar, dan implementasinya diserahkan
pada kelas turunannya
Perbandingan pada
pemrograman Java
(disimpan pada file
BangunDatar.java)
public abstract class BangunDatar extends Object {
public abstract double cariLuas();
public abstract double cariKeliling();
}
− jika kita mengimplementasikan kedua fungsi pada unit classBangunDatar, maka
kita akan mendapatkan pesan kesalahan :
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 Delphi – Wisnu Widiarta Halaman 24
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 Delphi – Wisnu Widiarta Halaman 25
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 Delphi – Wisnu Widiarta Halaman 26
{ 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 Delphi – Wisnu Widiarta Halaman 27
− 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
(disimpan pada file
PersegiPanjang.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; } }
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
Create (tidak seperti pada Java atau C++ yang mengharuskan nama constructor sama
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 Delphi – Wisnu Widiarta Halaman 28
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 29
Versi untuk kelas lingkaran adalah sebagai berikut :
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 30
Versi untuk kelas Segitiga adalah sebagai berikut :
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 31
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 Delphi – Wisnu Widiarta Halaman 32
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('Keliling 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 Delphi – Wisnu Widiarta Halaman 33
5 Membuat Komponen Sederhana
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). 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
K
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 34
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 TComponent
2. yang tidak memiliki window handle (contohnya TPaintBox), superclassnya
adalah TGraphicControl
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 35
3. yang memiliki window handle (contohnya TCheckBox, TComboBox),
superclassnya adalah 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 Delphi – Wisnu Widiarta Halaman 36
− 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 Delphi – Wisnu Widiarta Halaman 37
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 Delphi – Wisnu Widiarta Halaman 38
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 Delphi – Wisnu Widiarta Halaman 39
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 Delphi – Wisnu Widiarta Halaman 40
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 Delphi – Wisnu Widiarta Halaman 41
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 Delphi – Wisnu Widiarta Halaman 42
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 Delphi – Wisnu Widiarta Halaman 43
− 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 Delphi – Wisnu Widiarta Halaman 44
− 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 Delphi – Wisnu Widiarta Halaman 45
− 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 Delphi – Wisnu Widiarta Halaman 46
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 Delphi – Wisnu Widiarta Halaman 47
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 Delphi – Wisnu Widiarta Halaman 48
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 Delphi – Wisnu Widiarta Halaman 49
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 masing-masing 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 Delphi – Wisnu Widiarta Halaman 50
{ 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 Delphi – Wisnu Widiarta Halaman 51
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 Delphi – Wisnu Widiarta Halaman 52
{ 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 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 Delphi – Wisnu Widiarta Halaman 53
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 record'); Add('Previous record'); Add('Next record'); Add('Last record'); Add('Insert record'); Add('Delete record'); Add('Edit record'); Add('Save record'); Add('Cancel record'); Add('Refresh record'); end; TStringList(FHints).OnChange := OnHintsChange; { melakukan assignment event saat run time } FCaptions := TStringList.Create; if FCaptions.Count = 0 then begin msg[wbkFirst] := 'First'; msg[wbkPrior] := 'Prior'; msg[wbkNext] := 'Next'; msg[wbkLast] := 'Last'; msg[wbkInsert] := 'Insert'; msg[wbkDelete] := 'Delete'; msg[wbkPost] := 'Save'; msg[wbkCancel] := 'Cancel'; msg[wbkRefresh] := 'Refresh'; msg[wbkEdit] := '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 Delphi – Wisnu Widiarta Halaman 54
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 Delphi – Wisnu Widiarta Halaman 55
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 Delphi – Wisnu Widiarta Halaman 56
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 Delphi – Wisnu Widiarta Halaman 57
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; if aWidth < 1 then Raise Exception.Create('TWWDBNavigator: minimum value for this property is 1.') else begin leftPos := 0; for i:=Ord(wbkFirst) to Ord(wbkRefresh) do begin
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 58
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)].Width * Self.VisibleButtonCount; end; end; procedure TWWDBNavigator.SetButtonHeight(aHeight:integer); var i:integer; begin if aHeight < 1 then Raise Exception.Create('TWWDBNavigator: minimum value for this property is 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 Delphi – Wisnu Widiarta Halaman 59
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 Raise Exception.Create('TWWDBNavigator: minimum value for this property is 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 Delphi – Wisnu Widiarta Halaman 60
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('TWWDBNavigator: minimum value for this property is 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 Delphi – Wisnu Widiarta Halaman 61
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 Delphi – Wisnu Widiarta Halaman 62
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 Delphi – Wisnu Widiarta Halaman 63
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 Delphi – Wisnu Widiarta Halaman 64
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 data'); Add('Data sebelumnya'); Add('Data berikutnya'); Add('Akhir data'); Add('Tambah data'); Add('Hapus data'); Add('Edit data'); Add('Simpan data'); Add('Batalkan perubahan'); Add('Baca ulang data'); end; SetHints(newHints); msg[wbkFirst] := 'Awal'; msg[wbkPrior] := 'Maju'; msg[wbkNext] := 'Mundur'; msg[wbkLast] := 'Akhir'; msg[wbkInsert] := 'Tambah'; msg[wbkDelete] := 'Hapus'; msg[wbkPost] := 'Simpan'; msg[wbkCancel] := 'Batal'; msg[wbkRefresh] := 'Baca Ulang'; msg[wbkEdit] := 'Edit'; end else begin with newHints do begin Add('First record'); Add('Previous record'); Add('Next record'); Add('Last record'); Add('Insert record'); Add('Delete record'); Add('Edit record'); Add('Save record'); Add('Cancel record'); Add('Refresh record'); end; SetHints(newHints); msg[wbkFirst] := 'First';
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 65
msg[wbkPrior] := 'Prior'; msg[wbkNext] := 'Next'; msg[wbkLast] := 'Last'; msg[wbkInsert] := 'Insert'; msg[wbkDelete] := 'Delete'; msg[wbkPost] := 'Save'; msg[wbkCancel] := 'Cancel'; msg[wbkRefresh] := 'Refresh'; msg[wbkEdit] := '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 Delphi – Wisnu Widiarta Halaman 66
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, 1); pp.SebelumPanjangBerubah := Self.TestEvent; pp.Panjang := 10; pp.Free; end; procedure TformTest.TestEvent(Sender: TObject; Panjang: double); begin showMessage('Panjang akan diubah menjadi ' + VarToStr(Panjang)); end;
Membuat Komponen Sendiri dengan Delphi – Wisnu Widiarta Halaman 67
7 Referensi [Budd] Timothy Budd, An Introduction to Object-Oriented Programming, Addison-
Wesley, 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