Quick PDF Library와 PdfiumViewer에서 sgcPDF로 마이그레이션

Foxit은 2021년 12월 13일에 Quick PDF Library 지원을 종료했고, PdfiumViewer 저장소는 2019년 8월 2일부터 읽기 전용입니다. sgcPDF는 둘을 모두 대체합니다. Delphi exe에 컴파일되는 순수 Pascal과 WinForms용 관리형 C#이며, 배포할 PDF DLL이 없습니다. 이 키트는 Quick PDF Library 함수와 PdfiumViewer 클래스를 sgcPDF에 매핑하고, 컴파일되어 자체 테스트를 통과하는 두 샘플의 코드를 보여 줍니다.

더 이상 발전하지 않는 PDF 라이브러리 위에 만든 애플리케이션

흔한 경우는 두 가지입니다. Quick PDF Library로 PDF 파일을 만들고 병합하고 채우고 렌더링하는 Delphi 애플리케이션, 그리고 PdfiumViewer로 PDF 파일을 표시하는 WinForms 애플리케이션입니다.

Quick PDF Library(Delphi)에서

Quick PDF Library(Debenu Quick PDF Library, 이후 Foxit Quick PDF Library)는 잠금 해제 키가 있는 DLL, ActiveX 또는 LIB로 제공되며, "선택된" 문서, 페이지, 글꼴, 이미지를 가진 하나의 객체에서 동작합니다. sgcPDF는 객체 모델을 갖춘 Pascal 유닛 모음입니다. TsgcPDFDocument, TsgcPDFPage, TsgcPDFEditor, TsgcPDFAcroForm이며 Delphi 7부터 Delphi 13까지 지원합니다.

PdfiumViewer(WinForms)에서

PdfiumViewer는 네이티브 PDFium 라이브러리를 PdfViewer 컨트롤, PdfRenderer, PdfDocument로 감쌉니다. PDF 파일을 표시, 검색, 렌더링, 인쇄합니다. sgcPDF는 이를 관리형 컨트롤 하나인 TsgcPDFViewerControl로 대체하고, PdfiumViewer에 없던 기능을 더합니다. PDF 파일 만들기, 양식 채우기, 주석 추가, 변경 내용 저장입니다.

Quick PDF Library. Foxit 공지(2026-10-20에 확인)에는 다음과 같이 적혀 있습니다. "2021년 12월 13일부터 Foxit은 다음 제품의 지원을 종료합니다", 그리고 목록의 첫 번째 제품이 Foxit Quick PDF Library (All Platforms)입니다. 유지 관리 및 지원 계약이 유효한 고객은 2022년 12월 13일까지 지원을 받았습니다. "그 날짜 이후에는 제품이 지원 종료 상태가 되며 더 이상 지원을 받을 수 없습니다." Foxit이 제시하는 대체 제품은 Windows, Mac, Linux, Android, iOS용 PDF SDK, ActiveX SDK, .NET SDK 제품군입니다.

PdfiumViewer. GitHub 저장소(2026-10-20에 확인)에는 다음과 같이 표시됩니다. "소유자가 2019년 8월 2일에 이 저장소를 보관 처리했습니다. 이제 읽기 전용입니다." README는 이렇게 설명합니다. "오랫동안 이 프로젝트에 실제로 시간을 쓰지 못했습니다", 그리고 "이 프로젝트를 제대로 지원할 상황이 아닙니다." 또한 이렇게 밝힙니다. "PdfiumViewer 컨트롤에는 네이티브 PDFium 라이브러리가 필요합니다. 이 라이브러리는 PdfiumViewer NuGet 패키지에 포함되어 있지 않습니다." NuGet 패키지는 2017년 11월 6일(버전 2.13.0)에 마지막으로 업데이트되었고 net20을 대상으로 합니다.

소스 코드가 포함된 하나의 PDF 라이브러리

sgcPDF는 sgcUI의 PDF 제품입니다. Delphi와 .NET에서 PDF 파일을 만들고, 편집하고, 채우고, 서명하고, 암호화하고, 렌더링하고, 표시합니다.

배포할 PDF DLL이 없음

Delphi에서는 sgcPDF 유닛이 exe에 컴파일됩니다. 배포하고 등록할 DLL, ActiveX, LIB가 없고 잠금 해제 키 호출도 없습니다. .NET에서 sgcPDF는 관리형 C#이므로 pdfium.dll도, 선택해야 할 x86 또는 x64 네이티브 패키지도 없습니다. 샘플은 AnyCPU로 실행됩니다.

객체 모델

모든 호출이 페이지 객체나 인덱스를 받으므로 Quick PDF Library의 "선택된" 상태가 사라집니다. 임포지션은 벡터 폼 XObject(AddPageAsForm, DrawForm, DrawFormInRect)를 사용하고, 양식은 AcroForm을 사용하며, 암호화는 AES-256(emAES_256)까지 지원합니다.

편집이 되는 뷰어

TsgcPDFViewerControl은 너비, 페이지, 높이에 맞추고, 보기를 회전하고, 검색하고, 대화 상자로 인쇄하며, .NET에서는 PdfiumViewer처럼 PrintDocument를 제공합니다. 또한 양식 필드를 채우고(FormFilling), 마우스로 주석을 추가하고(AnnotationTool), 텍스트를 선택합니다. 보조 뷰는 TsgcPDFThumbnailView, TsgcPDFOutlineView, TsgcPDFCommentsView입니다.

