기술 문서

Delphi에서 PDFium VCL을 사용하여 PDF 문서 인쇄

정확한 렌더링과 적절한 크기 조정을 통해 PDF 문서를 인쇄하는 것은 일반적인 요구 사항입니다. Print PDF (Print PDF) 데모는 PDFium VCL 구성 요소를 사용하여 미리 보기, 페이지 선택 및 품질 옵션을 통해 전문적인 PDF 인쇄를 구현하는 방법을 보여줍니다.

개요

이 포괄적인 데모는 인쇄 미리 보기, 페이지 범위 선택, 품질 설정, 크기 조정 옵션 및 최근 파일 기록을 포함한 완벽한 인쇄 솔루션을 제공합니다. 이는 Delphi 애플리케이션에서 PDF 인쇄에 대한 모범 사례를 보여줍니다.

주요 기능

  • 인쇄 미리 보기 – 인쇄 전 시각적 미리 보기
  • Page Selection (페이지 선택) – 모든 페이지 또는 특정 범위 인쇄
  • 품질 설정 – 초안, 표준, 고품질 모드
  • 크기 조정 옵션 – 페이지에 맞춤, 축소하여 맞춤, 또는 크기 조정 없음
  • 여러 부 – 콜레이션을 사용하여 여러 부 인쇄
  • 진행 상황 추적 – 인쇄 중 시각적 피드백
  • 최근 파일 – 이전에 인쇄한 문서에 대한 빠른 액세스

PDFium DLL 요구 사항

PDFium VCL 애플리케이션을 실행하기 전에, PDFium DLL 파일이 설치되어 있는지 확인하십시오.

  • pdfium32.dll / pdfium64.dll – 표준 버전 (약 5-6 MB)
  • pdfium32v8.dll / pdfium64v8.dll – V8 JavaScript 엔진 포함 (약 23-27 MB)

설치: 실행 PDFiumVCL\DLLs\CopyDlls.bat 관리자 권한으로 실행하여 DLL 파일을 Windows 시스템 디렉터리에 자동으로 복사합니다.

기본 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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
procedure PrintPdfSimple(const FileName: string);
var
  Pdf: TPdf;
  I: Integer;
  Bitmap: TBitmap;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.Active := True;
    
    Printer.Title := Pdf.Title;
    Printer.BeginDoc;
    try
      for I := 1 to Pdf.PageCount do
      begin
        if I > 1 then
          Printer.NewPage;
          
        Pdf.PageNumber := I;
        
        // Render page to printer
        Bitmap := Pdf.RenderPage(
          0, 0,
          Printer.PageWidth,
          Printer.PageHeight,
          ro0,
          [rePrinting]
        );
        try
          PrintBitmap(Printer, Bitmap);
        finally
          Bitmap.Free;
        end;
      end;
    finally
      Printer.EndDoc;
    end;
    
  finally
    Pdf.Active := False;
    Pdf.Free;
  end;
end;

비트맵을 프린터로 인쇄

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
26
27
28
procedure PrintBitmap(Printer: TPrinter; Bitmap: TBitmap);
var
  InfoHeaderSize, ImageSize: DWORD;
  InfoHeader: PBitmapInfo;
  Image: Pointer;
begin
  GetDIBSizes(Bitmap.Handle, InfoHeaderSize, ImageSize);
  
  InfoHeader := AllocMem(InfoHeaderSize);
  try
    Image := AllocMem(ImageSize);
    try
      GetDIB(Bitmap.Handle, 0, InfoHeader^, Image^);
      
      StretchDIBits(
        Printer.Canvas.Handle,
        0, 0, Bitmap.Width, Bitmap.Height,
        0, 0, Bitmap.Width, Bitmap.Height,
        Image, InfoHeader^,
        DIB_RGB_COLORS, SRCCOPY
      );
    finally
      FreeMem(Image);
    end;
  finally
    FreeMem(InfoHeader);
  end;
end;

옵션을 사용한 전체 인쇄

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
procedure TFormMain.PrintPDFPages;
var
  FromPage, ToPage, Page, Copy, CopyCount: Integer;
  FirstPage: Boolean;
  Bitmap: TBitmap;
  ScaleX, ScaleY, Scale: Double;
  DestWidth, DestHeight: Integer;
  Dpi: Integer;
