html Dynamiczne tworzenie i zwalnianie komponentu HotPDF w C++Builder | losLab Software Development Blog

Artykuł techniczny

Dynamiczne tworzenie i zwalnianie komponentu HotPDF w C++Builder

· Programowanie PDF

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 BeginDoc i EndDoc w 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.