sgcPDF는 단독으로 판매되며, Delphi와 C++ Builder 개발자 1인용은 €249부터, .NET은 €249부터입니다. 전체 소스 코드와 1년간의 업데이트가 포함되고, sgcUI Enterprise와 All-Access 번들에도 포함됩니다. .NET 패키지는 NuGet에서 동일한 기능의 무료 Community 패키지인 esegece.sgcPDF.Community와 esegece.sgcPDF.WinForms.Community로도 제공됩니다. sgcPDF 제품 페이지를 참고하세요.

sgcPDF의 Quick PDF Library 함수

유닛은 sgcPDF_Types, sgcPDF_Fonts, sgcPDF_Document이며, 필요하면 sgcPDF_Editor, sgcPDF_Encryption, sgcPDF_Renderer_GDI, sgcPDF_Export를 추가합니다. sgcPDF의 페이지 인덱스는 0부터 시작합니다.

Quick PDF Library sgcPDF
UnlockKey코드에서 호출할 것이 없음
NewDocumentTsgcPDFDocument.Create 후 AddPage (새 문서에는 페이지를 추가하기 전까지 페이지가 없음)
NewPage, SetPageDimensions, SetPageSizeTsgcPDFDocument.AddPage(AWidth, AHeight): TsgcPDFPage, InsertPage(AIndex, AWidth, AHeight)
LoadFromFile, LoadFromStringTsgcPDFDocument.LoadFromFile, LoadFromStream, LoadFromBytes
비밀번호를 사용하는 LoadFromFileLoadFromFile 전에 TsgcPDFDocument.SetPassword(APassword)
SaveToFile, SaveToStringTsgcPDFDocument.SaveToFile, SaveToStream, SaveIncremental
PageCountTsgcPDFDocument.PageCount, 파일만 대상으로 할 때는 sgcPDFGetPageCount(AFileName)
SelectPageTsgcPDFDocument.Pages[AIndex] (0부터 시작, 기본 속성), GetPage(AIndex)
SetInformationTsgcPDFDocument.Info.Title, .Author, .Subject, .Keywords, .Creator, .Producer
AddStandardFont + SelectFont + SetTextSize + DrawTextTsgcPDFStandardFont(sfHelvetica, sfTimesRoman, sfCourier와 각각의 굵게 및 기울임 변형)를 사용하는 TsgcPDFPage.DrawText(AText, X, Y, AFont, AFontSize)
SetTextColor + DrawTextTsgcPDFPage.DrawTextColor(AText, X, Y, AFont, AFontSize, R, G, B) (구성 요소 값은 0에서 1)
AddTrueTypeFont + DrawTextTsgcPDFDocument.AddTrueTypeFont(AFontName, ABold, AItalic): Integer (또는 AddTrueTypeFontFromFile) 후 TsgcPDFPage.DrawTextTT
DrawLine, DrawBoxTsgcPDFPage.DrawLine(X1, Y1, X2, Y2, ALineWidth), DrawRectangle(X, Y, W, H, ALineWidth), DrawRectangleFill
AddImageFromFile + SelectImage + DrawImageTsgcPDFDocument.AddImage(AFileName): Integer + TsgcPDFPage.DrawImageFromIndex(AIndex, X, Y, W, H), 또는 DrawImageFile(AFileName, X, Y, W, H)
GetPageTextTsgcPDFDocument.ExtractTextW(APageIndex), ExtractText, FindText; TsgcPDFEditor.ExtractAllText, SearchText
AddToFileList + MergeFileListsgcPDFMergeFiles([...], AOutputFile)
MergeDocumentTsgcPDFDocument.AppendDocument(ADoc), TsgcPDFEditor.MergeFrom(AFileName)
ExtractPageRanges, ExtractFilePagessgcPDFExtractPages(AInputFile, AOutputFile, ARange) ('1,3,5-9'와 같은 1부터 시작하는 범위 문자열), TsgcPDFEditor.ExtractPages(ARange, AOutputFileName)
DeletePagesTsgcPDFDocument.DeletePages(ARange), DeletePage(AIndex)
RotatePageTsgcPDFEditor.RotatePage(AIndex, ADegrees)
SetTransparency + DrawText (워터마크)TsgcPDFEditor.AddWatermarkAllPages(TsgcPDFWatermarkOptions), AddWatermark, AddTransparentText
모든 페이지에 DrawText (스탬프, 머리글, 바닥글)TsgcPDFEditor.AddTextColor, AddHeaderText, AddFooterText, AddPageNumbers
RenderPageToDCTsgcPDFRendererGDI.RenderPage(ADC, ADocument.Parser, APage.PageDict, AWidth, AHeight), VCL 뷰어에서는 TsgcPDFViewerControl.RenderPageToBitmap
RenderPageToFileTsgcPDFExporter.ExportPage(ADocument, APageIndex, AFileName) (BMP, PNG, JPEG), sgcPDFPageToImage(APDFFile, AImageFile, APageIndex, ADPI)
FormFieldCount, FindFormFieldByTitleTsgcPDFDocument.AcroForm.FieldCount, AcroForm.FindField(AName)
SetFormFieldValue, SetFormFieldValueByTitleAcroForm.FillField(AName, AValue), AcroForm.SetCheckBox(AName, AChecked), TsgcPDFEditor.FillFormField
GetFormFieldValueAcroForm.GetFieldValue(AName)
NewFormFieldAcroForm.AddTextField, AddCheckBox, AddComboBox, AddListBox, AddRadioGroup + AddRadioButton, AddButton, AddSignatureField
FlattenFormFieldAcroForm.FlattenFields, TsgcPDFEditor.FlattenForm
EncryptemAES_256, emAES_128, emRC4_128 또는 emRC4_40을 사용하는 TsgcPDFDocument.SetEncryption(AMethod, AUserPassword, AOwnerPassword)
CapturePageTsgcPDFDocument.AddPageAsForm(ASource, APageIndex): Integer (페이지 박스, 사각형 또는 주석을 받는 오버로드 포함)
DrawCapturedPageTsgcPDFPage.DrawForm(AFormIndex, X, Y, AScaleX, AScaleY, ARotation), DrawFormInRect(AFormIndex, ATarget, AKeepAspect, ARotation), DrawFormMatrix
GetPageBoxTsgcPDFPage.GetPageBox(ABox) (ppbTrimBox, ppbBleedBox, ...), TsgcPDFDocument.GetFormBBox
NewOutlineTsgcPDFEditor.AddBookmark(ATitle, APageIndex), AddBookmarkChild
AddLinkToPageTsgcPDFEditor.AddLinkAnnotation(APageIndex, ALeft, ABottom, ARight, ATop, ADestPage)
AddNoteAnnotationTsgcPDFEditor.AddTextAnnotation(APageIndex, ALeft, ABottom, ARight, ATop, AText)
SignFileTsgcPDFEditor.SignDocument(AOutputFile, ACertSubjectName, AReason, ALocation)
PrintDocumentVCL 뷰어의 TsgcPDFViewerControl.Print(AFromPage, AToPage, ATitle)는 대화 상자 없이 인쇄하고, PrintDialog(ATitle)는 프린터 대화 상자(페이지 범위, 매수)를 표시한 뒤 인쇄합니다. FireMonkey 뷰어 TsgcPDFViewerFMX는 Windows와 macOS에서 같은 두 메서드를 제공합니다.
SetMeasurementUnits(0), SetOrigin(0)기본이자 유일한 좌표계: 포인트 단위, 원점은 왼쪽 아래, 도우미 함수는 sgcPDFMMToPoints, sgcPDFRectMM

