Technical Article

Create and free a HotPDF component dynamically in C++Builder

· PDF Programming

Most HotPDF examples place a component on a form at design time. That is convenient for demos, but production code sometimes needs to create the PDF component only for a specific export operation. Dynamic creation is useful in service modules, report helpers, batch jobs, and forms where the component should not live for the entire form lifetime.

The basic C++Builder pattern is to allocate a THotPDF instance, configure the output file and document options, generate the PDF, and release the component when the operation is complete. The example below shows the minimal workflow inside a 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 and cleanup

The constructor receives this as the owner, so the form can clean up the component if it remains alive. In this short example the object is also freed explicitly after EndDoc. In real code, keep the cleanup path exception-safe: if PDF generation can fail, wrap the work in a try/__finally block or use a small RAII helper so Free() still runs.

Do not call methods on the component after Free(), and avoid storing the pointer in a wider scope unless another part of the form really owns the component lifecycle. A local variable is usually the simplest choice for one-shot PDF exports.

Project setup notes

The project must be able to find the HotPDF headers, libraries, and design/runtime packages. Add the HotPDF include directory to the C++ include path and the library directory to the linker search path. If the project links HPDFDoc, keep the package and unit names unchanged so C++Builder can resolve the generated headers.

Before shipping

  • Use an absolute or validated output path when generating files outside a demo folder.
  • Call BeginDoc and EndDoc in balanced pairs.
  • Open the generated PDF in at least one external viewer, not only with AutoLaunch.
  • Log generation errors so support can distinguish path, permission, font, and PDF rendering problems.

Exception-safe structure

The sample keeps the code compact, but a real export routine should handle exceptions between allocation and cleanup. PDF generation can fail because the output folder is read-only, a font cannot be resolved, a stream is closed too early, or user data contains an unexpected value. The cleanup path should not depend on the success of every drawing call.

One practical approach is to create the component immediately before the export, then release it in a guaranteed cleanup block. That keeps the component lifetime tied to one PDF job. If the application generates many documents in sequence, this pattern also reduces the chance that state from one document leaks into the next one.

Design-time versus runtime components

A design-time component is easier when one form owns one predictable export workflow. A runtime component is better when the application needs multiple temporary exporters, chooses settings dynamically, or runs export code from a helper class rather than from a form. The API calls are the same; the difference is only who owns the object and how long it lives.

For server-style or batch code, avoid relying on AutoLaunch. Generate the file, check that it exists, record the output path, and let the calling workflow decide whether a viewer should be opened.