PDFium Component Docs

Programmeervoorbeelden voor PDFium VCL

Kies een uitvoerbare demo

De democollectie beslaat 33 onderwerpen: 33 Delphi-projecten, 32 C++Builder-projecten en 33 Lazarus-projecten, in totaal 98 native projecten. In de hoofdmap van elk platform staan 24 complete workflowdemo's. Negen gerichte onderwerpen staan onder Miscellaneous, samen 26 native projecten over de drie platforms; XfaLab is beschikbaar voor Delphi en Lazarus

Open eerst een workflow uit de hoofdmap: PDFViewer voor een featuretour, CreatePDF voor live documentcreatie, ContentExtractionLab voor een directe inventaris, FormFill voor bewerkbare formulieren, StandardsLab voor validatie en conversie, of IntakeWorkbenchCli voor geautomatiseerde intake. Deze zes instappunten leveren direct werkende resultaten op; de gerichte voorbeelden hieronder zijn handig wanneer u één API in detail wilt inspecteren

Workflowdemo's in de hoofdmap

DemoGebruik het voorWaarin het verschilt van verwante demo's
PDFViewerAlgemene weergave en feature-evaluatieDe hoofdviewer combineert navigatie, zoeken, miniaturen, weergavemodi, afdrukken en een feature-overzicht
MultiPageViewerDoorlopende pagina's, spreads en omslagpagina-indelingenEen gericht layoutvoorbeeld met de ingebouwde selectie-API's van de viewer; gebruik PDFViewer voor de bredere viewer-ervaring
SplitViewPagina's of documenten vergelijken in aparte deelvenstersDemonstreert onafhankelijke weergaveposities en het sturen van commando's naar het actieve deelvenster, in plaats van een tweepagina-indeling in één weergave
SearchAndSelectZoekresultaten en selectie over pagina's heenEen resultatenlijst en zoekopties leggen de zoekworkflow directer bloot dan een werkbalk in de viewer
PrintPDFVoorvertoning en gewone afdruktakenPaginabereiken, schaling, voortgang en annuleren vormen de kern van de afdrukworkflow
ContentExtractionLabMeerdere contentcategorieën samen inspecterenTXT/JSON-inventarissen beschrijven objecten en tonen voorvertoningstekst; ze vervangen geen volledige export van tekst of afbeeldingsbestanden
ExtractImagesIngebedde afbeeldingsobjecten exporterenHaalt afbeeldingsbitmaps op in plaats van screenshots van hele pagina's; de ingebouwde fixture bevat op elk van twee pagina's twee echte afbeeldingsobjecten
TableExtractionLabTabellen detecteren en als CSV/JSON exporterenTabellen met en zonder rasterlijnen, samengevoegde cellen, vervolggroepen en confidence-instellingen staan los van platte-tekstextractie
AttachmentIngebedde bijlagen lezen, toevoegen en exporterenBewerkingen op de payload van bijlagen gaan verder dan het tonen van namen en groottes in ContentExtractionLab
BatchExportPaginabeelden exporteren uit meerdere documentenGestreamde uitvoer, status per bestand en geïsoleerde fouten laten batchverwerking zien in plaats van één enkele conversie
CreatePDFPagina-inhoud aanmaken met een live voorvertoningAlle drie de native varianten maken doorzoekbare tekst, vectorvormen, een echte rasterafbeelding, tabellen en een review-annotatie aan; opties bouwen de voorvertoning opnieuw op vóór een expliciete opslag
ImageToPDFPagina's opbouwen uit invoerafbeeldingsbestandenAfbeeldingslayout, passend schalen, volgorde en JPEG-afhandeling vormen een workflow voor documentconversie
MergePDFPagina's uit meerdere PDF's samenstellenDemonstreert documentimport en geordende samenstelling; splitsen behandelt de omgekeerde workflow
SplitPDFGeselecteerde paginagroepen naar aparte PDF's schrijvenUitvoerbenaming en validatie van paginagroepen verschillen van samenvoegen of paginabeeld-rendering
WatermarkStampHerhaalde overlays aanbrengen op bestaande pagina'sPlaatsing en batchgewijs stempelen van pagina's vullen de basis-API's voor documentcreatie aan
FormFillInteractieve AcroForm-invoer en flatteningVeldinvoer en opgeslagen appearances verschillen van XFDF-uitwisseling en XFA-specifiek gedrag
AccessibilityReaderInteractief lezen en spraakDe GUI-lezer demonstreert leesnavigatie en markering in plaats van een compliance-audit
AccessibilityWorkbenchCliBatchgewijze accessibility-review en rapportgeneratieBevindingen, samenvattingen en review-gates dienen automatisering; bevindingen zijn geen vervanging voor handmatige accessibility-review
StandardsLabValidatie en conversie voor specifieke standaardenDe interactieve lab ontsluit bewerkingen en opties in plaats van alleen een totaalrapport te genereren
PreflightReportInteractieve standaardrapportenDe GUI ondersteunt handmatige inspectie en rapportexport
PreflightReportCliGeautomatiseerde standaardrapportenBatch-invoer, rapportformaten en exit-code-gates leveren de automatiseringsvariant van PreflightReport
IntakeWorkbenchCliBatch-intake, triage en routeringGeaggregeerde rapporten, drempels voor mislukte runs en routeringsbeslissingen maken dit een verwerkingsworkflow die verder gaat dan de SecurityAudit-GUI

Gerichte voorbeelden in Miscellaneous

Open deze projecten vanuit Demo\Delphi\Miscellaneous, Demo\CBuilder\Miscellaneous of Demo\Lazarus\Miscellaneous. Ze bewaren nuttige API-recepten en gerichte exporttaken, terwijl de hoofdmap zich op complete ervaringen richt. Eenvoudige controles waarbij Unicode-tekst wordt weggeschreven en opnieuw geladen, vallen onder de workflows voor documentcreatie en extractie; aparte demoprojecten zijn er niet meer

DemoGebruik het voorWaarin het verschilt van verwante demo's
SecurityAuditDe security posture interactief inspecterenDe GUI benadrukt rechten, scripts, handtekeningen en beveiligingsdetails in plaats van bestandsroutering
XfdfLabXFDF-gegevens importeren en exporterenUitwisseling plus een expliciete opslag van de geïmporteerde PDF tonen persistentie; alleen XFDF exporteren slaat de gewijzigde PDF niet op
AccessibilityLabDe reader-API's doorlopen in een consoleEen compacte, uitvoerbare rondleiding toont leeseenheden, woordkaders, structuur en speech-script-uitvoer
ExtractTextVolledige tekst exporteren van geselecteerde pagina'sTekstlaag-uitvoer, paginascheidingstekens en annuleren onderscheiden zich van inventarisvoorvertoningen en tabeldetectie; er wordt geen OCR uitgevoerd
FontPropertiesFont- en karaktermetrics inspecterenOpent met echte font- en karaktermetrics voor het eerste tekstobject; selecteer een andere regel om fonts te vergelijken zonder documentpayloads te exporteren
NavigationLabBladwijzers, bestemmingen en navigatieactiesDe compacte API-rondleiding vult de zichtbare navigatiebediening van PDFViewer aan
PDFtoJpgÉén document renderen naar paginabeeldenEen compact rendervoorbeeld voor één document; Delphi ontsluit discrete paginabereiken, terwijl BatchExport zich richt op meerdere invoerdocumenten
PrintPreferencesN-up-vellen en auteur-printvoorkeurenKopieën, filters op oneven/even en door de auteur opgegeven voorkeuren staan centraal; dit is een aanvulling op PrintPDF
ViewerInteractionLabMuis-, toetsenbord- en coördinaatinteracties diagnosticerenHet interactielog en de omzetting tussen pagina- en apparaatcoördinaten maken het een diagnostiektool voor de API
XfaLabStatische XFA-packets en runtime-mogelijkhedenOpent template- en datasets-packets met de gewone runtime; interactieve XFA-weergave vereist een runtime met XFA-ondersteuning, met varianten voor Delphi en Lazarus

