Meletakkan THotPDF di atas form pada saat desain baik untuk prototipe cepat, tetapi itu mengikat komponen dengan lifetime form, yang jarang diinginkan kode produksi. Generator laporan yang berjalan sekali per klik tombol, thread layanan yang mengekspor batch semalam, kelas helper yang sama sekali tidak memiliki form: dalam setiap situasi tersebut Anda ingin komponen ada persis selama durasi satu pekerjaan PDF lalu menghilang. Itu berarti alokasi runtime, dan itu mengubah dua hal yang perlu dipahami sebelum menulis baris pertama: siapa yang memiliki objek, dan bagaimana pembersihan berjalan ketika sesuatu berjalan salah
Semantik owner di VCL
Setiap konstruktor komponen VCL mengambil parameter Owner bertipe TComponent*. Melewatkan this (form) mendaftarkan objek baru dengan daftar komponen yang dimiliki form, sehingga jika form dihancurkan sementara komponen masih hidup, VCL membebaskannya secara otomatis. Melewatkan nullptr berarti tidak ada owner: Anda mengambil tanggung jawab penuh atas pointer, dan tidak ada yang akan membersihkannya jika exception membuka stack sebelum delete eksplisit Anda
Untuk ekspor sekali jalan yang selesai dalam satu fungsi, pilihan mana pun berhasil, tetapi keduanya memiliki mode kegagalan yang berbeda. Dengan this sebagai owner, kebocoran tidak mungkin terjadi selama form akhirnya ditutup; dengan nullptr, pointer harus mencapai blok __finally. Dalam praktiknya, pola nullptr plus __finally sedikit lebih bersih untuk objek berumur pendek karena membuat batas lifetime terlihat sekilas dan menghindari form mengumpulkan objek yang dimiliki yang dimaksudkan bersifat sementara
Struktur yang aman dari exception
Pembuatan PDF dapat gagal karena alasan yang tidak ada hubungannya dengan API: direktori output bersifat read-only, file font hilang, stream mengalir prematur, atau data yang disediakan pemanggil melebihi batas panjang. Apa pun penyebabnya, jalur pembersihan harus berjalan. Cara idiomatik C++Builder untuk menjamin itu adalah try/__finally:
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma link "HPDFDoc"
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
THotPDF* Pdf = new THotPDF(nullptr);
try
{
Pdf->FileName = "output.pdf";
Pdf->Compression = cmFlateDecode;
Pdf->FontEmbedding = true;
Pdf->BeginDoc();
Pdf->CurrentPage->SetFont("Arial", TFontStyles(), 12);
Pdf->CurrentPage->TextOut(72, 720, 0, L"Hello from C++Builder");
Pdf->EndDoc();
}
__finally
{
delete Pdf;
}
}
Beberapa hal dalam listing tersebut perlu diperhatikan. Owner adalah nullptr, membuat lifetime menjadi eksplisit. Compression dan FontEmbedding diset sebelum BeginDoc: keduanya adalah opsi tingkat dokumen yang HotPDF commit ketika dokumen dibuka, dan menetapkannya setelah itu tidak berpengaruh. TextOut mengambil koordinat dalam poin yang diukur dari sudut kiri-bawah halaman, Y bertambah ke atas; pasangan 72, 720 menempatkan teks di dekat kiri atas halaman berukuran letter dengan margin kiri satu inci. Perintah delete Pdf di blok __finally berjalan baik BeginDoc, drawing, maupun EndDoc memunculkan exception atau tidak
Hindari memanggil metode apa pun pada Pdf setelah delete. Jika pointer disimpan dalam variabel anggota, setel ke nullptr segera setelah penghapusan sehingga akses yang tidak disengaja nanti menghasilkan crash yang bersih alih-alih korupsi yang diam-diam
Konfigurasi proyek
C++Builder menemukan THotPDF melalui kombinasi include path, library path, dan direktif pragma. Header yang dihasilkan berada di sebelah HPDFDoc.pas di direktori sumber HotPDF; tambahkan direktori itu ke Project > Options > C++ Compiler > Include path. Direktif #pragma link "HPDFDoc" memberitahu linker untuk menarik unit yang dikompilasi tanpa mencantumkannya di file proyek secara manual. Jika Anda menggunakan runtime package alih-alih static linking, instal paket desain dan runtime HotPDF terlebih dahulu; pragma tetap berlaku
Pertahankan nama unit HPDFDoc tidak berubah. C++Builder mendapatkan nama header dari nama unit Pascal, sehingga mengganti nama file atau menggunakan alias path dalam pragma akan merusak pencarian secara diam-diam
Cakupan dan pekerjaan multi-dokumen
Untuk satu ekspor yang dipicu oleh tindakan pengguna, variabel lokal yang dicakup ke handler tombol adalah jawaban yang tepat: dibuat, digunakan, dan dihancurkan dalam satu call frame, dan tujuannya jelas bagi siapa pun yang membaca kode nanti. Alternatif waktu desain dibenarkan ketika form yang sama mendorong alur kerja berkelanjutan, seperti panel print-preview yang membangun ulang dokumen setiap kali pengguna mengubah pengaturan; dalam kasus itu, menjaga komponen tetap hidup dan memanggil BeginDoc/EndDoc secara berulang kurang mengganggu daripada mengalokasikan dan melepaskan objek heap secara berulang
Untuk pekerjaan batch yang menghasilkan banyak dokumen berurutan, mencakup satu THotPDF per dokumen sepadan dengan overhead alokasi. Status tidak terbawa antar dokumen jika tidak ada objek yang membawanya, dan itu adalah satu kelas bug yang kadang-kadang tidak perlu Anda debug. Alokasikan, hasilkan, hapus, ulangi
Satu properti yang muncul di beberapa demo HotPDF adalah AutoLaunch, yang membuka file yang dihasilkan di viewer PDF sistem segera setelah EndDoc. Berguna saat menulis draf pertama tata letak. Dalam produksi, lewati: buka path output secara eksplisit, verifikasi file ada dan memiliki ukuran bukan nol, catat hasilnya, dan biarkan alur kerja pemanggil memutuskan apakah viewer relevan. Dalam pekerjaan batch, AutoLaunch meluncurkan satu jendela viewer per dokumen dan akan memblokir proses di beberapa sistem sambil menunggu viewer ditutup
Komponen THotPDF dan semua panggilan drawing yang ditampilkan di sini adalah bagian dari HotPDF Component untuk Delphi dan C++Builder