begin
  // Get print quality DPI
  case cmbQuality.ItemIndex of
    0: Dpi := 150;  // Draft
    1: Dpi := 300;  // Normal
    2: Dpi := 600;  // High
  else
    Dpi := 300;
  end;
  
  // Determine page range
  if radAllPages.Checked then
  begin
    FromPage := 1;
    ToPage := Pdf.PageCount;
  end
  else
  begin
    FromPage := StrToIntDef(edtFromPage.Text, 1);
    ToPage := StrToIntDef(edtToPage.Text, Pdf.PageCount);
  end;
  
  // Handle copies and collation
  if chkCollate.Checked then
    CopyCount := 1  // Will repeat entire job
  else
    CopyCount := spnCopies.Value;
    
  FProcessing := True;
  FCancelled := False;
  
  Printer.Title := ExtractFileName(Pdf.FileName);
  Printer.BeginDoc;
  try
    FirstPage := True;
    progressPrint.Max := (ToPage - FromPage + 1) * spnCopies.Value;
    progressPrint.Position := 0;
    
    for Page := FromPage to ToPage do
    begin
      for Copy := 1 to CopyCount do
      begin
        if FCancelled then
          Break;
          
        if FirstPage then
          FirstPage := False
        else
          Printer.NewPage;
          
        Pdf.PageNumber := Page;
        
        // Calculate scaling based on settings
        case cmbScaling.ItemIndex of
          0: // No scaling
          begin
            DestWidth := Round(Pdf.PageWidth * Dpi / 72);
            DestHeight := Round(Pdf.PageHeight * Dpi / 72);
          end;
          
          1: // Fit to page
          begin
            ScaleX := Printer.PageWidth / (Pdf.PageWidth * Dpi / 72);
            ScaleY := Printer.PageHeight / (Pdf.PageHeight * Dpi / 72);
            Scale := Min(ScaleX, ScaleY);
            DestWidth := Round(Pdf.PageWidth * Dpi / 72 * Scale);
            DestHeight := Round(Pdf.PageHeight * Dpi / 72 * Scale);
          end;
          
          2: // Shrink to fit (only if needed)
          begin
            ScaleX := Printer.PageWidth / (Pdf.PageWidth * Dpi / 72);
            ScaleY := Printer.PageHeight / (Pdf.PageHeight * Dpi / 72);
            Scale := Min(ScaleX, ScaleY);
            if Scale > 1 then Scale := 1;
            DestWidth := Round(Pdf.PageWidth * Dpi / 72 * Scale);
            DestHeight := Round(Pdf.PageHeight * Dpi / 72 * Scale);
          end;
        end;
        
        // Render and print
        Bitmap := Pdf.RenderPage(0, 0, DestWidth, DestHeight,
          ro0, [rePrinting, reAnnotations]);
        try
          PrintBitmap(Printer, Bitmap);
        finally
          Bitmap.Free;
        end;
        
        progressPrint.Position := progressPrint.Position + 1;
        Application.ProcessMessages;
      end;
      
      if FCancelled then
        Break;
    end;
    
  finally
    Printer.EndDoc;
    FProcessing := False;
  end;
end;

인쇄 대화 상자 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
procedure TFormMain.btnPrintClick(Sender: TObject);
begin
  if not FileExists(edtPdfFile.Text) then
  begin
    ShowError('Please select a valid PDF file first.');
    Exit;
  end;
  
  // Setup print dialog
  PrintDialog.MinPage := 1;
  PrintDialog.MaxPage := Pdf.PageCount;
  PrintDialog.FromPage := 1;
  PrintDialog.ToPage := Pdf.PageCount;
  PrintDialog.Options := [poPageNums, poSelection];
  
  if PrintDialog.Execute then
  begin
    PrintPDFPages;
  end;
end;

인쇄 미리 보기

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
26
27
28
29
30
31
32
33
procedure TFormMain.UpdatePreview;
var
  PreviewWidth, PreviewHeight: Integer;
  Scale: Double;
begin
  if not Pdf.Active then
    Exit;
    
  Pdf.PageNumber := FCurrentPreviewPage;
  
  // Calculate preview size to fit panel
  Scale := Min(
    pnlPreview.Width / Pdf.PageWidth,
    pnlPreview.Height / Pdf.PageHeight
  ) * (FCurrentZoom / 100);
  
  PreviewWidth := Round(Pdf.PageWidth * Scale);
  PreviewHeight := Round(Pdf.PageHeight * Scale);
  
  // Render preview
  FPreviewBitmap.Free;
  FPreviewBitmap := Pdf.RenderPage(
    0, 0, PreviewWidth, PreviewHeight,
    ro0, [reAnnotations], clWhite
  );
  
  // Display in image control
  imgPreview.Picture.Assign(FPreviewBitmap);
  
  // Update page info
  lblPageInfo.Caption := Format('Page %d of %d',
    [FCurrentPreviewPage, Pdf.PageCount]);
end;