Begin met een werkende featuretour

PDFViewer opent zijn meegeleverde PDFiumDemoShowcase.pdf, een document van zes pagina's met doorzoekbare tekst, vectorgrafieken, twee ingebedde afbeeldingen, een tabel, vier AcroForm-velden, hoofdstukbladwijzers, links, een review-notitie en twee bestandsbijlagen. De experience-bar biedt Restart showcase, Find live text, 2-page spread, Night reading, Inspect this PDF en Explore forms; elke actie werkt op het huidige document

CreatePDF opent een live rapportvoorvertoning van twee pagina's. Bewerk de titel en auteur of wissel vormen, de tabel en het watermerk om echte pagina-inhoud opnieuw op te bouwen; de Unicode-optie voegt een derde pagina toe. Er wordt niets weggeschreven tot u opslaat, en de opgeslagen PDF blijft doorzoekbaar

MultiPageViewer, SearchAndSelect, ContentExtractionLab en FormFill openen hetzelfde document voor hun eigen workflows, met zoekresultaten, een extractie-inventaris en bewerkbare velden direct gereed. Miscellaneous\NavigationLab gebruikt zijn eigen lokale kopie voor een rondleiding langs de bladwijzer- en bestemmings-API's

Attachment start met twee echte ingebedde bestanden. PrintPreferences start met vier pagina's en auteursvoorkeuren voor twee kopieën, geselecteerde paginabereiken, schaling en duplex; de huidige printworkflow past kopieën en paginabereiken toe, terwijl schaling en duplex worden geïnspecteerd en gerapporteerd. XfaLab start met echte template- en datasets-packets voor statische XFA-inspectie; interactieve XFA-weergave vereist een geschikte runtime en is een aparte mogelijkheid

Elk weergave-, formulier-, extractie- en navigatieproject bevat zijn eigen PDFiumDemoShowcase.pdf. Kopieer de projectmap en houd deze meegeleverde invoer naast de gedistribueerde executable; Lazarus-builds zetten hem automatisch klaar. De tour werkt offline, en algemene viewers en extractievoorbeelden bieden ook gegenereerde fallback-content wanneer de lokale PDF niet beschikbaar is

De native voorbeelden kopiëren en onderhouden

Elke native demo bevat zijn eigen voorbeeldimplementatie. De Delphi- en Lazarus-instappunten voor AccessibilityLab, AccessibilityWorkbenchCli, IntakeWorkbenchCli en PreflightReportCli bevatten de volledige workflow in de projectmap, inclusief compilerspecifieke initialisatie en het schrijven van JPEG's. De voorbeelden voor bijlagen, printvoorkeuren en XFA bouwen hun eigen featurespecifieke invoer ook lokaal op. Buiten het gekopieerde project zijn alleen de library, de bijpassende native runtime en de normale afhankelijkheden van het compilerframework nodig

Kies extractie van afbeeldingsobjecten wanneer ingebedde bitmaps nodig zijn, paginarendering wanneer de zichtbare pagina nodig is, en tekstextractie wanneer de PDF al een tekstlaag heeft. Een rapport dat deze categorieën opsomt, exporteert niet hun volledige payloads. Deze grenzen houden de gerichte voorbeelden nuttig zonder dat elke demo uitgroeit tot weer een andere algemene viewer of workbench

Basis documentbewerkingen

Een PDF-document laden en weergeven

Pdf1.FileName := 'C:\MyDocument.pdf';
Pdf1.Active := True;
ShowMessage('Pages: ' + IntToStr(Pdf1.PageCount));
ShowMessage('Title: ' + Pdf1.Title);
ShowMessage('Author: ' + Pdf1.Author);

var
  Stream: TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  try
    Stream.LoadFromFile('C:\MyDocument.pdf');
    Pdf1.LoadDocument(Stream, True);
    Pdf1.Active := True;
    ShowMessage('PDF loaded from stream');
  finally
    Stream.Free;
  end;
end;

Een nieuw PDF-document maken

Pdf1.CreateDocument;
Pdf1.Active := True;
Pdf1.AddPage(0, 612, 792);
Pdf1.PageNumber := 1;
Pdf1.AddText('Hello World!', 'Arial', 12, 100, 700, clBlack, $FF, 0.0);
Pdf1.UpdatePage;
Pdf1.SaveAs('C:\NewDocument.pdf');
Pdf1.Active := False;

Tekstbewerkingen

Tekst extraheren uit een PDF

var
  PageText: WString;
  RectText: WString;
begin
  Pdf1.PageNumber := 1;
  PageText := Pdf1.Text;
  Memo1.Text := PageText;
  RectText := Pdf1.TextInRectangle(100, 100, 500, 200);
  ShowMessage('Text in rectangle: ' + RectText);
end;

Tekst zoeken

var
  Position: Integer;
begin
  Position := Pdf1.FindFirst('Hello', [seCaseSensitive]);
  while Position >= 0 do
  begin
    ShowMessage('Found at character: ' + IntToStr(Position));
    Position := Pdf1.FindNext;
  end;
end;

Tekst met opmaak toevoegen

Pdf1.PageNumber := 1;
Pdf1.AddText('Document Title', 'Times New Roman', 16, 100, 750, clBlue);
Pdf1.AddText('This is the document content.', 'Arial', 12, 100, 700, clBlack);
Pdf1.UpdatePage;

Karakter- en font-metadata inspecteren

var
  I: Integer;
  MetricSize: Single;
  FontBytes: TBytes;
begin
  Pdf1.PageNumber := 1;
  for I := 0 to Pdf1.ObjectCount - 1 do
    if Pdf1.ObjectType[I] = otText then
    begin
      MetricSize := 12.0;
      FontBytes := Pdf1.FontData[I];
      Memo1.Lines.Add('Object ' + IntToStr(I));
      Memo1.Lines.Add('Base name: ' + Pdf1.FontBaseName[I]);
      Memo1.Lines.Add('Family: ' + Pdf1.FontFamilyName[I]);
      Memo1.Lines.Add('Embedded: ' + BoolToStr(Pdf1.FontIsEmbedded[I], True));
      Memo1.Lines.Add('Weight: ' + IntToStr(Pdf1.FontWeight[I]));
      Memo1.Lines.Add('Italic angle: ' + IntToStr(Pdf1.FontItalicAngle[I]));
      Memo1.Lines.Add('Ascent: ' + FloatToStr(Pdf1.FontAscent[I, MetricSize]));
      Memo1.Lines.Add('Descent: ' + FloatToStr(Pdf1.FontDescent[I, MetricSize]));
      Memo1.Lines.Add('Font data bytes: ' + IntToStr(Length(FontBytes)));
    end;

  if Pdf1.CharacterCount > 0 then
  begin
    Memo1.Lines.Add('First character size: ' + FloatToStr(Pdf1.CharacterFontSize[0]));
    Memo1.Lines.Add('First character weight: ' + IntToStr(Pdf1.CharacterFontWeight[0]));
    Memo1.Lines.Add('First character angle: ' + FloatToStr(Pdf1.CharacterAngle[0]));
  end;
end;