Delphi 뷰어에는 이것도 있습니다. 높이 맞춤 확대/축소(TsgcPDFViewerControl의 zmFitHeight, TsgcPDFViewerFMX의 fzmFitHeight, TsgcPDFViewer의 ZoomFitHeight)와 보기 회전(ViewRotation, RotateLeft, RotateRight)이며, 보기만 돌리고 문서는 바꾸지 않습니다.

sgcPDF로 옮기는 일반적인 Quick PDF Library 작업

모든 발췌 코드는 MigrateFromQuickPDF 데모에서 복사한 것이며, 이 데모는 Delphi 7(Win32)과 Delphi 13(Win32 및 Win64)에서 컴파일되고 자체 테스트를 통과합니다. 주석에는 각 줄이 대체하는 Quick PDF Library 호출이 적혀 있습니다.

uses 절

Quick PDF Library 임포트 유닛과 DLL은 필요 없어집니다. 다음 유닛이 데모의 모든 작업을 다룹니다.

frmMain.pas
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, ShellAPI,
  // sgc
  sgcPDF_Types, sgcPDF_Fonts, sgcPDF_Document, sgcPDF_Encryption,
  sgcPDF_Editor, sgcPDF_Renderer_GDI;

텍스트, 상자, 이미지가 있는 문서 만들기

NewDocument, SetInformation, AddStandardFont, SelectFont, SetTextSize, SetTextColor, DrawText, DrawBox, AddImageFromFile, SelectImage, DrawImage, SaveToFile을 대체합니다.

frmMain.pas
oDoc := TsgcPDFDocument.Create;
try
  // SetInformation(1, ...) / SetInformation(2, ...)
  oDoc.Info.Title := 'Created with sgcPDF';
  oDoc.Info.Author := 'Migration sample';
  // NewDocument creates page 1, sgcPDF adds every page explicitly
  oPage := oDoc.AddPage(CS_A4_WIDTH, CS_A4_HEIGHT);
  // AddStandardFont(4) + SelectFont + SetTextSize(28) + DrawText
  oPage.DrawText('Hello from sgcPDF', 72, 760, sfHelveticaBold, 28);
  // SetTextColor(r, g, b) + DrawText
  oPage.DrawTextColor('No DLL, pure Pascal.', 72, 725, sfHelvetica, 14,
    0.1, 0.3, 0.7);
  // SetLineColor + SetLineWidth + DrawBox(x, y, w, h, 0)
  oPage.DrawRectangle(72, 520, 260, 120, 1.5);
  // AddImageFromFile + SelectImage + DrawImage(x, y, w, h)
  vImage := oDoc.AddImage(OutFile('logo.bmp'));
  oPage.DrawImageFromIndex(vImage, 102, 540, 200, 80);
  oDoc.SaveToFile(OutFile('created.pdf'));
finally
  oDoc.Free;
end;

페이지의 텍스트 추출

LoadFromFile, PageCount, SelectPage, GetPageText를 대체합니다. 페이지 인덱스가 0부터 시작한다는 점에 유의하세요.

frmMain.pas
oDoc.LoadFromFile(OutFile('input_a.pdf'));
Log('Extract text: input_a.pdf has ' + IntToStr(oDoc.PageCount) +
  ' pages');
// SelectPage(2) + GetPageText(0): sgcPDF page indexes are 0-based
vText := string(oDoc.ExtractTextW(1));
Log(vText);

병합과 분할

AddToFileList와 MergeFileList, 그리고 ExtractPageRanges 또는 ExtractFilePages를 대체합니다. 범위 문자열은 계속 1부터 시작합니다.

