技術文章

在 C++Builder 中動態建立並釋放 HotPDF 元件

· PDF 程式設計

很多 HotPDF 示例會在設計期把元件放到窗體上。這樣寫演示很方便,但生產程式碼有時只需要在某次匯出操作中臨時建立 PDF 元件。動態建立適合服務模組、報表輔助類、批處理任務,以及元件不應跟隨窗體整個生命週期存在的場景。

基本模式是分配一個 THotPDF 例項,設定輸出檔案和文件選項,生成 PDF,然後在操作結束時釋放元件。下面的示例展示了按鈕事件中的最小流程。

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();
}

所有權和清理

建構函式傳入 this 作為 owner,因此如果元件仍然存活,窗體可以負責清理。在這個短示例中,物件也會在 EndDoc 之後顯式釋放。實際程式碼應讓清理路徑具備異常安全性:如果 PDF 生成可能失敗,請用 try/__finally 或小型 RAII 輔助物件確保 Free() 仍會執行。

呼叫 Free() 後不要再訪問元件。除非窗體其他部分確實需要管理元件生命週期,否則不要把指標儲存到更大的作用域裡。對於一次性 PDF 匯出,區域性變數通常最簡單。

專案配置注意事項

專案必須能找到 HotPDF 的標頭檔案、庫檔案以及設計期或執行期包。把 HotPDF include 目錄加入 C++ include path,把庫目錄加入 linker search path。如果專案連結 HPDFDoc,保持包名和單元名不變,讓 C++Builder 能解析生成的標頭檔案。

異常安全結構

示例程式碼保持簡潔,但真實匯出例程要處理分配和清理之間的異常。PDF 生成可能因為輸出目錄只讀、字型無法解析、流提前關閉或使用者資料異常而失敗。清理路徑不應依賴每個繪製呼叫都成功。

一個實用做法是在匯出前立即建立元件,並在保證執行的清理塊中釋放。這樣元件生命週期只繫結到一次 PDF 任務。如果應用連續生成多份文件,也能降低一個文件狀態洩漏到下一個文件的風險。

設計期元件與執行期元件

如果一個窗體擁有一個固定匯出流程,設計期元件更簡單。如果應用需要多個臨時匯出器、動態選擇設定,或從輔助類執行匯出程式碼,執行期元件更合適。API 呼叫相同,區別只在於誰擁有物件以及物件存活多久。

  • 為輸出檔案使用絕對路徑或經過驗證的路徑。
  • 保持 BeginDocEndDoc 成對出現。
  • 不要在批處理或服務式程式碼中依賴 AutoLaunch
  • 記錄生成錯誤,便於區分路徑、許可權、字型和渲染問題。