De projecten Demo\Delphi\Miscellaneous\FontProperties, Demo\CBuilder\Miscellaneous\FontProperties en Demo\Lazarus\Miscellaneous\FontProperties tonen dezelfde metadata via zowel TPdf als TPdfView

Een rapport voor inhoudsextractie met meerdere categorieën bouwen

De projecten Demo\Delphi\ContentExtractionLab, Demo\CBuilder\ContentExtractionLab en Demo\Lazarus\ContentExtractionLab maken van inhoudsextractie één workflow. Ze openen of maken een PDF, laten gebruikers metadata, paginatekst, pagina-objecten, afbeeldingen, bijlagen, links, annotaties, bladwijzers en font-/karaktermetrics kiezen, en genereren vervolgens een samenvatting plus een gedetailleerd TXT- of JSON-rapport. De lab bevat ook alle / geen categorie-selectie, rapport-kopiëren-naar-klembord en bron-PDF-opslag-acties, zodat gebruikers de gegenereerde voorbeeld-PDF naast zijn extractierapport kunnen bewaren. ExtractImages en Attachment verzorgen workflows voor payload-export, terwijl Miscellaneous\ExtractText en Miscellaneous\FontProperties gerichte API-voorbeelden blijven; ExtractText ondersteunt opties voor paginabereik en paginascheidingstekens om tekstuitvoer per pagina te produceren in Delphi, C++Builder en Lazarus, terwijl ContentExtractionLab het overkoepelende inventarisvoorbeeld is

Tabellen detecteren en extraheren

De projecten Demo\Delphi\TableExtractionLab, Demo\CBuilder\TableExtractionLab en Demo\Lazarus\TableExtractionLab maken van tabeldetectie één werkstroom. De lab bouwt een voorbeelddocument met een tabel met rasterlijnen en samengevoegde kopcellen, een tabel die zonder lijnen op witruimte is uitgelijnd en een lange tabel die over een paginagrens heen afbreekt, draait vervolgens ExtractTables voor de huidige pagina of ExtractDocumentTables voor het hele document en rapporteert rijen, kolommen, RowSpan- en ColumnSpan-waarden, kopvlaggen, detectiemodus, confidence en vervolggroepen. De opties DetectRuledTables, DetectWhitespaceTables, DetectContinuations, DetectFilledRulings en MinConfidence zijn in de gebruikersinterface te bewerken, en de geselecteerde tabel wordt geëxporteerd via TPdfTable.ToCsv en TPdfTable.ToJson. De lab batcht ook een hele map: Batch folder draait ExtractDocumentTables over elke PDF, rapporteert tabellaantallen per document, vlagt scans zonder tekstlaag en probeert lege documenten opnieuw met een voorinstelling voor compacte kolommen; Export all CSV schrijft elke gedetecteerde tabel naast de bronbestanden. Elk document opent in zijn eigen TPdf-instantie, zodat één onleesbaar bestand de rest van de batch niet kan beïnvloeden

Formulierbewerkingen

Met formuliervelden werken

var
  I: Integer;
  FieldInfo: TPdfFormFieldInfo;
begin
  Pdf1.FormField[0] := 'John';
  for I := 0 to Pdf1.FormFieldCount - 1 do
  begin
    FieldInfo := Pdf1.FormFieldInfo[I];
    ShowMessage(FieldInfo.Name + ': ' + Pdf1.FormField[I]);
  end;
end;

Ingevulde formulierwaarden afvlakken in de pagina

// Zonder afvlakken schrijft FormField[i] := value alleen de /V-entry —
// de zichtbare appearance komt uit de /AP-stream en kan mogelijk niet
// vernieuwen. GenerateFormAppearances regenereert /AP voor elk widget,
// daarna bakt FlattenAllPages alle annotaties en widgets van elke pagina
// in als permanente, niet-bewerkbare inhoud.
Pdf1.FileName := 'C:\Application.pdf';
Pdf1.Active := True;
Pdf1.FormField[0] := 'John Smith';
Pdf1.FormField[1] := '[email protected]';
Pdf1.GenerateFormAppearances;
if Pdf1.FlattenAllPages then
  Pdf1.SaveAs('C:\Application.flat.pdf');
Pdf1.Active := False;

Afbeeldingsbewerkingen

Afbeeldingen extraheren

var
  I: Integer;
  Bitmap: TBitmap;
begin
  for I := 0 to Pdf1.BitmapCount - 1 do
  begin
    Bitmap := Pdf1.Bitmap[I];
    try
      Bitmap.SaveToFile('C:\ExtractedImage' + IntToStr(I) + '.bmp');
    finally
      Bitmap.Free;
    end;
  end;
end;

Afbeeldingen toevoegen

var
  JpegStream: TFileStream;
begin
  JpegStream := TFileStream.Create('C:\MyImage.jpg', fmOpenRead or fmShareDenyWrite);
  try
    Pdf1.AddJpegImage(JpegStream, 100, 500, 200, 150);
  finally
    JpegStream.Free;
  end;
  Pdf1.AddPicture(Image1.Picture, 100, 300, 150, 100);
  Pdf1.UpdatePage;
end;

Annotatiebewerkingen

Met annotaties werken

var
  I: Integer;
  Annotation: TPdfAnnotation;
begin
  for I := 0 to Pdf1.AnnotationCount - 1 do
  begin
    Annotation := Pdf1.Annotation[I];
    ShowMessage('Annotation ' + IntToStr(I) + ': ' + Annotation.ContentsText);
  end;
end;

Tekenbewerkingen

Vormen tekenen

Pdf1.CreatePath(100, 100, 200, 150, fmAlternate, clYellow, $FF, True, clBlack, $FF, 2.0);
Pdf1.AddPath;

Pdf1.CreatePath(100, 100, fmNone, clBlack, $FF, True, clRed, $FF, 3.0);
Pdf1.LineTo(200, 100);
Pdf1.LineTo(150, 200);
Pdf1.ClosePath;
Pdf1.AddPath;
Pdf1.UpdatePage;

Navigatie en bladwijzers

Met bladwijzers werken

var
  I: Integer;
  Bookmarks: TBookmarks;
begin
  Bookmarks := Pdf1.Bookmarks;
  for I := 0 to Length(Bookmarks) - 1 do
    ShowMessage(Bookmarks[I].Title + ' -> Page ' + IntToStr(Bookmarks[I].PageNumber));
end;

Met benoemde bestemmingen werken

var
  I: Integer;
  Destination: TDestination;
begin
  for I := 0 to Pdf1.DestinationCount - 1 do
  begin
    Destination := Pdf1.Destination[I];
    if Destination.Name = 'Chapter1' then
    begin
      Pdf1.PageNumber := Destination.PageNumber;
      Break;
    end;
  end;
end;

Bijlagebewerkingen

Met bijlagen werken

var
  I: Integer;
  AttachmentData: TBytes;
  AttachmentName: WString;
  FileStream: TFileStream;
begin
  for I := 0 to Pdf1.AttachmentCount - 1 do
  begin
    AttachmentName := Pdf1.AttachmentName[I];
    AttachmentData := Pdf1.Attachment[I];
    FileStream := TFileStream.Create('C:\Extracted_' + string(AttachmentName), fmCreate);
    try
      if Length(AttachmentData) > 0 then
        FileStream.WriteBuffer(AttachmentData[0], Length(AttachmentData));
    finally
      FileStream.Free;
    end;
  end;
  if Pdf1.CreateAttachment('MyFile.txt') then
    Pdf1.Attachment[Pdf1.AttachmentCount - 1] := TFile.ReadAllBytes('C:\MyFile.txt');
end;

Paginabeheer

Paginabewerkingen