frmMain.pas
sgcPDFMergeFiles([OutFile('input_a.pdf'), OutFile('input_b.pdf')],
  OutFile('merged.pdf'));
frmMain.pas
// 1-based range string, the same syntax as Quick PDF Library
sgcPDFExtractPages(OutFile('merged.pdf'), OutFile('pages_2-3.pdf'), '2-3');
// one file per page: split
sgcPDFExtractPages(OutFile('merged.pdf'), OutFile('page_4.pdf'), '4');

모든 페이지에 워터마크와 스탬프 넣기

페이지를 순회하는 루프 안의 SelectPage, SetTransparency, SetTextColor, DrawText를 대체합니다.

frmMain.pas
oEditor.LoadFromFile(OutFile('input_a.pdf'));
vOptions.Text := 'CONFIDENTIAL';
vOptions.Font := sfHelveticaBold;
vOptions.FontSize := 72;
vOptions.Rotation := 45;
vOptions.Opacity := 0.3;
vOptions.R := 0.8;
vOptions.G := 0.1;
vOptions.B := 0.1;
oEditor.AddWatermarkAllPages(vOptions);
// a stamp in the top right corner of every page
for i := 0 to oEditor.Document.PageCount - 1 do
  oEditor.AddTextColor(i, 'APPROVED', 440, 800, sfHelveticaBold, 16,
    0.0, 0.5, 0.0);
oEditor.SaveToFile(OutFile('watermarked.pdf'));

페이지를 디바이스 컨텍스트에 렌더링

RenderPageToDC를 대체합니다. 렌더러는 로드된 문서의 Parser와 페이지의 PageDict를 받습니다.

frmMain.pas
oDoc.LoadFromFile(OutFile('created.pdf'));
oPage := oDoc.Pages[0];
// 96 DPI: points are 1/72 inch
vScale := 96 / 72;
vW := Round(oPage.Width * vScale);
vH := Round(oPage.Height * vScale);
oBitmap.PixelFormat := pf24bit;
oBitmap.Width := vW;
oBitmap.Height := vH;
oBitmap.Canvas.Brush.Color := clWhite;
oBitmap.Canvas.FillRect(Rect(0, 0, vW, vH));
oRenderer.RenderPage(oBitmap.Canvas.Handle, oDoc.Parser, oPage.PageDict,
  vW, vH);
GdiFlush;
oBitmap.SaveToFile(OutFile('created_page1.bmp'));

양식 채우기

FormFieldCount, FindFormFieldByTitle, SetFormFieldValue를 대체합니다.

frmMain.pas
oDoc.LoadFromFile(OutFile('form.pdf'));
Log('Fill form: form.pdf has ' + IntToStr(oDoc.AcroForm.FieldCount) +
  ' fields');
oDoc.AcroForm.FillField('Customer', 'ACME Corporation');
oDoc.AcroForm.FillField('Amount', '1250.00');
oDoc.AcroForm.SetCheckBox('Paid', True);
oDoc.SaveToFile(OutFile('form_filled.pdf'));

AES-256으로 암호화하고 비밀번호로 열기

Encrypt, 그리고 비밀번호를 사용하는 LoadFromFile을 대체합니다.

frmMain.pas
oDoc.LoadFromFile(OutFile('input_a.pdf'));
oDoc.SetEncryption(emAES_256, CS_USER_PASSWORD, CS_OWNER_PASSWORD);
oDoc.SaveToFile(OutFile('encrypted.pdf'));
frmMain.pas
oDoc.SetPassword(CS_USER_PASSWORD);
oDoc.LoadFromFile(OutFile('encrypted.pdf'));
vText := string(oDoc.ExtractTextW(0));

2-up 임포지션

CapturePage, NewPage, SetPageDimensions, DrawCapturedPage를 대체합니다. AddPageAsForm은 각 원본 페이지를 폼 XObject로 유지하므로 텍스트가 벡터로 남고 선택할 수 있습니다.

frmMain.pas
oSource.LoadFromFile(OutFile('merged.pdf'));
vHalf := CS_A4_HEIGHT / 2;
oSheet := nil;
for i := 0 to oSource.PageCount - 1 do
begin
  // a landscape A4 sheet for every 2 source pages
  if i mod 2 = 0 then
    oSheet := oTarget.AddPage(CS_A4_HEIGHT, CS_A4_WIDTH);
  // CapturePage
  vForm := oTarget.AddPageAsForm(oSource, i);
  // DrawCapturedPage, scaled to fit the left or the right half
  oSheet.DrawFormInRect(vForm, sgcPDFRect((i mod 2) * vHalf, 0,
    (i mod 2) * vHalf + vHalf, CS_A4_WIDTH), True);
end;
oTarget.SaveToFile(OutFile('imposed_2up.pdf'));

sgcPDF의 PdfiumViewer 클래스

네임스페이스는 esegece.sgcPDF, 패키지는 esegece.sgcPDF.WinForms입니다. 두 라이브러리 모두 페이지 인덱스는 0부터 시작합니다.

