Die meisten HotPDF-Beispiele platzieren eine Komponente zur Entwurfszeit auf einem Formular. Das ist für Demos bequem, Produktionscode muss die PDF-Komponente aber manchmal nur für einen bestimmten Exportvorgang erstellen. Dynamische Erstellung ist nützlich in Servicemodulen, Report-Helfern, Batchjobs und Formularen, in denen die Komponente nicht während der gesamten Formularlebensdauer existieren soll.
Das grundlegende C++Builder-Muster besteht darin, eine THotPDF-Instanz anzulegen, Ausgabedatei und Dokumentoptionen zu konfigurieren, das PDF zu erzeugen und die Komponente nach Abschluss des Vorgangs freizugeben. Das folgende Beispiel zeigt den minimalen Ablauf in einem 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(); } |
Ownership und Aufräumen
Der Konstruktor erhält this als Owner, sodass das Formular die Komponente bereinigen kann, falls sie am Leben bleibt. In diesem kurzen Beispiel wird das Objekt nach EndDoc auch ausdrücklich freigegeben. In realem Code sollte der Cleanup-Pfad ausnahmesicher sein: Wenn die PDF-Erzeugung fehlschlagen kann, kapseln Sie die Arbeit in einem try/__finally-Block oder verwenden Sie einen kleinen RAII-Helfer, damit Free() trotzdem ausgeführt wird.
Rufen Sie nach Free() keine Methoden der Komponente mehr auf, und speichern Sie den Pointer nicht in einem größeren Gültigkeitsbereich, sofern nicht ein anderer Teil des Formulars wirklich den Lebenszyklus besitzt. Eine lokale Variable ist für einmalige PDF-Exporte meist die einfachste Wahl.
Hinweise zur Projekteinrichtung
Das Projekt muss die HotPDF-Header, Bibliotheken sowie Design- und Runtime-Packages finden können. Fügen Sie das HotPDF-Include-Verzeichnis dem C++-Include-Pfad und das Bibliotheksverzeichnis dem Linker-Suchpfad hinzu. Wenn das Projekt HPDFDoc linkt, behalten Sie Package- und Unit-Namen unverändert, damit C++Builder die generierten Header auflösen kann.
Vor der Auslieferung
- Verwenden Sie einen absoluten oder validierten Ausgabepfad, wenn Dateien außerhalb eines Demo-Ordners erzeugt werden.
- Rufen Sie
BeginDocundEndDocin ausgeglichenen Paaren auf. - Öffnen Sie das erzeugte PDF in mindestens einem externen Viewer, nicht nur mit
AutoLaunch. - Protokollieren Sie Erzeugungsfehler, damit Support Pfad-, Berechtigungs-, Font- und PDF-Rendering-Probleme unterscheiden kann.
Ausnahmesichere Struktur
Das Beispiel hält den Code kompakt, aber eine echte Exportroutine sollte Ausnahmen zwischen Allocation und Cleanup behandeln. PDF-Erzeugung kann fehlschlagen, weil der Ausgabeordner schreibgeschützt ist, ein Font nicht aufgelöst werden kann, ein Stream zu früh geschlossen wird oder Benutzerdaten einen unerwarteten Wert enthalten. Der Cleanup-Pfad darf nicht vom Erfolg jedes Zeichenaufrufs abhängen.
Ein praktischer Ansatz ist, die Komponente unmittelbar vor dem Export zu erstellen und sie in einem garantierten Cleanup-Block freizugeben. So ist die Komponentenlebensdauer an genau einen PDF-Job gebunden. Wenn die Anwendung viele Dokumente nacheinander erzeugt, verringert dieses Muster außerdem das Risiko, dass Zustand von einem Dokument in das nächste gelangt.
Entwurfszeit- gegenüber Laufzeitkomponenten
Eine Entwurfszeitkomponente ist einfacher, wenn ein Formular einen vorhersehbaren Exportablauf besitzt. Eine Laufzeitkomponente ist besser, wenn die Anwendung mehrere temporäre Exporter benötigt, Einstellungen dynamisch wählt oder Exportcode aus einer Hilfsklasse statt aus einem Formular ausführt. Die API-Aufrufe sind gleich; der Unterschied ist nur, wem das Objekt gehört und wie lange es lebt.
Vermeiden Sie in Server- oder Batchcode die Abhängigkeit von AutoLaunch. Erzeugen Sie die Datei, prüfen Sie ihre Existenz, protokollieren Sie den Ausgabepfad und lassen Sie den aufrufenden Workflow entscheiden, ob ein Viewer geöffnet werden soll.