Pdf1.AddPage(Pdf1.PageCount + 1, 612, 792);
Pdf1.AddPage(Pdf1.PageCount + 1, 595, 842);
Pdf1.AddPage(Pdf1.PageCount + 1, 400, 600);

var
  SourcePdf: TPdf;
begin
  SourcePdf := TPdf.Create(nil);
  try
    SourcePdf.FileName := 'C:\SourceDocument.pdf';
    SourcePdf.Active := True;
    Pdf1.ImportPages(SourcePdf, '1', Pdf1.PageCount + 1);
  finally
    SourcePdf.Free;
  end;
end;

if Pdf1.PageCount > 1 then
  Pdf1.DeletePage(Pdf1.PageCount);

Opslaan en compressie

Opslaan met compressie

// Maak een gecomprimeerd PDF-document
Pdf1.CreateDocument;
Pdf1.Compressed := True; // zorg dat alle streams FlateDecode-gecomprimeerd zijn (standaard)
Pdf1.Active := True;
Pdf1.AddPage(0, 595, 842); // A4-formaat
Pdf1.AddText('Hello World!', 'Arial', 24, 100, 700, clBlack, $FF, 0.0);
Pdf1.SaveAs('C:\Compressed.pdf');
Pdf1.Active := False;

// Opslaan met opties
Pdf1.SaveAs('C:\Output.pdf', saIncremental); // incrementeel opslaan
Pdf1.SaveAs('C:\NoSecurity.pdf', saRemoveSecurity); // beveiliging verwijderen

// Opslaan met specifieke PDF-versie als doel. De PDF-versie-validator
// weigert elke functie die na de gekozen doelversie is geïntroduceerd
// (JBIG2Decode, MarkInfo, AES-versleuteling, Polygon / Caret / Watermark /
// Redact-annotaties, ...).
if not Pdf1.SaveAs('C:\Legacy15.pdf', saNone, pv15) then
  ShowMessage('Save rejected: document contains features newer than PDF 1.5');

PDF/A-1b archiveringsuitvoer maken

// SaveAsPdfA nabewerkt de basisopslag met een incrementele update die een
// XMP-metadatastream, een sRGB ICC OutputIntent en een bijgewerkte
// documentcatalogus injecteert zodat het resultaat PDF/A-1b-conform is.
// Het meegeleverde sRGB IEC61966-2.1-profiel wordt automatisch gebruikt
// wanneer geen aangepast profiel wordt geleverd.
Pdf1.FileName := 'C:\Report.pdf';
Pdf1.Active := True;
if Pdf1.SaveAsPdfA('C:\Report.pdfa.pdf', pac1b) then
  ShowMessage('Saved PDF/A-1b archive');

// PDF/A met een aangepast ICC-profiel (bijvoorbeeld voor CMYK-print-pijplijnen)
var
  Opts: TPdfASaveOptions;
begin
  Opts := Default(TPdfASaveOptions);
  Opts.Conformance    := pac1b;
  Opts.IccProfileData := TFile.ReadAllBytes('C:\Profiles\Coated_GRACoL_2006.icc');
  Pdf1.SaveAsPdfA('C:\Report.cmyk.pdfa.pdf', Opts);
end;

// PDF/A-uitvoer in het geheugen
var
  Stream: TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  try
    Opts := Default(TPdfASaveOptions);
    Opts.Conformance := pac1b;
    if Pdf1.SaveAsPdfAToStream(Stream, Opts) then
      UploadToArchive(Stream);
  finally
    Stream.Free;
  end;
end;

PDF/A-conformiteit valideren

var
  Validation: TPdfAValidationResult;
  Issue: TPdfAValidationIssue;
begin
  Pdf1.FileName := 'C:\Incoming\report.pdf';
  Pdf1.Active   := True;

  // Goedkope header-stijl probe — leest de conformiteit zonder de
  // volledige validator te itereren. Resultaat: pacNone, pac1a, pac1b,
  // pac2b, pac3b of pacUnknown.
  case Pdf1.PdfAConformance of
    pac1b: Status.Caption := 'PDF/A-1b';
    pac2b: Status.Caption := 'PDF/A-2b';
    pacNone: Status.Caption := 'Not PDF/A';
  else
    Status.Caption := 'Unknown conformance';
  end;

  // Volledige validator met diagnostiek per probleem
  Validation := Pdf1.ValidatePdfA;
  Memo1.Lines.Add('Conformance: ' + GetEnumName(TypeInfo(TPdfAConformance),
    Ord(Validation.Conformance)));
  for Issue in Validation.Issues do
    Memo1.Lines.Add('- ' + Issue.Description);
end;

Meerdere PDF-standaarden inspecteren in StandardsLab

De projecten Demo\Delphi\StandardsLab, Demo\CBuilder\StandardsLab en Demo\Lazarus\StandardsLab laden of maken een PDF, voeren ValidatePdfA, ValidatePdfUa, ValidatePdfE, ValidatePdfX, ValidatePdfR en ValidatePdfVT uit en tonen vervolgens elk gedetecteerd conformiteitsniveau en aantal problemen in één raster. Hun save-knoppen roepen SaveAsPdfA, SaveAsPdfUa, SaveAsPdfE, SaveAsPdfX, SaveAsPdfR en SaveAsPdfVT aan, zodat de marker-output-workflow zichtbaar is zonder een aangepast harnas te schrijven

Preflight-rapporten genereren

De unit FPdfPreflightReport wikkelt ValidatePdfA, ValidatePdfUa, ValidatePdfE, ValidatePdfX, ValidatePdfR en ValidatePdfVT in één doorzoekbaar rapportobject met ernst Info / Warning / Error, aggregatie van status en problemen, opzoeken, zoeken, filtering en stabiele SHA-256-vingerafdrukken. Rapporten kunnen worden uitgevoerd als tekst, HTML, Markdown, JSON, CSV, SARIF 2.1.0, JUnit XML, NDJSON of native XML. Demo\Delphi\PreflightReport, Demo\Lazarus\PreflightReport en Demo\CBuilder\PreflightReport bieden interactieve selectie- en voorvertoningsworkflows, terwijl Demo\Delphi\PreflightReportCli scriptbare invoer-/uitvoerargumenten, filtering op standaard, optionele inbedding van rapportbijlagen, CI-exitcode-gating, batchverwerking via lijsten en mappen, collision-veilige routering, samenvattende totalen en CSV-manifesten toevoegt. Het gegenereerde rapport vermeldt dat de ingebouwde validators marker-level- en geselecteerde file-level-checks dekken, zodat volledige content-level preflight nog steeds kan worden gedelegeerd aan een gespecialiseerde validatie-engine

Streaming-load en grote documenten

Een PDF op aanvraag laden met LoadCustomDocument

// LoadCustomDocument laat PDFium blokken ophalen uit elke seekable TStream
// op aanvraag. De stream wordt NIET naar het geheugen gekopieerd, zodat
// PDF's van meerdere GB, remote HTTP body streams en databasegebaseerde
// bronnen allemaal haalbaar zijn zonder een vooraf gemaakte buffer.
var
  FileStream: TFileStream;
begin
  // Streamen vanuit bestand (geen kopie in geheugen)
  FileStream := TFileStream.Create('C:\Huge.pdf',
    fmOpenRead or fmShareDenyWrite);
  Pdf1.LoadCustomDocument(FileStream, True{AOwnsStream});
  // ^^ eigendom overgedragen — Pdf1 vrijgeeft FileStream bij UnloadDocument.
  Pdf1.Active := True;
  ShowMessage('Pages: ' + IntToStr(Pdf1.PageCount));
end;