PdfiumViewer sgcPDF .NET
PdfViewer (도구 모음과 책갈피 창이 있는 UserControl)TsgcPDFViewerControl, 도구 모음은 직접 만들고 책갈피는 TsgcPDFOutlineView
PdfRenderer (PdfViewer.Renderer)동일한 TsgcPDFViewerControl
PdfViewer.Document = PdfDocument.Load(path)TsgcPDFViewerControl.LoadFromFile(path) (뷰어가 문서를 소유), LoadFromStream, 또는 Document = vDoc (직접 해제)
PdfDocument.Load(path, password)LoadFromFile 전에 TsgcPDFDocument.SetPassword, 그다음 TsgcPDFViewerControl.Document = vDoc
PdfDocument.PageCountTsgcPDFViewerControl.PageCount (속성), TsgcPDFDocument.PageCount() (메서드)
PdfDocument.PageSizesTsgcPDFDocument.GetPage(i).Width와 .Height (포인트)
PdfRenderer.PageTsgcPDFViewerControl.PageIndex, GotoPage, NextPage, PrevPage, FirstPage, LastPage, 이벤트 OnPageChange
PdfViewerZoomMode.FitWidthZoomMode = TsgcPDFViewerZoomMode.zmFitWidth
PdfViewerZoomMode.FitHeightTsgcPDFViewerZoomMode.zmFitHeight
PdfViewerZoomMode.FitBestTsgcPDFViewerZoomMode.zmFitPage
Zoom (배율 값, 1.0 = 100%)TsgcPDFViewerControl.Zoom (백분율, 100 = 100%, zmCustom으로 설정), ZoomIn, ZoomOut, zmActualSize, ZoomToRect
PdfRenderer.RotateLeft(), RotateRight()TsgcPDFViewerControl.RotateLeft(), RotateRight()
PdfRenderer.RotationTsgcPDFViewerControl.ViewRotation (TsgcPDFViewerRotation: pvr0, pvr90, pvr180, pvr270), PageRotation(i)는 표시되는 회전을 반환
PdfDocument.Search(text, matchCase, wholeWord) + PdfRenderer.MarkersTsgcPDFViewerControl.FindText(AText, ACaseSensitive, AWholeWord) (강조 표시 및 스크롤), FindNext, FindPrevious, SearchResults, GetSearchMatch(i), ClearSearch
PdfDocument.CreatePrintDocument() + PrintDialog 또는 PrintPreviewDialogTsgcPDFViewerControl.CreatePrintDocument()는 같은 PrintDialog와 PrintPreviewDialog 코드에 쓸 System.Drawing.Printing.PrintDocument를 반환합니다. 한 번의 호출로는 PrintDialog(ATitle), 대화 상자 없이는 Print(AFromPage, AToPage, ATitle)
PdfDocument.Render(page, dpiX, dpiY, forPrinting)TsgcPDFViewerControl.RenderPageToBitmap(APageIndex, ref Bitmap, AZoomPercent, ADPI), 뷰어가 없으면 sgcPDF_Export.sgcPDFPageToImage 또는 TsgcPDFExporter.ExportPage
PdfDocument.GetPdfText(page)TsgcPDFDocument.ExtractTextW(APageIndex), 문자 위치가 필요하면 TsgcPDFViewerControl.PageText(i), 마우스 선택은 SelectedText, CopyToClipboard
PdfDocument.BookmarksTsgcPDFOutlineView
PdfViewer.LinkClickTsgcPDFViewerControl.OnLinkClick, OpenLinksInBrowser
PdfDocument.Save(path)TsgcPDFDocument.SaveToFile, SaveIncremental(AFileName) (원본 바이트를 유지하고 변경 내용을 덧붙임)
대응 기능 없음: 양식 채우기TsgcPDFViewerControl.FormFilling = true, OnFieldChange, 코드에서는 AcroForm.FillField, SetCheckBox, GetFieldValue, FindField
대응 기능 없음: 주석TsgcPDFDocument.Annotations.AddText, AddFreeText, AddHighlight, AddStamp, AddLine, AddSquare, AddCircle, 그다음 AnnotationsChanged(), 마우스로는 AnnotationTool과 AnnotationEditing
대응 기능 없음: PDF 만들기TsgcPDFDocument.AddPage, TsgcPDFPage.DrawText, DrawRectangle, AcroForm.AddTextField, AddCheckBox, SaveToFile

sgcPDF 뷰어를 사용하는 PdfiumViewer 폼

모든 발췌 코드는 MigrateFromPdfiumViewer 데모에서 복사한 것이며, 이 데모는 Release로 컴파일되고 자체 테스트를 통과합니다. 주석에는 각 블록이 대체하는 PdfiumViewer 코드가 인용되어 있습니다.

PdfViewer와 PdfRenderer 대신 컨트롤 하나

MainForm.cs
// PdfiumViewer: PdfViewer (UserControl with toolbar) and its PdfRenderer (the page
// surface, PdfViewer.Renderer) -> one control, TsgcPDFViewerControl
private TsgcPDFViewerControl FViewer;
MainForm.cs
FViewer = new TsgcPDFViewerControl();
FViewer.Parent = pnlViewer;
FViewer.Dock = DockStyle.Fill;
// PdfiumViewer: PdfRenderer.DisplayRectangleChanged / polling PdfRenderer.Page -> OnPageChange
FViewer.OnPageChange = DoPageChange;
// PdfiumViewer: none, PdfiumViewer renders form fields but cannot edit them.
// sgcPDF: the user types into text fields and toggles check boxes in the viewer
FViewer.FormFilling = true;
FViewer.OnFieldChange = DoFieldChange;
// PdfiumViewer: none. sgcPDF: AnnotationTool adds notes, highlights, shapes, ink
// and stamps with the mouse; AnnotationEditing moves, resizes and deletes them
FViewer.AnnotationAuthor = "sgcPDF demo";

파일 열기

