Większość przykładów HotPDF umieszcza komponent na formularzu w czasie projektowania. To wygodne w demo, ale kod produkcyjny czasem musi tworzyć komponent PDF tylko dla konkretnej operacji eksportu. Tworzenie dynamiczne jest przydatne w modułach usług, helperach raportów, zadaniach wsadowych i formularzach, w których komponent nie powinien istnieć przez cały czas życia formularza.
Podstawowy wzorzec w C++Builder polega na zaalokowaniu instancji THotPDF, skonfigurowaniu pliku wyjściowego i opcji dokumentu, wygenerowaniu PDF oraz zwolnieniu komponentu po zakończeniu operacji. Przykład poniżej pokazuje minimalny workflow wewnątrz button handler.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include #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* HotPDF1 = new THotPDF(this); HotPDF1->FileName = "HelloWorld.pdf"; HotPDF1->AutoLaunch = true; HotPDF1->BeginDoc(false); HotPDF1->CurrentPage->PrintText( 10, 10, 0, "Hello World!" ); HotPDF1->EndDoc(); HotPDF1->Free(); } |
Własność i sprzątanie
Konstruktor otrzymuje this jako owner, więc formularz może posprzątać komponent, jeśli ten pozostanie żywy. W tym krótkim przykładzie obiekt jest też jawnie zwalniany po EndDoc. W prawdziwym kodzie utrzymuj ścieżkę cleanup exception-safe: jeśli generowanie PDF może się nie udać, opakuj pracę w blok try/__finally albo użyj małego helpera RAII, aby Free() nadal zostało wykonane.
Nie wywołuj metod komponentu po Free() i unikaj przechowywania wskaźnika w szerszym zakresie, chyba że inna część formularza naprawdę zarządza cyklem życia komponentu. Zmienna lokalna jest zwykle najprostszym wyborem dla jednorazowych eksportów PDF.
Uwagi o konfiguracji projektu
Projekt musi móc znaleźć nagłówki, biblioteki oraz pakiety design/runtime HotPDF. Dodaj katalog include HotPDF do ścieżki include C++ oraz katalog bibliotek do ścieżki wyszukiwania linkera. Jeśli projekt linkuje HPDFDoc, zachowaj nazwy pakietów i jednostek bez zmian, aby C++Builder mógł rozwiązać wygenerowane nagłówki.
Przed wydaniem
- Używaj bezwzględnej lub zweryfikowanej ścieżki wyjściowej podczas generowania plików poza folderem demo.
- Wywołuj
BeginDociEndDocw zrównoważonych parach. - Otwórz wygenerowany PDF w co najmniej jednym zewnętrznym viewerze, nie tylko przez
AutoLaunch. - Loguj błędy generowania, aby support mógł rozróżnić problemy ze ścieżką, uprawnieniami, fontem i renderowaniem PDF.
Struktura exception-safe
Przykład utrzymuje kod zwięzły, ale prawdziwa procedura eksportu powinna obsługiwać wyjątki między alokacją i cleanup. Generowanie PDF może się nie udać, bo folder wyjściowy jest tylko do odczytu, font nie może zostać odnaleziony, stream zamknięto za wcześnie albo dane użytkownika zawierają nieoczekiwaną wartość. Ścieżka cleanup nie powinna zależeć od powodzenia każdego wywołania rysowania.
Praktyczne podejście to utworzenie komponentu bezpośrednio przed eksportem, a potem zwolnienie go w gwarantowanym bloku cleanup. Dzięki temu czas życia komponentu jest związany z jednym zadaniem PDF. Jeśli aplikacja generuje wiele dokumentów po kolei, ten wzorzec zmniejsza też ryzyko, że stan jednego dokumentu przecieknie do następnego.
Komponenty design-time kontra runtime
Komponent design-time jest łatwiejszy, gdy jeden formularz ma jeden przewidywalny workflow eksportu. Komponent runtime jest lepszy, gdy aplikacja potrzebuje wielu tymczasowych eksporterów, wybiera ustawienia dynamicznie albo uruchamia kod eksportu z klasy pomocniczej zamiast z formularza. Wywołania API są takie same; różnica polega tylko na tym, kto posiada obiekt i jak długo on żyje.
W kodzie serwerowym lub wsadowym unikaj polegania na AutoLaunch. Wygeneruj plik, sprawdź, czy istnieje, zapisz ścieżkę wyjściową i pozwól workflow wywołującemu zdecydować, czy otworzyć viewer.