// Stream in extern beheer (aanroeper geeft hem vrij na UnloadDocument)
var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create('C:\Live.pdf',
    fmOpenRead or fmShareDenyNone);
  try
    Pdf1.LoadCustomDocument(Stream, False);
    Pdf1.Active := True;
    DoWork;
    Pdf1.Active := False;
  finally
    Stream.Free;
  end;
end;

Async-annulering en progressieve rendering

Coöperatieve annuleringstokens

// FPdfAsync biedt IPdfCancellationToken / IPdfCancellationTokenSource voor
// cancel-from-UI-semantiek die werkt over de langlopende export- en
// renderpaden.
uses FPdfAsync;

var
  CancelSource: IPdfCancellationTokenSource;
  CancelToken:  IPdfCancellationToken;
begin
  CancelSource := PdfCancellationTokenSource;
  CancelToken  := CancelSource.Token;

  // ... gebruiker klikt op Annuleren ...
  CancelSource.Cancel;

  // De worker controleert periodiek CancelToken.IsCancelled, of het
  // renderpad peilt het via PDFium's IFSDK_PAUSE-callback.
  if CancelToken.IsCancelled then
    Memo1.Lines.Add('Cancelled by user');
end;

Annuleerbare progressieve pagina-render

// RenderPageProgressive laat een lange high-DPI-render halverwege de
// pagina afbreken wanneer de gebruiker op Annuleren klikt, in plaats van
// de aanroeper te blokkeren tot het klaar is.
var
  Status: TPdfProgressiveStatus;
  Bitmap: TBitmap;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.PixelFormat := pf32bit;
    Bitmap.SetSize(2480, 3508); // A4 @ 300 DPI

    Status := Pdf1.RenderPageProgressive(Bitmap, 0, 0, Bitmap.Width,
      Bitmap.Height, CancelToken, ro0, [reAnnotations], clWhite);

    case Status of
      prsDone:      SaveBitmap(Bitmap);
      prsCancelled: Memo1.Lines.Add('Render cancelled — partial result available');
      prsFailed:    Memo1.Lines.Add('PDFium reported FPDF_RENDER_FAILED');
    end;
  finally
    Bitmap.Free;
  end;
end;

Renders draaien op een achtergrondthread met TPdfFuture

// TPdfFuture<T> start een worker op een achtergrondthread en stuurt een
// TPdfFutureResult<T>-envelop terug naar de hoofdthread.
//
// Belangrijk: TPdf serialiseert render-aanroepen per instance, maar de
// worker beheert nog steeds dispatch en levensduur van het document. Muteer
// geen TPdf terwijl een render onderweg is; batch-export houdt meestal één
// TPdf per bestand aan.
type
  TRenderResult = record
    Bitmap : TBitmap;
    PageNo : Integer;
  end;

var
  Future: TPdfFuture<TRenderResult>;
begin
  Future := TPdfFuture<TRenderResult>.Create(
    function (const ACancelToken: IPdfCancellationToken): TRenderResult
    var
      LocalPdf: TPdf;
    begin
      LocalPdf := TPdf.Create(nil);
      try
        LocalPdf.FileName := 'C:\Huge.pdf';
        LocalPdf.Active   := True;
        LocalPdf.PageNumber := 1;
        Result.Bitmap := LocalPdf.RenderPage(0, 0, 2480, 3508);
        Result.PageNo := 1;
      finally
        LocalPdf.Free;
      end;
    end,
    procedure (const AResult: TPdfFutureResult<TRenderResult>)
    begin
      case AResult.State of
        pfsSuccess:   PaintBitmapToView(AResult.Value.Bitmap);
        pfsCancelled: Log.Add('Cancelled');
        pfsFailed:    Log.Add('Worker failed: ' + AResult.ErrorMessage);
      end;
    end);
end;

Transformatie-matrices

Translate / Scale / Rotate / Skew componeren

// FPdfMatrix wikkelt PDFium's FS_MATRIX zodat aanroepers een transform
// declaratief kunnen bouwen en aan FPDFPageObj_SetMatrix kunnen overdragen.
uses FPdfMatrix, FPdfView;

var
  M: TPdfMatrix;
  RawMatrix: FS_MATRIX;
  PageObj: FPDF_PAGEOBJECT;
begin
  M := TPdfMatrix.Create;
  try
    M.Translate(72, 200);       // verplaats 1in naar rechts, ~2.8in omhoog
    M.Scale(0.5, 0.5);          // half-formaat stempel
    M.Rotate(15);               // 15 graden CCW-rotatie
    // M.HorizontalFlip;
    // M.VerticalFlip;
    // M.CentralFlip;
    // M.Skew(10, 5);
    // M.Multiply(Other);       // post-multipliceer met een andere matrix

    // Toepassen op elk PDFium-pagina-object (text / path / image / form XObject)
    RawMatrix := M.Handle;
    FPDFPageObj_SetMatrix(PageObj, RawMatrix);
  finally
    M.Free;
  end;
end;

Paginacompositie

Een subset pagina's importeren op basis van index

// ImportPagesByIndex kopieert een expliciete zero-based index-array van
// een bron-PDF naar dit document. InsertAt = 0 voegt in vóór pagina 1;
// PageCount voegt toe aan het einde.
var
  Source: TPdf;
begin
  Source := TPdf.Create(nil);
  try
    Source.FileName := 'C:\Report.pdf';
    Source.Active   := True;

    // Importeer pagina's 0, 2, 4 (one-based: pagina's 1, 3, 5) uit Source
    // en voeg ze toe aan het einde van Pdf1.
    Pdf1.ImportPagesByIndex(Source, [0, 2, 4], Pdf1.PageCount);

    // Een lege array importeert elke bronpagina
    // Pdf1.ImportPagesByIndex(Source, [], 0);
  finally
    Source.Free;
  end;
end;

N-up samengestelde uitvoer

// ImportNPagesToOne retourneert een gloednieuwe TPdf waarvan de pagina's
// NumX*NumY composieten zijn van DIT document. OutputWidth/Height zijn
// PDF-user-units (1 unit = 1/72 in).
var
  Composite: TPdf;
begin
  Pdf1.FileName := 'C:\Slides.pdf';
  Pdf1.Active   := True;
  // 4-up A4 landschap: 842 x 595 pt, 2 kolommen x 2 rijen
  Composite := Pdf1.ImportNPagesToOne(842, 595, 2, 2);
  try
    if Composite <> nil then
      Composite.SaveAs('C:\Slides_4up.pdf');
  finally
    Composite.Free;
  end;
end;

Pagina's in-place herordenen

// MovePages neemt de zero-based indices van de te verplaatsen pagina's
// plus de doelindex voor de eerste verplaatste pagina nadat de verplaatsing
// is voltooid. Andere pagina's schuiven rond het verplaatste blok zodat de
// documentlengte hetzelfde blijft.
//
// Voorbeeld: in een document van 5 pagina's met pagina's [0,1,2,3,4],
// herordent MovePages([2, 3], 0) naar [2, 3, 0, 1, 4].
if not Pdf1.MovePages([2, 3], 0) then
  ShowMessage('Invalid indices passed to MovePages');

Watermerken via hergebruik van pagina's met Form XObject

// CreateXObjectFromPage maakt een herbruikbare Form XObject-handle van
// elke pagina van elke andere TPdf. Stempel die handle op zoveel pagina's
// van DIT document als u wilt — elke stempel is één PDFium-pagina-object
// dat kan worden gepositioneerd, geschaald en geroteerd via de matrix-API.
uses FPdfMatrix, FPdfView;