MainForm.cs
// PdfiumViewer: pdfViewer1.Document = PdfDocument.Load(AFileName)
// sgcPDF: the viewer loads and owns the document; to share a document you load
// yourself, assign it: FViewer.Document = vDoc (you dispose it)
FViewer.LoadFromFile(AFileName);
// PdfiumViewer: PdfViewer.ZoomMode = PdfViewerZoomMode.FitWidth
FViewer.ZoomMode = TsgcPDFViewerZoomMode.zmFitWidth;
// PdfiumViewer: PdfDocument.PageCount -> TsgcPDFViewerControl.PageCount
// (or TsgcPDFDocument.PageCount(), a method)
Log("Opened " + Path.GetFileName(AFileName) + ", " + sgcPDF_RTL.IntToStr(FViewer.PageCount) + " pages");

확대/축소 모드와 보기 회전

너비 맞춤, 페이지 맞춤, 높이 맞춤은 일대일로 대응합니다. 확대/축소는 배율 값이 아니라 백분율입니다.

MainForm.cs
internal void FitWidth()
{
    // PdfiumViewer: PdfViewerZoomMode.FitWidth -> TsgcPDFViewerZoomMode.zmFitWidth
    FViewer.ZoomMode = TsgcPDFViewerZoomMode.zmFitWidth;
}

internal void FitPage()
{
    // PdfiumViewer: PdfViewerZoomMode.FitBest -> TsgcPDFViewerZoomMode.zmFitPage
    FViewer.ZoomMode = TsgcPDFViewerZoomMode.zmFitPage;
}

internal void FitHeight()
{
    // PdfiumViewer: PdfViewerZoomMode.FitHeight -> TsgcPDFViewerZoomMode.zmFitHeight
    FViewer.ZoomMode = TsgcPDFViewerZoomMode.zmFitHeight;
}

internal void RotateLeft()
{
    // PdfiumViewer: PdfRenderer.RotateLeft() -> TsgcPDFViewerControl.RotateLeft()
    // (ViewRotation turns the view only, the document is not changed)
    FViewer.RotateLeft();
}

internal void RotateRight()
{
    // PdfiumViewer: PdfRenderer.RotateRight() -> TsgcPDFViewerControl.RotateRight()
    FViewer.RotateRight();
}

internal void SetZoomPercent(double APercent)
{
    // PdfiumViewer: PdfRenderer.Zoom is a factor (1.0 = 100%);
    // TsgcPDFViewerControl.Zoom is a percentage (100 = 100%) and sets ZoomMode to zmCustom
    FViewer.Zoom = APercent;
}

검색

MainForm.cs
// PdfiumViewer: PdfDocument.Search(text, matchCase, wholeWord) returns PdfMatches
// and the app adds PdfMarker objects to PdfRenderer.Markers to highlight them.
// sgcPDF: FindText highlights every match and scrolls to the first one,
// FindNext / FindPrevious move between them, GetSearchMatch(i) gives page and chars
if (!FViewer.FindText(AText, false, false))
{
    Log("Not found: " + AText);
    return 0;
}
for (int i = 0; i < FViewer.SearchResults; i++)
{
    TsgcPDFViewerSearchMatch vMatch = FViewer.GetSearchMatch(i);
    Log("Match " + sgcPDF_RTL.IntToStr(i + 1) + ": page " + sgcPDF_RTL.IntToStr(vMatch.PageIndex + 1) +
      ", char " + sgcPDF_RTL.IntToStr(vMatch.FirstChar));
}
return FViewer.SearchResults;

CreatePrintDocument로 인쇄

PdfiumViewer의 인쇄 코드는 형태가 그대로 유지됩니다. CreatePrintDocument()는 PrintDialog 또는 PrintPreviewDialog에 쓸 PrintDocument를 반환합니다.

MainForm.cs
// PdfiumViewer: using (PrintDocument d = PdfDocument.CreatePrintDocument())
//   { PrintDialog dlg = new PrintDialog(); dlg.Document = d; if (dlg.ShowDialog() == OK) d.Print(); }
// sgcPDF: TsgcPDFViewerControl.CreatePrintDocument() returns the same kind of
// System.Drawing.Printing.PrintDocument, so the PdfiumViewer code stays as it is. It honours
// the page range (all, some pages, current page), copies and collate of its PrinterSettings.
// A shorter way: FViewer.PrintDialog(title) shows the dialog and prints in one call, and
// FViewer.Print(from, to, title) prints without a dialog (0-based pages, -1 = last page).
if (FViewer.PageCount == 0)
    return;
using (PrintDocument vDoc = FViewer.CreatePrintDocument())
using (PrintDialog vDialog = new PrintDialog())
{
    vDoc.DocumentName = "PdfiumViewer migration sample";
    vDialog.Document = vDoc;
    vDialog.AllowSomePages = true;
    vDialog.AllowCurrentPage = true;
    vDialog.UseEXDialog = true;
    vDoc.PrinterSettings.MinimumPage = 1;
    vDoc.PrinterSettings.MaximumPage = FViewer.PageCount;
    vDoc.PrinterSettings.FromPage = 1;
    vDoc.PrinterSettings.ToPage = FViewer.PageCount;
    if (vDialog.ShowDialog(this) == DialogResult.OK)
        vDoc.Print();
}
MainForm.cs
// PdfiumViewer: PrintPreviewDialog with PdfDocument.CreatePrintDocument()
// sgcPDF: the same with TsgcPDFViewerControl.CreatePrintDocument()
if (FViewer.PageCount == 0)
    return;
