기술 문서

C++Builder에서 HotPDF 컴포넌트를 동적으로 만들고 해제하기

· PDF 프로그래밍

대부분의 HotPDF 예제는 디자인 타임에 폼 위에 컴포넌트를 배치합니다. 데모에는 편리하지만, 운영 코드에서는 특정 내보내기 작업에만 PDF 컴포넌트를 만들어야 할 때가 있습니다. 동적 생성은 서비스 모듈, 보고서 도우미, 배치 작업, 그리고 컴포넌트가 폼 전체 수명 동안 살아 있을 필요가 없는 폼에서 유용합니다.

기본 C++Builder 패턴은 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 를 받으므로 컴포넌트가 살아 있으면 폼이 정리할 수 있습니다. 이 짧은 예제에서는 EndDoc후에 객체도 명시적으로 해제합니다. 실제 코드에서는 정리 경로를 예외 안전하게 유지하십시오. PDF 생성이 실패할 수 있다면 작업을 try/__finally 블록으로 감싸거나 작은 RAII 도우미를 사용해 Free() 가 계속 실행되게 하십시오.

컴포넌트를 Free()한 뒤에는 그 메서드를 호출하지 말고, 폼의 다른 부분이 컴포넌트 수명 주기를 실제로 소유하지 않는 한 포인터를 더 넓은 범위에 저장하지 마십시오. 일회성 PDF 내보내기에는 보통 지역 변수가 가장 단순합니다.

프로젝트 설정 참고

프로젝트는 HotPDF 헤더, 라이브러리, 디자인/런타임 패키지를 찾을 수 있어야 합니다. C++ include 경로에 HotPDF include 디렉터리를 추가하고, 링커 검색 경로에 라이브러리 디렉터리를 추가하십시오. 프로젝트가 HPDFDoc를 링크한다면 C++Builder가 생성된 헤더를 확인할 수 있도록 패키지와 유닛 이름을 그대로 유지하십시오.

배포 전 확인

  • 데모 폴더 밖에 파일을 생성할 때는 절대 경로 또는 검증된 출력 경로를 사용하십시오.
  • 호출할 때는 BeginDocEndDoc 는 균형 잡힌 쌍으로 호출하십시오.
  • 생성된 PDF는 AutoLaunch만으로 확인하지 말고 최소 하나 이상의 외부 뷰어에서 열어 보십시오.
  • 지원팀이 경로, 권한, 글꼴, PDF 렌더링 문제를 구분할 수 있도록 생성 오류를 기록하십시오.

예외 안전 구조

샘플은 코드를 간결하게 유지하지만 실제 내보내기 루틴은 할당과 정리 사이의 예외를 처리해야 합니다. PDF 생성은 출력 폴더가 읽기 전용이거나, 글꼴을 확인할 수 없거나, 스트림이 너무 일찍 닫히거나, 사용자 데이터에 예상치 못한 값이 있어 실패할 수 있습니다. 정리 경로는 모든 그리기 호출이 성공한다는 가정에 의존해서는 안 됩니다.

실용적인 방법은 내보내기 직전에 컴포넌트를 만들고 보장된 정리 블록에서 해제하는 것입니다. 이렇게 하면 컴포넌트 수명이 하나의 PDF 작업에 묶입니다. 애플리케이션이 많은 문서를 연속으로 생성하는 경우에도 이 패턴은 한 문서의 상태가 다음 문서로 새어 나갈 가능성을 줄여 줍니다.

디자인 타임 컴포넌트와 런타임 컴포넌트

하나의 폼이 예측 가능한 하나의 내보내기 워크플로를 소유한다면 디자인 타임 컴포넌트가 더 쉽습니다. 애플리케이션이 여러 임시 내보내기를 필요로 하거나, 설정을 동적으로 선택하거나, 폼이 아닌 도우미 클래스에서 내보내기 코드를 실행한다면 런타임 컴포넌트가 더 적합합니다. API 호출은 동일하며, 차이는 누가 객체를 소유하고 얼마나 오래 유지하는가뿐입니다.

서버 스타일 또는 배치 코드에서는 AutoLaunch에 의존하지 마십시오. 파일을 생성하고, 존재 여부를 확인하고, 출력 경로를 기록한 뒤, 뷰어를 열지는 호출 워크플로가 결정하게 하십시오.