var
  WatermarkSource: TPdf;
  XObj:            TPdfXObject;
  PageObj:         FPDF_PAGEOBJECT;
  M:               TPdfMatrix;
  RawMatrix:       FS_MATRIX;
  I:               Integer;
begin
  WatermarkSource := TPdf.Create(nil);
  try
    WatermarkSource.FileName := 'C:\Watermarks\Confidential.pdf';
    WatermarkSource.Active   := True;

    // Wikkel pagina 0 van WatermarkSource in als herbruikbaar XObject
    XObj := Pdf1.CreateXObjectFromPage(WatermarkSource, 0);
    try
      for I := 1 to Pdf1.PageCount do
      begin
        Pdf1.PageNumber := I;
        PageObj := Pdf1.InsertFormObjectFromXObject(XObj);
        if PageObj = nil then Continue;

        // Centreer het watermerk op de pagina
        M := TPdfMatrix.Create;
        try
          M.Scale(0.5, 0.5);
          M.Translate(0.25 * Pdf1.PageWidth, 0.5 * Pdf1.PageHeight);
          RawMatrix := M.Handle;
          FPDFPageObj_SetMatrix(PageObj, RawMatrix);
        finally
          M.Free;
        end;

        Pdf1.UpdatePage;
      end;
    finally
      XObj.Free; // sluit de FPDF_XOBJECT-handle
    end;

    Pdf1.SaveAs('C:\Watermarked.pdf');
  finally
    WatermarkSource.Free;
  end;
end;

De projecten Demo\Delphi\WatermarkStamp, Demo\Lazarus\WatermarkStamp en Demo\CBuilder\WatermarkStamp maken van dit patroon een uitvoerbare workflow: ze maken een doel-PDF en een herbruikbare stempel-PDF, wikkelen de stempelpagina in met CreateXObjectFromPage, voegen hetzelfde Form XObject in op elke doelpagina, passen TPdfMatrix-transformaties toe voor gecentreerde watermerken en stempels rechtsboven en voegen optionele paginanummerlabels toe vóór het opslaan van het resultaat

Afbeeldingsinvoeging (directe AddImage-overloads)

Een geregistreerd afbeeldingsbestand of een TBitmap toevoegen

// AddImage(FileName) accepteert elk formaat dat is geregistreerd bij de
// grafische units van VCL of LCL (BMP, PNG via PngImage, JPG, ...).
Pdf1.AddImage('C:\Photo.png', 100, 500, 200, 150);

// AddImage(TBitmap) slaat de tussenstap via TPicture over, ideaal wanneer
// de bitmap al uit rendering- of batch-generatiewerk komt.
var
  Bitmap: TBitmap;
begin
  Bitmap := Pdf1.RenderPage(0, 0, 595, 842);
  try
    Pdf1.PageNumber := 2;
    Pdf1.AddImage(Bitmap, 50, 50, 250, 350);
    Pdf1.UpdatePage;
  finally
    Bitmap.Free;
  end;
end;

De projecten Demo\Delphi\ImageToPDF, Demo\CBuilder\ImageToPDF en Demo\Lazarus\ImageToPDF maken hiervan een volledige batchworkflow: selecteer meerdere afbeeldingsbestanden, bekijk het geselecteerde item, maak één PDF-pagina per afbeelding, schaal elke afbeelding in een A4-staand- of liggende pagina, sla het resultaat op en open de gegenereerde PDF

Zoek-markering in de viewer

Markeer elke match op de huidige pagina

var
  MatchCount: Integer;
begin
  // Schilder een clYellow-masker over elke match op de huidige pagina van
  // de viewer. Wisselen naar een andere pagina wist de markering automatisch.
  PdfView1.HighlightColor := clYellow;
  MatchCount := PdfView1.HighlightSearchText('invoice', False{Case}, True{Word});
  Status.Caption := Format('%d match(es) on this page', [MatchCount]);

  // Verwijder de overlay programmatisch voordat de pagina wisselt
  PdfView1.ClearHighlight;
end;

Viewer-lay-out en paginakleur

Fit-modus en pagina-achtergrond

// FitMode houdt lange documenten ingekaderd tijdens Resize of paginawisselingen.
// Het rechtstreeks instellen van Zoom annuleert FitMode (wordt teruggezet naar pfmNone).
PdfView1.FitMode := pfmFitPage;       // hele pagina in viewport
// PdfView1.FitMode := pfmFitWidth;   // paginabreedte komt overeen met viewport-breedte
// PdfView1.FitMode := pfmActualSize; // 100%

// PageColor ontkoppelt de gerenderde PDF-pagina van de Color van de host-control
// — een typische donker-thema viewer-opzet houdt het scrollgebied donker terwijl
// de PDF-pagina papierwit blijft.
PdfView1.Color     := clBlack;        // scrollgebied
PdfView1.PageColor := clWhite;        // PDF-pagina-achtergrond

// Optionele slagschaduw en paginarand om de pagina van een donkere achtergrond te tillen
PdfView1.PageShadowSize  := 6;
PdfView1.PageShadowColor := $00404040;
PdfView1.PageBorderColor := clGray;

Viewer-interactie verkennen in ViewerInteractionLab

De projecten Demo\Delphi\Miscellaneous\ViewerInteractionLab, Demo\CBuilder\Miscellaneous\ViewerInteractionLab en Demo\Lazarus\Miscellaneous\ViewerInteractionLab houden de moderne TPdfView-interactie-oppervlakte in één compact formulier: open of maak een voorbeeld-PDF, wissel DisplayMode, pas FitMode toe, wijzig PageColor, roteer pagina's, markeer huidige-pagina-zoekresultaten met HighlightSearchText, schakel gebruikerstekstselectie in of uit, inspecteer SelectedText, roep SelectAll, CopySelectionToClipboard en ClearSelection aan, en bekijk hoe DeviceToPage-coördinaten in de statusbalk bijwerken terwijl de muis over de pagina beweegt

Tekst zoeken en selecteren in SearchAndSelect

De projecten Demo\Delphi\SearchAndSelect, Demo\CBuilder\SearchAndSelect en Demo\Lazarus\SearchAndSelect maken van de viewer-workflow voor zoeken en selecteren standalone voorbeelden. Ze openen of maken een PDF, vermelden zoekresultaten over alle pagina's met paginanummer, karakterindex en voorvertoningstekst, ondersteunen Vorige/Volgende-navigatie en dubbelklik-resultaat-springen, markeren huidige-pagina-matches met HighlightSearchText, stellen hoofdletter-/heel-woord-opties beschikbaar, schakelen AllowUserTextSelection aan/uit, bekijken SelectedText, sturen vanuit knoppen SelectAll, CopySelectionToClipboard en ClearSelection aan, en laten gebruikers wisselen tussen enkele en spread-weergavemodi

PDF-printvoorkeuren lezen in PrintPreferences

De projecten Demo\Delphi\Miscellaneous\PrintPreferences, Demo\CBuilder\Miscellaneous\PrintPreferences en Demo\Lazarus\Miscellaneous\PrintPreferences lezen auteur-printvoorkeuren vóór het afdrukken. Ze tonen PrintCopies, PrintPageRanges, PrintScaling en PrintPaperHandling, kunnen door de auteur opgegeven kopieën en bereiken kopiëren naar de print-invoeren, en laten zien hoe SetPdfPrintPaperHandlingDevMode de PDF-duplex-intentie vertaalt naar een Windows-DEVMODE

Standaard PDF-afdrukken in PrintPDF