using (PrintDocument vDoc = FViewer.CreatePrintDocument())
using (PrintPreviewDialog vPreview = new PrintPreviewDialog())
{
    vPreview.Document = vDoc;
    vPreview.Width = 900;
    vPreview.Height = 700;
    vPreview.ShowDialog(this);
}

페이지를 비트맵으로 렌더링

MainForm.cs
// PdfiumViewer: Image img = PdfDocument.Render(page, dpiX, dpiY, forPrinting)
// sgcPDF: RenderPageToBitmap(page, ref bitmap, zoomPercent, dpi); the bitmap passed
// in is disposed and replaced
Bitmap vBitmap = null;
FViewer.RenderPageToBitmap(APageIndex, ref vBitmap, 100, 150);
try
{
    vBitmap.Save(AFileName, ImageFormat.Png);
    Log("Page " + sgcPDF_RTL.IntToStr(APageIndex + 1) + " rendered at 150 dpi: " +
      sgcPDF_RTL.IntToStr(vBitmap.Width) + " x " + sgcPDF_RTL.IntToStr(vBitmap.Height) + " px, " +
      AFileName);
}
finally
{
    vBitmap.Dispose();
}
// without a viewer (server, batch): one call from file to image
sgcPDF_Export.sgcPDFPageToImage(FViewer.FileName, Path.ChangeExtension(AFileName, null) + "_file.png",
  APageIndex, 72);

페이지 텍스트

MainForm.cs
// PdfiumViewer: PdfDocument.GetPdfText(page) returns the plain text of a page.
// sgcPDF: TsgcPDFDocument.ExtractTextW(page) is the same plain text, and
// TsgcPDFViewerControl.PageText(page) returns a TsgcPDFTextExtractor with the
// characters and their positions (GetTextWithPositions); the user can also select
// text with the mouse and copy it (SelectedText, CopyToClipboard)
string vText = FViewer.Document.ExtractTextW(APageIndex);
Log("Text of page " + sgcPDF_RTL.IntToStr(APageIndex + 1) + ": " + vText.Trim());
TsgcPDFTextExtractor vExtractor = FViewer.PageText(APageIndex);
if (vExtractor != null)
    Log("Characters with positions: " + sgcPDF_RTL.IntToStr(vExtractor.GetCharCount()));
return vText;

PdfiumViewer를 넘어서: 양식 채우기와 메모 추가

MainForm.cs
// PdfiumViewer: none (no AcroForm API). sgcPDF: AcroForm.FillField / SetCheckBox,
// then an incremental save keeps the original bytes and appends the change
TsgcPDFDocument vDoc = FViewer.Document;
if (vDoc.AcroForm.FindField("CustomerName") == null)
{
    Log("This document has no CustomerName field, open the generated sample");
    return;
}
vDoc.AcroForm.FillField("CustomerName", "ACME Ltd.");
vDoc.AcroForm.SetCheckBox("Approved", true);
FViewer.ClearCache();
FViewer.Invalidate();
vDoc.SaveIncremental(AFileName);
Log("Form filled and saved: " + AFileName);
MainForm.cs
// PdfiumViewer: none (annotations are only rendered). sgcPDF: the document's
// Annotations manager adds notes, free text, highlights, stamps, lines, shapes and
// ink; the viewer shows them after AnnotationsChanged
TsgcPDFDocument vDoc = FViewer.Document;
int vPage = FViewer.PageIndex;
TsgcPDFTextAnnotation vNote = vDoc.Annotations.AddText(vPage, 420, 760, 444, 784,
  "Migrated from PdfiumViewer to sgcPDF.");
vNote.Author = "sgcPDF demo";
vNote.SetColor(1.0, 0.9, 0.2);
vDoc.Annotations.AddHighlight(vPage, 72, 728, 330, 728, 72, 742, 330, 742);
FViewer.AnnotationsChanged();
vDoc.SaveIncremental(AFileName);
Log("Note and highlight added on page " + sgcPDF_RTL.IntToStr(vPage + 1) + ", saved: " + AFileName);

단계별 안내

작업이나 폼을 하나씩 옮기고, 이전과 이후의 출력 파일을 비교하세요.

Delphi: Quick PDF Library에서

1

유닛 추가

sgcPDF Source 폴더 또는 설치된 패키지를 추가하고, Quick PDF Library 임포트를 sgcPDF_Types, sgcPDF_Fonts, sgcPDF_Document로 바꿉니다. 필요하면 sgcPDF_Editor, sgcPDF_Encryption, sgcPDF_Renderer_GDI도 추가합니다.

2

DLL 제거

배포에서 DLL 또는 ActiveX를 제거하고, 코드에서 UnlockKey 호출을 제거합니다.

3

문서당 객체 하나

TQuickPDF 객체를 문서마다 TsgcPDFDocument로, 불러오기, 편집, 저장 작업에는 TsgcPDFEditor로 바꿉니다.

4

페이지는 객체

SelectPage와 그리기 호출을 AddPage 또는 Pages[i]에서 얻은 TsgcPDFPage의 호출로 바꾸고, 모든 페이지 번호에서 1을 뺍니다.

5

호출 매핑

위의 표를 사용하세요. 표준 글꼴은 DrawText의 인수이고, TrueType 글꼴은 AddTrueTypeFont로 한 번 추가한 뒤 DrawTextTT로 그립니다.

6

임포지션

CapturePage와 DrawCapturedPage를 AddPageAsForm과 DrawForm 또는 DrawFormInRect로 바꿉니다.

7

출력 비교