미리 보기 탐색

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
procedure TFormMain.btnFirstPageClick(Sender: TObject);
begin
  if Pdf.Active then
  begin
    FCurrentPreviewPage := 1;
    edtPreviewPage.Text := '1';
    UpdatePreview;
  end;
end;
 
procedure TFormMain.btnPrevPageClick(Sender: TObject);
begin
  if Pdf.Active and (FCurrentPreviewPage > 1) then
  begin
    Dec(FCurrentPreviewPage);
    edtPreviewPage.Text := IntToStr(FCurrentPreviewPage);
    UpdatePreview;
  end;
end;
 
procedure TFormMain.btnNextPageClick(Sender: TObject);
begin
  if Pdf.Active and (FCurrentPreviewPage < Pdf.PageCount) then
  begin
    Inc(FCurrentPreviewPage);
    edtPreviewPage.Text := IntToStr(FCurrentPreviewPage);
    UpdatePreview;
  end;
end;
 
procedure TFormMain.btnLastPageClick(Sender: TObject);
begin
  if Pdf.Active then
  begin
    FCurrentPreviewPage := Pdf.PageCount;
    edtPreviewPage.Text := IntToStr(FCurrentPreviewPage);
    UpdatePreview;
  end;
end;

Zoom 컨트롤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure TFormMain.cmbZoomChange(Sender: TObject);
begin
  case cmbZoom.ItemIndex of
    0: FCurrentZoom := 50;
    1: FCurrentZoom := 75;
    2: FCurrentZoom := 100;
    3: FCurrentZoom := 125;
    4: FCurrentZoom := 150;
    5: FCurrentZoom := 200;
  else
    FCurrentZoom := 100;
  end;
  
  UpdatePreview;
end;

페이지 회전 처리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function GetPrintRotation(Rotation: TRotation): TRotation;
begin
  // Adjust rotation for printing (printer coordinate system)
  case Rotation of
    ro90:  Result := ro270;
    ro270: Result := ro90;
  else
    Result := Rotation;
  end;
end;
 
// Use in printing
Bitmap := Pdf.RenderPage(0, 0, Width, Height,
  GetPrintRotation(Pdf.PageRotation), [rePrinting]);

설정 저장/로드

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
26
27
28
29
30
31
32
33
34
procedure TFormMain.SaveSettings;
var
  Ini: TIniFile;
begin
  Ini := TIniFile.Create(FSettingsFile);
  try
    Ini.WriteInteger('Print', 'Quality', cmbQuality.ItemIndex);
    Ini.WriteInteger('Print', 'Scaling', cmbScaling.ItemIndex);
    Ini.WriteInteger('Print', 'Copies', spnCopies.Value);
    Ini.WriteBool('Print', 'Collate', chkCollate.Checked);
    Ini.WriteInteger('Preview', 'Zoom', FCurrentZoom);
  finally
    Ini.Free;
  end;
end;
 
procedure TFormMain.LoadSettings;
var
  Ini: TIniFile;
begin
  if FileExists(FSettingsFile) then
  begin
    Ini := TIniFile.Create(FSettingsFile);
    try
      cmbQuality.ItemIndex := Ini.ReadInteger('Print', 'Quality', 1);
      cmbScaling.ItemIndex := Ini.ReadInteger('Print', 'Scaling', 1);
      spnCopies.Value := Ini.ReadInteger('Print', 'Copies', 1);
      chkCollate.Checked := Ini.ReadBool('Print', 'Collate', False);
      FCurrentZoom := Ini.ReadInteger('Preview', 'Zoom', 100);
    finally
      Ini.Free;
    end;
  end;
end;

사용 사례

  • 문서 인쇄 – PDF 문서의 고품질 인쇄
  • 일괄 인쇄 – 여러 문서를 순차적으로 인쇄
  • 보고서 배포 – 배포를 위한 보고서 인쇄
  • 교정 인쇄 – 최종 생산 전에 인쇄 교정본을 확인하세요.

결론

Print PDF 데모는 PDFium VCL을 사용하여 전문적인 PDF 인쇄를 구현하는 방법을 보여줍니다. 간단한 단일 페이지 인쇄부터 미리보기 및 품질 설정을 갖춘 고급 다중 복사 인쇄 작업까지, 이 구성 요소는 필요한 모든 기능을 제공합니다.

The RenderPage method with the rePrinting 이 옵션은 프린터의 최적 출력을 보장하며, 미리보기 기능은 사용자가 인쇄 전에 설정을 확인할 수 있도록 합니다.

전문적인 PDF 인쇄 기능을 추가하세요. 다음을 사용하여 애플리케이션에 통합하세요. PDFium Delphi 컴포넌트..