De projecten Demo\Delphi\PrintPDF, Demo\CBuilder\PrintPDF en Demo\Lazarus\PrintPDF tonen de standaard print-workflow: open een PDF, bekijk pagina's vooraf, kies paginabereiken en kopieën in het platform-printdialoog, respecteer collate-modus, render elke pagina via TPdf.RenderPage en stel printvoortgang beschikbaar met annulering. Het Delphi-voorbeeld accepteert ook gesleepte PDF-bestanden voor snel laden

Snel pagina-doorbladeren in MultiPageViewer

De projecten Demo\Delphi\MultiPageViewer, Demo\CBuilder\MultiPageViewer en Demo\Lazarus\MultiPageViewer oefenen continue, spread- en omslag-bewuste weergave met reguliere pagina-navigatie- en zoom-workflows. Ze zijn ook nuttig voor het testen van open-to-first-page-snelheid en render-responsiviteit op zeer grote PDF's: in tests met grote bestanden kunnen documenten van 2,x GB die Acrobat of Foxit 20-30 seconden kunnen kosten vóór de eerste weergave, bijna onmiddellijk bruikbaar worden via het viewer-pad van PDFium Delphi Component

Naast elkaar bekijken in SplitView

De projecten Demo\Delphi\SplitView, Demo\CBuilder\SplitView en Demo\Lazarus\SplitView tonen PDF-beoordeling naast elkaar. De C++Builder- en Lazarus-voorbeelden richten zich op vergelijking in twee of drie panelen, selectie van actieve weergave, optionele gesynchroniseerde navigatie-commando's, gedeelde zoom-presets en rotatie voor de geselecteerde weergave of alle geladen weergaven. Gebruik deze voorbeelden om grote documenten te vergelijken terwijl de eerste bruikbare weergave en daaropvolgende pagina-rendering responsief blijven; dezelfde 2,x GB PDF-bestanden die Acrobat of Foxit 20-30 seconden nodig hebben om te openen, kunnen bijna onmiddellijk bruikbaar worden in het viewer-pad van PDFium Delphi Component

PDF-risico-oppervlak auditen in SecurityAudit

De projecten Demo\Delphi\SecurityAudit, Demo\CBuilder\SecurityAudit en Demo\Lazarus\SecurityAudit openen een PDF alleen-lezen en vermelden de status van rechten, ingebedde bijlagen, document-JavaScript-acties, URI- en Launch-linkannotaties, weblinks, samenvattingen van handtekeningen, XFA-status, beschikbaarheid van V8-helpers en niet-ondersteunde-functie-callbacks. Dezelfde samenvattings- en bevindingsrijen kunnen worden opgeslagen of gekopieerd als TXT-auditrapport of als gestructureerd JSON-rapport worden opgeslagen. Ze zijn bedoeld als risico-panelen voor de host-toepassing, niet als malware-detectie

Linkafhandeling in de viewer

Veilig klik-om-te-volgen met per-actie allow lists

// LinkOptions bestuurt de automatische afhandeling van de vier PDF-link-
// actietypen. Standaardwaarden schakelen alleen goto en URI in; launch
// (een programma uitvoeren) en embedded GotoR (naar een ander bestand
// springen) blijven UIT, zodat een per ongeluk klik geen willekeurige code
// kan uitvoeren.
PdfView1.LinkOptions :=
  [loAutoGoto, loAutoOpenURI];  // veilige standaardwaarden

// OnAnnotationLinkClick vuurt voor bestemmingen binnen het document
// (paginasprongen, benoemde bestemmingen, actie-ketens). Markeer Handled = True
// om te voorkomen dat de viewer de link automatisch volgt.
procedure TForm1.PdfView1AnnotationLinkClick(Sender: TObject;
  LinkIndex: Integer; const Action: TPdfAction;
  var Handled: Boolean);
begin
  if Action.Kind = paUri then
  begin
    if MessageDlg('Open ' + Action.Uri + '?', mtConfirmation, [mbYes, mbNo], 0)
      <> mrYes then
      Handled := True;  // onderdruk automatische afhandeling
  end;
end;

// OnWebLinkClick vuurt voor URI-strings ontdekt door PDFium's weblink-
// scanner (automatisch gedetecteerde URL's in de tekststream, zelfs zonder
// /A <</S/URI...>>-annotatie).
procedure TForm1.PdfView1WebLinkClick(Sender: TObject;
  WebLinkIndex: Integer; const Url: WString;
  var Handled: Boolean);
begin
  Log.Add('Web link clicked: ' + string(Url));
end;

Formulier-widget bewerken in de viewer

Selectie en ongedaan maken / opnieuw uitvoeren

// Op het gefocuste AcroForm-widget sturen zes nieuwe methoden de
// formulier-edit-geschiedenis van PDFium aan. Alle zes vallen veilig
// terug wanneer geen widget gefocust is of het document geen AcroForm
// bevat.
procedure TForm1.btnSelectAllClick(Sender: TObject);
begin
  PdfView1.SelectAllFormText;
  EditMenuCopy.Caption := 'Copy: ' + string(PdfView1.GetSelectedFormText);
end;

procedure TForm1.btnUndoClick(Sender: TObject);
begin
  btnUndo.Enabled := PdfView1.FormCanUndo;
  btnRedo.Enabled := PdfView1.FormCanRedo;
  if PdfView1.FormCanUndo then
    PdfView1.FormUndo;
end;

procedure TForm1.btnRedoClick(Sender: TObject);
begin
  if PdfView1.FormCanRedo then
    PdfView1.FormRedo;
end;

De viewer vergrendelen voor kiosken

Pagina-navigatie-gebaren uitschakelen

// Alle drie staan standaard op True, zodat bestaande apps zonder
// gedragswijziging upgraden. Zet ze op False voor kiosken, preview-panes
// of alleen-lezen embeds zonder TPdfView te subclassen.
PdfView1.AllowUserPageChange       := False;  // PgUp/PgDn/Ctrl+Home/End
PdfView1.ChangePageOnMouseScrolling := False; // wiel-omhoog/omlaag-sprongen
PdfView1.AllowUserTextSelection    := False;  // muis-/toetsenbord-tekstselectie

// Ctrl+wheel is gereserveerd voor zoom en wordt overgeslagen door de
// navigatie-handler ongeacht ChangePageOnMouseScrolling.

Miniatuur-zijpaneel

Een TPdfThumbnailView koppelen aan een TPdfView

// TPdfThumbnailView (unit FPdfThumbnail) rendert één paginaminiatuur per
// rij in een scrollbaar zijpaneel.
uses FPdfThumbnail;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ThumbView.Pdf              := Pdf1;
  ThumbView.ThumbnailWidth   := 120;
  ThumbView.ThumbnailHeight  := 160;
  ThumbView.SelectionColor   := $00CFA85F;  // warme accentkleur
  ThumbView.OnPageClick      := ThumbViewPageClick;
end;

procedure TForm1.ThumbViewPageClick(Sender: TObject; PageIndex: Integer);
begin
  PdfView1.PageNumber := PageIndex + 1; // PageIndex is zero-based
end;

procedure TForm1.PdfView1PageNumberChanged(Sender: TObject);
begin
  ThumbView.CurrentPageIndex := PdfView1.PageNumber - 1;
end;

Coöperatief annuleerbare batchexport

Multi-file PDF naar JPG met progress per bestand en per pagina

// Patroon gebruikt door Demo\Delphi\BatchExport, Demo\CBuilder\BatchExport
// en Demo\Lazarus\BatchExport. Één TPdf per bestand, IPdfCancellationToken
// voor cancel-from-UI, TPdfStreamAdapter voor gebufferde file load.
uses FPdfAsync;

procedure ExportBatch(const Files: TArray<string>;
  const OutDir: string; DPI: Integer; Quality: Integer;
  const ACancelToken: IPdfCancellationToken);