변환한 작업을 실행하고 파일을 확인하세요. 데모의 자체 테스트가 템플릿입니다. 각 출력을 다시 열어 페이지 수, 텍스트, 양식 값을 확인합니다.

WinForms: PdfiumViewer에서

1

네이티브 부분 제거

PdfiumViewer 패키지, 모든 PdfiumViewer.Native.* 패키지, 직접 복사한 pdfium.dll을 제거하고 x86과 x64 폴더도 지웁니다. 프로젝트를 AnyCPU로 되돌릴 수 있습니다.

2

sgcPDF 추가

esegece.sgcPDF.WinForms(또는 esegece.sgcPDF.WinForms.Community)를 추가하면 esegece.sgcPDF가 함께 설치됩니다. 그리고 using esegece.sgcPDF;를 추가합니다.

3

컨트롤 교체

PdfViewer 또는 PdfRenderer를 TsgcPDFViewerControl(Dock = Fill)로 바꾸고, 사용하던 도구 모음 버튼을 컨트롤의 호출로 다시 만듭니다.

4

문서 불러오기

PdfDocument.Load와 Document =를 LoadFromFile로 바꾸거나, TsgcPDFDocument를 직접 불러온 뒤 Document에 할당합니다.

5

멤버 매핑

Page는 PageIndex 또는 GotoPage가 되고, 확대/축소 모드는 TsgcPDFViewerZoomMode에 대응하며, 확대/축소 배율에는 100을 곱하고, Search는 FindText가, Render는 RenderPageToBitmap이 됩니다.

6

인쇄 코드 유지

PdfiumViewer 문서 대신 뷰어에서 CreatePrintDocument()를 호출하세요. PrintDialog와 PrintPreviewDialog 코드는 그대로 남습니다. 또는 PrintDialog(ATitle)를 사용하세요.

7

새 기능 켜기

선택 사항으로 FormFilling = true, AnnotationTool, SaveIncremental이 있으며, PdfiumViewer는 제공하지 못하던 기능입니다.

일대일로 대응하지 않는 것

옮기기 전에 먼저 읽어 보세요.

Quick PDF Library

PdfiumViewer

MigrateFromQuickPDF와 MigrateFromPdfiumViewer

두 데모는 자체 입력 파일을 생성하므로 외부 PDF가 필요 없고, 둘 다 자체 테스트가 있습니다.

Delphi: 위치

sgcUI 설치 프로그램이 Demos\PDF\Delphi\MigrateFromQuickPDF에 설치합니다. sgcPDF_Demo_MigrateFromQuickPDF.dpr, frmMain.pas, frmMain.dfm, readme.html이 들어 있습니다.

Delphi: 실행 방법

Delphi 7부터 13까지 아무 버전에서 .dpr을 열고(VCL, Win32 또는 Win64), Generate sample inputs를 클릭한 다음 아무 버튼이나 Run all을 클릭하세요. 출력은 exe 옆의 output 폴더에 저장됩니다.

Delphi: 자체 테스트

sgcPDF_Demo_MigrateFromQuickPDF.exe /selftest [folder]는 모든 작업을 실행하고 결과를 확인한 뒤 SELFTEST OK로 끝나는 selftest.log를 기록합니다.

.NET: 위치

sgcUI .NET 데모에서 sgcUI_Demos.sln 솔루션의 PDF\MigrateFromPdfiumViewer 폴더에 있습니다. sgcPDF_Demo_MigrateFromPdfiumViewer.csproj, Program.cs, MainForm.cs가 들어 있습니다.

.NET: 실행 방법

dotnet run --project demos\PDF\MigrateFromPdfiumViewer를 실행하고(Community 에디션은 -p:SgcCommunity=true 추가), Generate sample을 클릭하면 output\sample.pdf를 만들어 열어 줍니다. 그다음 아무 버튼이나 클릭하세요.

.NET: 자체 테스트

sgcPDF_Demo_MigrateFromPdfiumViewer.exe /selftest [folder]는 샘플을 열고, 탐색하고, 확대/축소하고, 높이에 맞추고, 회전하고, 검색하고, 렌더링하고, 인쇄 미리보기의 페이지 수를 세고, 텍스트를 추출하고, 양식을 채우고, 메모를 추가하고, 저장한 파일을 다시 엽니다. SELFTEST OK로 끝나는 selftest.log를 기록합니다.

두 라이브러리를 공정하게 말씀드리면, Quick PDF Library나 PdfiumViewer로 만든 애플리케이션은 지금 배포된 곳에서 계속 동작하며, Foxit은 자사 PDF SDK를 Quick PDF Library의 후속으로 제시합니다. PDF 코드를 애플리케이션에 컴파일되는 Pascal 또는 C# 소스로 두고, 배포할 네이티브 PDF 라이브러리 없이, 뷰어가 보여 주는 파일을 만들고 채우고 주석을 달고 서명하고 암호화하는 하나의 API를 원한다면 sgcPDF가 그 길입니다. 컴포넌트와 에디션은 sgcPDF 제품 페이지를 참고하세요.

최고의 가성비: All-Access모든 eSeGeCe 제품과 프리미엄 지원이 포함되어 연 €1,059부터 이용할 수 있어요.
All-Access 가격 보기

오늘 첫 PDF 작업을 옮겨 보세요

PDF가 포함된 sgcUI를 다운로드하거나 NuGet의 무료 Community 패키지를 추가하고, 함께 제공되는 MigrateFromQuickPDF 및 MigrateFromPdfiumViewer 데모로 첫 작업이나 폼을 옮겨 보세요.