var
  I, J: Integer;
  Job:  TPdf;
  Bmp:  TBitmap;
  Jpeg: TJPEGImage;
begin
  for I := 0 to High(Files) do
  begin
    if ACancelToken.IsCancelled then Break;
    OverallProgress.Position := I;

    Job := TPdf.Create(nil);
    try
      Job.FileName := Files[I];
      Job.Active   := True;
      PageProgress.Max := Job.PageCount;

      for J := 1 to Job.PageCount do
      begin
        if ACancelToken.IsCancelled then Break;
        PageProgress.Position := J;

        Job.PageNumber := J;
        Bmp := Job.RenderPage(
          0, 0,
          Round(Job.PageWidth  * DPI / 72),
          Round(Job.PageHeight * DPI / 72));
        try
          Jpeg := TJPEGImage.Create;
          try
            Jpeg.CompressionQuality := Quality;
            Jpeg.Assign(Bmp);
            Jpeg.SaveToFile(Format('%s\%s.p%.3d.jpg',
              [OutDir, ExtractFileName(Files[I]), J]));
          finally
            Jpeg.Free;
          end;
        finally
          Bmp.Free;
        end;
      end;
    finally
      Job.Free;
    end;
  end;
end;

Viewer-coördinaten en hit-testing

De huidige pagina passend maken en tekst onder de muis inspecteren

procedure FitCurrentPage;
begin
  PdfView1.Zoom := PdfView1.PageZoom[PdfView1.PageNumber];
end;

procedure InspectViewerPoint(X, Y: Integer);
var
  PageNo: Integer;
  PageX, PageY: Double;
  CharIndex: Integer;
  Ch: WString;
begin
  PageNo := PdfView1.PageNumber;
  if not PdfView1.DeviceToPage(X, Y, PageNo, PageX, PageY) then
    Exit;

  CharIndex := PdfView1.CharacterIndexAtPos(X, Y, 8, 8);
  if CharIndex >= 0 then
  begin
    Ch := PdfView1.Text(CharIndex, 1);
    ShowMessage(Format('Page %d, X %.2f, Y %.2f, character %s',
      [PageNo, PageX, PageY, string(Ch)]));
  end;
end;

Foutafhandeling

Robuuste PDF-bewerkingen

function LoadPdfSafely(const FileName: string): Boolean;
begin
  Result := False;
  if not FileExists(FileName) then
    Exit;
  try
    Pdf1.FileName := FileName;
    Pdf1.Active := True;
    Result := Pdf1.Active;
  except
    Result := False;
  end;
end;

function ExtractTextSafely(PageNo: Integer): WString;
begin
  Result := '';
  if not Pdf1.Active then
    Exit;
  if (PageNo < 1) or (PageNo > Pdf1.PageCount) then
    Exit;
  Pdf1.PageNumber := PageNo;
  Result := Pdf1.Text;
end;

Tagged PDF en toegankelijkheid

Tagged PDF detecteren en de structuurboom doorlopen

// IsTagged is een goedkope catalog-probe — True wanneer /StructTreeRoot
// bestaat. StructureElements materialiseert de boom in een flat array van
// TPdfStructureElement-records met type, title, alternate text, actual
// text, expansion text, language, level, parent index en child / marked
// content / attribute counts.
var
  Elements: TPdfStructureElements;
  I: Integer;
begin
  if not Pdf1.IsTagged then
  begin
    Log.Add('Document is NOT tagged — accessibility tools may struggle.');
    Exit;
  end;
  if Pdf1.Language = '' then
    Log.Add('Tagged PDF without /Lang — fails PDF/UA.');

  Elements := Pdf1.StructureElements;
  for I := 0 to High(Elements) do
    Log.Add(StringOfChar(' ', Elements[I].Level * 2)
      + Elements[I].StructType + ' "' + Elements[I].Title + '"');
end;

Selectie van afdrukmodus

EMF- / PostScript- / image-mask-print-modus instellen

// SetPdfPrintMode is een globale functie die overeenkomt met PDFium's
// FPDF_SetPrintMode. Gebruik de bijpassende TPdfPrintMode-waarde voor het
// gebruikte printer-stuurprogramma.
SetPdfPrintMode(pmEmf);                   // GDI EMF (standaard)
// SetPdfPrintMode(pmTextOnly);           // alleen-tekst-rendering
// SetPdfPrintMode(pmPostScript2);        // PostScript Level 2
// SetPdfPrintMode(pmPostScript3);        // PostScript Level 3
// SetPdfPrintMode(pmPostScript2PassThrough);
// SetPdfPrintMode(pmPostScript3PassThrough);
// SetPdfPrintMode(pmEmfImageMasks);      // EMF + image masks
// SetPdfPrintMode(pmPostScript3Type42);  // PostScript 3 + Type 42-fonts

Door de auteur bedoelde printinstellingen lezen

// PrintCopies, PrintPageRanges, PrintScaling en PrintPaperHandling zijn
// de viewer-preference-dictionary-entries — ze coderen wat de
// documentauteur wilde dat PDF-readers standaard zouden gebruiken.
var
  Ranges: TPrintPageRanges;
  Range: TPrintPageRange;
begin
  ShowMessage('Suggested copies: ' + IntToStr(Pdf1.PrintCopies));
  ShowMessage('Print scaling: ' + GetEnumName(TypeInfo(TPrintScaling),
    Ord(Pdf1.PrintScaling)));

  Ranges := Pdf1.PrintPageRanges; // one-based bereiken
  for Range in Ranges do
    Log.Add(Format('Pages %d..%d', [Range.First, Range.Last]));

  if SetPdfPrintPaperHandlingDevMode(PrinterDevMode, Pdf1.PrintPaperHandling) then
    ApplyPrinterDevMode(PrinterDevMode);
end;

JavaScript-acties op documentniveau

Name-tree-JavaScript opsommen

// JavaScript op documentniveau wordt opgeslagen in de /Names /JavaScript
// name-tree. JavaScriptAction[i] retourneert één entry; JavaScriptActions
// retourneert de volledige array.
var
  I: Integer;
  Action: TPdfJavaScriptAction;
begin
  for I := 0 to Pdf1.JavaScriptActionCount - 1 do
  begin
    Action := Pdf1.JavaScriptAction[I];
    Memo1.Lines.Add('Name:   ' + string(Action.Name));
    Memo1.Lines.Add('Script: ' + string(Action.Script));
    Memo1.Lines.Add('---');
  end;
end;

Prestatietips

PDF-bewerkingen optimaliseren

procedure ProcessMultiplePages;
var
  I: Integer;
  PageText: WString;
begin
  for I := 1 to Pdf1.PageCount do
  begin
    Pdf1.PageNumber := I;
    PageText := Pdf1.Text;
    ProcessPageText(PageText);
  end;
end;

procedure SetOptimalRenderOptions;
begin
  PdfView1.Options := [reAnnotations, reLcd];
end;

// Zero-copy renderpad (standaard sinds v1.21.0): RenderPage schrijft
// rechtstreeks in de DIB-buffer van de bestemmings-TBitmap wanneer
// aanroepers een vooraf gealloceerde bitmap doorgeven, waarmee één kopie
// van width * height * 4 bytes wordt vermeden.
procedure RenderIntoCallerBitmap(Bitmap: TBitmap);
begin
  Bitmap.PixelFormat := pf32bit;
  Bitmap.SetSize(2480, 3508); // A4 @ 300 DPI
  Pdf1.RenderPage(Bitmap, 0, 0, Bitmap.Width, Bitmap.Height);
end;