PDFium Delphi Component Docs

PDFium VCL-programmeringsexempel

Välj en körbar demo

Demosamlingen omfattar 33 ämnen: 33 Delphi-projekt, 32 C++Builder-projekt och 33 Lazarus-projekt, totalt 98 nativa projekt. Varje plattform behåller 24 kompletta arbetsflödesdemoer i sin huvudkatalog. Nio fokuserade ämnen ligger under Miscellaneous, med 26 nativa projekt över de tre plattformarna; XfaLab finns för Delphi och Lazarus

Öppna först ett arbetsflöde i huvudkatalogen: PDFViewer för en rundtur, CreatePDF för direkt skapande, ContentExtractionLab för en snabb inventering, FormFill för redigerbara formulär, StandardsLab för validering och konvertering, eller IntakeWorkbenchCli för automatiserad intake. Dessa sex ingångspunkter ger fungerande resultat direkt; de fokuserade exemplen nedan är användbara när du behöver inspektera ett API i detalj

Arbetsflödesdemoer i huvudkatalogen

DemoAnvänd den förHur den skiljer sig från närliggande demoer
PDFViewerAllmän visning och funktionsutvärderingHuvudvisaren kombinerar navigering, sökning, miniatyrbilder, visningslägen, utskrift och en funktionsshowcase
MultiPageViewerKontinuerliga sidor, uppslag och omslagslayouterEtt fokuserat layoutexempel som använder visarens inbyggda markerings-API:er; använd PDFViewer för den bredare visarupplevelsen
SplitViewJämföra sidor eller dokument i separata panelerDemonstrerar oberoende vypositioner och att kommandon routas till den aktiva panelen, i stället för tvåsidig layout i en enda vy
SearchAndSelectSökresultat och markering över flera sidorEn träfflista och sökalternativ exponerar sökarbetsflödet mer direkt än ett verktygsfält i visaren
PrintPDFFörhandsvisning och vanliga utskriftsjobbSidintervall, skalning, förlopp och avbrytning ger huvudflödet för utskrift
ContentExtractionLabInspektera flera innehållskategorier tillsammansTXT-/JSON-inventeringar beskriver objekt och förhandsvisar text; de ersätter inte fullständig export av text eller bildfiler
ExtractImagesExportera inbäddade bildobjektExtraherar bildbitmaps i stället för skärmdumpar av hela sidor; det medföljande exempeldokumentet innehåller två riktiga bildobjekt på var och en av de två sidorna
TableExtractionLabDetektera tabeller och exportera CSV/JSONLinjerade och mellanrumjusterade tabeller, sammanslagna celler, fortsättningsgrupper och konfidenskontroller är oberoende av extraktion av ren text
AttachmentLäsa, lägga till och exportera inbäddade bilagorÅtgärder på bilageinnehållet går längre än att lista namn och storlekar i ContentExtractionLab
BatchExportExportera sidbilder från flera dokumentStrömmande utdata, status per fil och isolerade fel demonstrerar batchbearbetning i stället för en enda konvertering
CreatePDFSkapa sidinnehåll med direkt förhandsvisningAlla tre nativa varianter skapar sökbar text, vektorformer, en riktig rasterbild, tabeller och en granskningsannotering; alternativen bygger om förhandsvisningen innan en explicit sparning
ImageToPDFBygga sidor från indatabildfilerBildlayout, anpassning, ordning och JPEG-hantering ger ett arbetsflöde för dokumentkonvertering
MergePDFSätta samman sidor från flera PDF:erDemonstrerar dokumentimport och ordnad komposition; delning löser det omvända arbetsflödet
SplitPDFSkriva valda sidgrupper till separata PDF:erNamngivning av utdata och validering av sidgrupper skiljer sig från sammanslagning eller rendering av sidbilder
WatermarkStampApplicera upprepade överlagringar på befintliga sidorPlacering och stämpling av många sidor kompletterar de grundläggande API:erna för innehållsskapande
FormFillInteraktiv AcroForm-ifyllnad och plattläggningFältinmatning och sparade appearances skiljer sig från XFDF-utbyte och XFA-specifikt beteende
AccessibilityReaderInteraktiv läsning och uppläsningGUI-läsaren demonstrerar läsnavigering och markering i stället för en efterlevnadsgranskning
AccessibilityWorkbenchCliBatchgranskning av tillgänglighet och rapportgenereringFynd, sammanfattningar och granskningsgrindar tjänar automatiseringen; fynden ersätter inte manuell tillgänglighetsgranskning
StandardsLabStandardsspecifik validering och konverteringDet interaktiva laboratoriet exponerar åtgärder och alternativ i stället för att bara generera en sammanlagd rapport
PreflightReportInteraktiva standardrapporterGUI:t stöder manuell inspektion och rapportexport
PreflightReportCliAutomatiserade standardrapporterBatchindata, rapportformat och utgångskodsgrindar ger automationsmotsvarigheten till PreflightReport
IntakeWorkbenchCliBatch-intake, triage och routningSammanlagda rapporter, felgrindar och routningsbeslut gör detta till ett bearbetningsflöde utöver GUI:t i SecurityAudit

Fokuserade exempel under Miscellaneous

Öppna de här projekten från Demo\Delphi\Miscellaneous, Demo\CBuilder\Miscellaneous eller Demo\Lazarus\Miscellaneous. De bevarar användbara API-recept och avgränsade exportuppgifter medan huvudkatalogen fokuserar på kompletta upplevelser. Grundläggande Unicode-kontroller som skriver och läser in text igen täcks av arbetsflödena för skapande och extraktion; de har inte längre separata demoprojekt

DemoAnvänd den förHur den skiljer sig från närliggande demoer
SecurityAuditInspektera säkerhetspositionen interaktivtGUI:t betonar behörigheter, skript, signaturer och säkerhetsdetaljer i stället för filroutning
XfdfLabImportera och exportera XFDF-dataUtbyte och en explicit sparning av den importerade PDF:en demonstrerar persistens; att bara exportera XFDF sparar inte den ändrade PDF:en
AccessibilityLabGå igenom läsar-API:erna i en konsolEn kompakt körbar genomgång exponerar läsenheter, ordboxar, struktur och utdata från uppläsningsskript
ExtractTextExportera fullständig text från valda sidorUtdata från textlager, sidavgränsare och avbrytning skiljer sig från inventeringsförhandsvisningar och tabelldetektering; ingen OCR körs
FontPropertiesInspektera typsnitts- och teckenmåttÖppnas med faktiska typsnitts- och teckenmått för det första textobjektet; markera en annan rad för att jämföra typsnitt utan att exportera dokumentens innehåll
NavigationLabBokmärken, destinationer och navigeringsåtgärderDen kompakta API-genomgången kompletterar de synliga navigeringskontrollerna i PDFViewer
PDFtoJpgRendera ett dokument till sidbilderEtt kompakt renderings-exempel för ett enskilt dokument; Delphi exponerar diskreta sidintervall, medan BatchExport fokuserar på flera indatadokument
PrintPreferencesN-up-ark och PDF-författarens utskriftsinställningarAntal kopior, filtrering av udda/jämna sidor och författarens inställningar står i fokus; detta är ett komplement till PrintPDF
ViewerInteractionLabDiagnostisera mus-, tangentbords- och koordinatinteraktionerInteraktionsloggen och omvandlingen mellan sid- och enhetskoordinater gör den till ett API-diagnostikverktyg
XfaLabStatiska XFA-paket och runtime-funktionerÖppnar mall- och dataset-paket med den ordinarie runtimen; interaktiv XFA-rendering kräver en XFA-aktiverad runtime, med varianter för Delphi och Lazarus

Börja med en rundtur bland funktionerna som fungerar direkt

PDFViewer öppnar sin medföljande PDFiumDemoShowcase.pdf, ett sexsidigt dokument med sökbar text, vektordiagram, två inbäddade bilder, en tabell, fyra AcroForm-fält, kapitelbokmärken, länkar, en granskningsnotis och två filbilagor. Upplevelseraden erbjuder Restart showcase, Find live text, 2-page spread, Night reading, Inspect this PDF och Explore forms; varje åtgärd arbetar mot det aktuella dokumentet

CreatePDF öppnar en direkt förhandsvisning av en tvåsidig rapport. Ändra dess titel och författare eller växla former, tabellen och vattenstämpeln för att bygga om det faktiska sidinnehållet; Unicode-alternativet lägger till en tredje sida. Inget skrivs förrän du sparar, och den sparade PDF:en förblir sökbar

MultiPageViewer, SearchAndSelect, ContentExtractionLab och FormFill öppnar samma dokument för sina egna arbetsflöden, med sökresultat, en extraktionsinventering och redigerbara fält klara direkt. Miscellaneous\NavigationLab använder sin egen lokala kopia för en genomgång av bokmärkes- och destinations-API:erna

Attachment startar med två riktiga inbäddade filer. PrintPreferences startar med fyra sidor och författarinställningar för två kopior, valda sidintervall, skalning och duplex; det aktuella utskriftsflödet tillämpar kopior och sidintervall, medan skalning och duplex inspekteras och rapporteras. XfaLab startar med riktiga mall- och dataset-paket för statisk XFA-inspektion; interaktiv XFA-rendering kräver en lämplig runtime och är en separat funktion

Varje visnings-, formulär-, extraktions- och navigeringsprojekt innehåller sin egen PDFiumDemoShowcase.pdf. Kopiera projektkatalogen och behåll den här medföljande indatan bredvid den distribuerade körbara filen; Lazarus-byggen placerar ut den automatiskt. Rundturen fungerar offline, och allmänna visare och extraktionsexempel tillhandahåller också genererat reservinnehåll när den lokala PDF:en saknas

Kopiera och underhåll de nativa exemplen

Varje nativ demo innehåller sin egen exempelimplementation. Ingångspunkterna i Delphi och Lazarus för AccessibilityLab, AccessibilityWorkbenchCli, IntakeWorkbenchCli och PreflightReportCli har hela arbetsflödet i projektkatalogen, inklusive kompilatorsspecifik initiering och JPEG-skrivning. Exemplen för bilagor, utskriftsinställningar och XFA bygger också sina funktionsspecifika indata lokalt. Utanför det kopierade projektet krävs bara biblioteket, motsvarande nativa runtime och normala ramverksberoenden för kompilatorn

Välj extraktion av bildobjekt när du behöver inbäddade bitmaps, sidrendering när du behöver den synliga sidan och textextraktion när PDF:en redan har ett textlager. En rapport som listar kategorierna exporterar inte deras fulla innehåll. De här gränserna håller de fokuserade exemplen användbara utan att varje demo växer till ännu en allmän visare eller arbetsbänk

Grundläggande dokumentoperationer

Läsa in och visa ett PDF-dokument

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;

Skapa ett nytt PDF-dokument

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;

Textoperationer

Extrahera text från 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;

Söka i text

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;

Lägga till text med formatering

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;

Inspektera tecken- och typsnittsmetadata

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;

Projekten Demo\Delphi\Miscellaneous\FontProperties, Demo\CBuilder\Miscellaneous\FontProperties och Demo\Lazarus\Miscellaneous\FontProperties visar samma metadata genom både TPdf och TPdfView

Bygga en extraktionsrapport för innehåll med flera kategorier

Projekten Demo\Delphi\ContentExtractionLab, Demo\CBuilder\ContentExtractionLab och Demo\Lazarus\ContentExtractionLab gör innehållsextraktion till ett enda arbetsflöde. De öppnar eller skapar en PDF, låter användaren välja metadata, sidtext, sidobjekt, bilder, bilagor, länkar, annoteringar, bokmärken samt typsnitts- och teckenmått, och genererar sedan en sammanfattning plus en detaljerad TXT- eller JSON-rapport. Labben innehåller även kategorival av alla / ingen, kopiering av rapporten till urklipp och åtgärder för att spara käll-PDF:en, så att användaren kan behålla den genererade exempel-PDF:en bredvid sin extraktionsrapport. ExtractImages och Attachment tillhandahåller arbetsflöden för export av innehåll, medan Miscellaneous\ExtractText och Miscellaneous\FontProperties är kvar som fokuserade API-exempel; ExtractText stöder sidintervalls- och sidavgränsaralternativ för att producera text per sida i Delphi, C++Builder och Lazarus, medan ContentExtractionLab är det övergripande inventeringsexemplet

Detektera och extrahera tabeller

Projekten Demo\Delphi\TableExtractionLab, Demo\CBuilder\TableExtractionLab och Demo\Lazarus\TableExtractionLab gör detektering av tabeller till ett enda arbetsflöde. Labben bygger ett exempeldokument som innehåller en linjerad tabell med sammanslagna rubrikceller, en tabell justerad med mellanrum utan linjer och en lång tabell som bryts över en sidgräns, kör sedan ExtractTables för den aktuella sidan eller ExtractDocumentTables för hela dokumentet och rapporterar rader, kolumner, värden för RowSpan och ColumnSpan, rubrikflaggor, detekteringsläge, konfidens och fortsättningsgrupper. Alternativen DetectRuledTables, DetectWhitespaceTables, DetectContinuations, DetectFilledRulings och MinConfidence kan redigeras i användargränssnittet, och den valda tabellen exporteras via TPdfTable.ToCsv och TPdfTable.ToJson. Labben kör också batch över en hel mapp: Batch folder kör ExtractDocumentTables på varje PDF, rapporterar tabellantal per dokument, flaggar skanningar utan textlager och försöker igen med tomma dokument med en förinställning för kompakta kolumner; Export all CSV skriver varje detekterad tabell bredvid källfilerna. Varje dokument öppnas i sin egen TPdf-instans så att en oläslig fil inte kan påverka resten av batchen

Formuläroperationer

Arbeta med formulärfält

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;

Plattlägg ifyllda formulärvärden in i sidan

// Without flattening, FormField[i] := value writes only the /V entry —
// the visible appearance comes from the /AP stream and may not refresh
// GenerateFormAppearances regenerates /AP for every widget, then
// FlattenAllPages bakes every page's annotations and widgets into
// permanent, non-editable content
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;

Bildoperationer

Extrahera bilder

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;

Lägga till bilder

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;

Annoteringsoperationer

Arbeta med annoteringar

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;

Ritoperationer

Rita former

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;

Navigering och bokmärken

Arbeta med bokmärken

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;

Arbeta med namngivna destinationer

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;

Bilageoperationer

Arbeta med bilagor

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;

Sidhantering

Sidoperationer

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

Sparande och komprimering

Spara med komprimering

// Create a compressed PDF document
Pdf1.CreateDocument;
Pdf1.Compressed := True; // ensure all streams are FlateDecode compressed (default)
Pdf1.Active := True;
Pdf1.AddPage(0, 595, 842); // A4 size
Pdf1.AddText('Hello World!', 'Arial', 24, 100, 700, clBlack, $FF, 0.0);
Pdf1.SaveAs('C:\Compressed.pdf');
Pdf1.Active := False;

// Save with options
Pdf1.SaveAs('C:\Output.pdf', saIncremental); // incremental save
Pdf1.SaveAs('C:\NoSecurity.pdf', saRemoveSecurity); // remove security

// Save to a specific PDF version target. The PDF version validator rejects
// any feature introduced after the chosen target (JBIG2Decode, MarkInfo,
// AES encryption, Polygon / Caret / Watermark / Redact annotations, ...)
if not Pdf1.SaveAs('C:\Legacy15.pdf', saNone, pv15) then
  ShowMessage('Save rejected: document contains features newer than PDF 1.5');

Skapa arkivutdata i PDF/A-1b

// SaveAsPdfA post-processes the base save with an incremental update that
// injects an XMP metadata stream, an sRGB ICC OutputIntent, and an updated
// document catalog so the result is PDF/A-1b conformant. The bundled
// sRGB IEC61966-2.1 profile is used automatically when no custom profile
// is supplied
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 with a custom ICC profile (CMYK printing pipelines for example)
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;

// In-memory PDF/A output
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;

Validera PDF/A-konformans

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

  // Cheap header-style probe — reads the conformance without iterating
  // the full validator. Result: pacNone, pac1a, pac1b, pac2b, pac3b, or
  // 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;

  // Full validator with per-issue diagnostics
  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;

Inspektera flera PDF-standarder i StandardsLab

Projekten Demo\Delphi\StandardsLab, Demo\CBuilder\StandardsLab och Demo\Lazarus\StandardsLab läser in eller skapar en PDF, kör ValidatePdfA, ValidatePdfUa, ValidatePdfE, ValidatePdfX, ValidatePdfR och ValidatePdfVT och visar sedan varje upptäckt konformansnivå och problemantal i ett enda rutnät. Deras sparningsknappar anropar SaveAsPdfA, SaveAsPdfUa, SaveAsPdfE, SaveAsPdfX, SaveAsPdfR och SaveAsPdfVT så att markörutdataflödet syns utan att man behöver skriva en egen testrigg

Generera förhandskontrollrapporter

Enheten FPdfPreflightReport samlar ValidatePdfA, ValidatePdfUa, ValidatePdfE, ValidatePdfX, ValidatePdfR och ValidatePdfVT i ett frågbart rapportobjekt med allvarlighetsgrad Info / Warning / Error, aggregering av status och problem, uppslag, sökning, filtrering och stabila SHA-256-fingeravtryck. Rapporter kan skrivas som text, HTML, Markdown, JSON, CSV, SARIF 2.1.0, JUnit XML, NDJSON eller inbyggd XML. Demo\Delphi\PreflightReport, Demo\Lazarus\PreflightReport och Demo\CBuilder\PreflightReport tillhandahåller interaktiva arbetsflöden för val och förhandsvisning, medan Demo\Delphi\PreflightReportCli lägger till skriptbara in-/utdataargument, standardfiltrering, valfri inbäddning av rapportbilagor, styrning av CI-utgångskod, batchlist- och katalogbearbetning, kollisionssäker routning, aggregerade sammanfattningar och CSV-manifest. Den genererade rapporten anger att de inbyggda validatorerna täcker kontroller på markörnivå och utvalda kontroller på filnivå, så fullständiga innehållskontroller fortfarande kan delegeras till en dedikerad valideringsmotor

Strömmande inläsning och stora dokument

Läsa in en PDF på begäran med LoadCustomDocument

// LoadCustomDocument lets PDFium pull blocks from any seekable TStream on
// demand. The stream is NOT copied into memory, so multi-GB PDFs, remote
// HTTP body streams, and database-backed sources are all viable without
// an up-front buffer
var
  FileStream: TFileStream;
begin
  // Read-from-file streaming (no in-memory copy)
  FileStream := TFileStream.Create('C:\Huge.pdf',
    fmOpenRead or fmShareDenyWrite);
  Pdf1.LoadCustomDocument(FileStream, True{AOwnsStream});
  // ^^ ownership transferred — Pdf1 frees FileStream on UnloadDocument
  Pdf1.Active := True;
  ShowMessage('Pages: ' + IntToStr(Pdf1.PageCount));
end;

// Externally-owned stream (caller frees it after 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;

Asynkron avbrytning och progressiv rendering

Kooperativa avbrytningstoken

// FPdfAsync exposes IPdfCancellationToken /
// IPdfCancellationTokenSource for cancel-from-UI semantics that work
// across the long-running export and render paths
uses FPdfAsync;

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

  // user clicks Cancel
  CancelSource.Cancel;

  // The worker periodically checks CancelToken.IsCancelled, or the render
  // path polls it through PDFium's IFSDK_PAUSE callback
  if CancelToken.IsCancelled then
    Memo1.Lines.Add('Cancelled by user');
end;

Avbrytbar progressiv sidrendering

// RenderPageProgressive lets a long high-DPI render abort mid-page when
// the user clicks Cancel, instead of blocking the caller until done
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;

Köra renderingar på en bakgrundstråd med TPdfFuture

// TPdfFuture<T> spins up a worker on a background thread and posts a
// TPdfFutureResult<T> envelope back to the main thread
//
// Important: TPdf serializes render calls per instance, but the worker still
// owns dispatch and document lifetime. Do not mutate a TPdf while a render is
// in flight; batch export usually keeps one TPdf per file
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;

Transformationsmatriser

Kombinera Translate / Scale / Rotate / Skew

// FPdfMatrix wraps PDFium's FS_MATRIX so callers can build a transform
// declaratively and hand it to FPDFPageObj_SetMatrix
uses FPdfMatrix, FPdfView;

var
  M: TPdfMatrix;
  RawMatrix: FS_MATRIX;
  PageObj: FPDF_PAGEOBJECT;
begin
  M := TPdfMatrix.Create;
  try
    M.Translate(72, 200);       // move 1in right, ~2.8in up
    M.Scale(0.5, 0.5);          // half-size stamp
    M.Rotate(15);               // 15-degree CCW rotation
    // M.HorizontalFlip;
    // M.VerticalFlip;
    // M.CentralFlip;
    // M.Skew(10, 5);
    // M.Multiply(Other);       // post-multiply with another matrix

    // Apply to any PDFium page object (text / path / image / form XObject)
    RawMatrix := M.Handle;
    FPDFPageObj_SetMatrix(PageObj, RawMatrix);
  finally
    M.Free;
  end;
end;

Sidkomposition

Importera en delmängd sidor efter index

// ImportPagesByIndex copies an explicit zero-based index array from a
// source PDF into this document. InsertAt = 0 inserts before page 1;
// PageCount appends
var
  Source: TPdf;
begin
  Source := TPdf.Create(nil);
  try
    Source.FileName := 'C:\Report.pdf';
    Source.Active   := True;

    // Import pages 0, 2, 4 (one-based: pages 1, 3, 5) from Source
    // and append them at the end of Pdf1
    Pdf1.ImportPagesByIndex(Source, [0, 2, 4], Pdf1.PageCount);

    // Empty array imports every source page
    // Pdf1.ImportPagesByIndex(Source, [], 0);
  finally
    Source.Free;
  end;
end;

N-up-sammansatt utdata

// ImportNPagesToOne returns a brand-new TPdf whose pages are NumX*NumY
// composites of THIS document. OutputWidth/Height are PDF user units
// (1 unit = 1/72 in)
var
  Composite: TPdf;
begin
  Pdf1.FileName := 'C:\Slides.pdf';
  Pdf1.Active   := True;
  // 4-up A4 landscape: 842 x 595 pt, 2 columns x 2 rows
  Composite := Pdf1.ImportNPagesToOne(842, 595, 2, 2);
  try
    if Composite <> nil then
      Composite.SaveAs('C:\Slides_4up.pdf');
  finally
    Composite.Free;
  end;
end;

Ordna om sidor på plats

// MovePages takes the zero-based indices of the pages to move plus the
// destination index for the first moved page after the move completes
// Other pages shift around the moved block so the document length stays
// the same
//
// Example: in a 5-page document with pages numbered [0,1,2,3,4],
// MovePages([2, 3], 0) reorders to [2, 3, 0, 1, 4]
if not Pdf1.MovePages([2, 3], 0) then
  ShowMessage('Invalid indices passed to MovePages');

Vattenstämplar via återanvändning av Form XObject-sidor

// CreateXObjectFromPage manufactures a reusable Form XObject handle from
// any page of any other TPdf. Stamp that handle onto as many pages of
// THIS document as you want — each stamp is a single PDFium page object
// that can be positioned, scaled, and rotated through the 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;

    // Wrap page 0 of WatermarkSource as a reusable 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;

        // Centre the watermark on the page
        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; // closes the FPDF_XOBJECT handle
    end;

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

Projekten Demo\Delphi\WatermarkStamp, Demo\Lazarus\WatermarkStamp och Demo\CBuilder\WatermarkStamp gör det här mönstret till ett körbart arbetsflöde: de skapar en mål-PDF och en återanvändbar stämpel-PDF, slår in stämpelsidan med CreateXObjectFromPage, infogar samma Form XObject på varje målsida, applicerar TPdfMatrix-transformationer för centrerade vattenstämplar och stämplar uppe till höger, och lägger till valfria sidnummeretiketter innan resultatet sparas

Bildinsättning (direkta AddImage-överlagringar)

Lägga till en registrerad bildfil eller en TBitmap

// AddImage(FileName) accepts any format registered with the VCL or LCL
// graphics units (BMP, PNG via PngImage, JPG, ...)
Pdf1.AddImage('C:\Photo.png', 100, 500, 200, 150);

// AddImage(TBitmap) skips the TPicture intermediary, ideal when the
// bitmap already comes from rendering or batch generation work
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;

Projekten Demo\Delphi\ImageToPDF, Demo\CBuilder\ImageToPDF och Demo\Lazarus\ImageToPDF gör detta till ett komplett batcharbetsflöde: välj flera bildfiler, förhandsvisa vald post, skapa en PDF-sida per bild, skala varje bild till en A4-sida i stående eller liggande format, spara resultatet och öppna den genererade PDF:en

Sökmarkering i visaren

Markera varje träff på den aktuella sidan

var
  MatchCount: Integer;
begin
  // Paint a clYellow mask over every match on the view's current page
  // Switching to a different page clears the highlight automatically
  PdfView1.HighlightColor := clYellow;
  MatchCount := PdfView1.HighlightSearchText('invoice', False{Case}, True{Word});
  Status.Caption := Format('%d match(es) on this page', [MatchCount]);

  // Programmatically remove the overlay before the page changes
  PdfView1.ClearHighlight;
end;

Visarens layout och sidfärg

Fit-läge och sidbakgrund

// FitMode keeps long documents framed during Resize or page changes
// Setting Zoom directly cancels FitMode (it reverts to pfmNone)
PdfView1.FitMode := pfmFitPage;       // whole page in viewport
// PdfView1.FitMode := pfmFitWidth;   // page width matches viewport width
// PdfView1.FitMode := pfmActualSize; // 100%

// PageColor decouples the rendered PDF page from the host control's Color
// — typical dark-mode viewer setup keeps the scroll area dark while the
// PDF page stays paper-white
PdfView1.Color     := clBlack;        // scroll area
PdfView1.PageColor := clWhite;        // PDF page background

// Optional drop shadow and page border to lift the page off a dark bg
PdfView1.PageShadowSize  := 6;
PdfView1.PageShadowColor := $00404040;
PdfView1.PageBorderColor := clGray;

Utforska visarinteraktion i ViewerInteractionLab

Projekten Demo\Delphi\Miscellaneous\ViewerInteractionLab, Demo\CBuilder\Miscellaneous\ViewerInteractionLab och Demo\Lazarus\Miscellaneous\ViewerInteractionLab samlar den moderna interaktionsytan i TPdfView i ett kompakt formulär: öppna eller skapa en exempel-PDF, växla DisplayMode, applicera FitMode, ändra PageColor, rotera sidor, markera sökträffar på aktuell sida med HighlightSearchText, aktivera eller inaktivera textmarkering, inspektera SelectedText, anropa SelectAll, CopySelectionToClipboard och ClearSelection, och se hur DeviceToPage-koordinaterna uppdateras i statusraden medan musen rör sig över sidan

Söka och markera text i SearchAndSelect

Projekten Demo\Delphi\SearchAndSelect, Demo\CBuilder\SearchAndSelect och Demo\Lazarus\SearchAndSelect gör sök- och markeringsflödet i visaren till fristående exempel. De öppnar eller skapar en PDF, listar sökresultat från alla sidor med sidnummer, teckenindex och förhandsvisningstext, stödjer navigering Föregående / Nästa samt hopp till träff vid dubbelklick, markerar träffar på aktuell sida med HighlightSearchText, exponerar alternativen match case och hel ord, växlar AllowUserTextSelection, förhandsvisar SelectedText, driver SelectAll, CopySelectionToClipboard och ClearSelection från knappar, och låter användaren växla mellan visningslägen för enkelsida och uppslag

Läsa PDF:ns utskriftsinställningar i PrintPreferences

Projekten Demo\Delphi\Miscellaneous\PrintPreferences, Demo\CBuilder\Miscellaneous\PrintPreferences och Demo\Lazarus\Miscellaneous\PrintPreferences läser författarens utskriftsinställningar före utskrift. De visar PrintCopies, PrintPageRanges, PrintScaling och PrintPaperHandling, kan kopiera författarens angivna antal kopior och intervall till utskriftsinmatningarna, och visar hur SetPdfPrintPaperHandlingDevMode mappar PDF:ens duplexavsikt till en Windows-DEVMODE

Standardutskrift av PDF i PrintPDF

Projekten Demo\Delphi\PrintPDF, Demo\CBuilder\PrintPDF och Demo\Lazarus\PrintPDF visar standardutskriftsflödet: öppna en PDF, förhandsvisa sidor, välja sidintervall och antal kopior i plattformens utskriftsdialog, följa samlarläget (collate), rendera varje sida via TPdf.RenderPage och exponera utskriftsstatus med avbrytning. Delphi-exemplet accepterar också PDF-filer som dras och släpps in för snabb inläsning

Snabb flersidesvisning i MultiPageViewer

Projekten Demo\Delphi\MultiPageViewer, Demo\CBuilder\MultiPageViewer och Demo\Lazarus\MultiPageViewer tränar kontinuerlig visning, uppslag och omslagsmedveten visning med vanlig sidnavigering och zoom. De är också praktiska för att testa tiden till första användbara vyn och renderingsresponsen på mycket stora PDF-filer: i storfiler kan 2.x GB-dokument som kan få Acrobat eller Foxit att lägga 20-30 sekunder på första vyn bli användbara nästan omedelbart via visarvägen i PDFium Delphi Component

Granskning sida vid sida i SplitView

Projekten Demo\Delphi\SplitView, Demo\CBuilder\SplitView och Demo\Lazarus\SplitView visar PDF-granskning sida vid sida. C++Builder- och Lazarus-exemplen fokuserar på jämförelse i två eller tre paneler, val av aktiv vy, valfria synkroniserade navigeringskommandon, delade zoomförinställningar och rotation för markerad vy eller alla inlästa vyer. Använd dessa exempel för att jämföra stora dokument medan första användbara vyn och efterföljande sidrendering förblir responsiva; samma 2.x GB PDF-filer som kan ta Acrobat eller Foxit 20-30 sekunder att öppna kan bli användbara nästan omedelbart i visarvägen hos PDFium Delphi Component

Granska PDF:ens riskyta i SecurityAudit

Projekten Demo\Delphi\SecurityAudit, Demo\CBuilder\SecurityAudit och Demo\Lazarus\SecurityAudit öppnar en PDF skrivskyddat och listar behörighetsstatus, inbäddade bilagor, dokumentets JavaScript-åtgärder, URI- och Launch-länkannoteringar, webblänkar, signatursammanfattningar, XFA-status, tillgängliga V8-hjälpare och callbacks för funktioner utan stöd. Samma rader med sammanfattningar och fynd kan sparas eller kopieras som en TXT-granskningsrapport eller sparas som strukturerad JSON. De är avsedda som riskpaneler för värdapplikationen, inte som malware-detektion

Länkhantering i visaren

Säkert klicka-och-följ med tillåtelselistor per åtgärd

// LinkOptions controls automatic handling of the four PDF link action
// types. Defaults enable goto and URI only; launch (run a program) and
// embedded GotoR (jump to another file) stay OFF so a stray click cannot
// run arbitrary code
PdfView1.LinkOptions :=
  [loAutoGoto, loAutoOpenURI];  // safe defaults

// OnAnnotationLinkClick fires for in-document destinations (page jumps,
// named destinations, action chains). Mark Handled = True to prevent the
// view from auto-following the link
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;  // suppress auto-handling
  end;
end;

// OnWebLinkClick fires for URI strings discovered by PDFium's web-link
// scanner (auto-detected URLs in the text stream, even without an
// /A <</S/URI...>> annotation)
procedure TForm1.PdfView1WebLinkClick(Sender: TObject;
  WebLinkIndex: Integer; const Url: WString;
  var Handled: Boolean);
begin
  Log.Add('Web link clicked: ' + string(Url));
end;

Redigering av formulärwidgets i visaren

Markering och ångra / gör om

// On the focused AcroForm widget, six new methods drive PDFium's form
// edit history. All six short-circuit safely if no widget is focused or
// the document carries no AcroForm
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;

Låsa visaren för kiosker

Inaktivera gester för sidnavigering

// All three default to True so existing apps upgrade with no behaviour
// change. Flip them False for kiosks, preview panes, or read-only
// embeddings without subclassing TPdfView
PdfView1.AllowUserPageChange       := False;  // PgUp/PgDn/Ctrl+Home/End
PdfView1.ChangePageOnMouseScrolling := False; // wheel up/down jumps
PdfView1.AllowUserTextSelection    := False;  // mouse/keyboard text selection

// Ctrl+wheel is reserved for zoom and is skipped by the navigation
// handler regardless of ChangePageOnMouseScrolling.

Sidopanel med miniatyrbilder

Koppla en TPdfThumbnailView till en TPdfView

// TPdfThumbnailView (unit FPdfThumbnail) renders one page thumbnail per
// row in a scrollable side panel
uses FPdfThumbnail;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ThumbView.Pdf              := Pdf1;
  ThumbView.ThumbnailWidth   := 120;
  ThumbView.ThumbnailHeight  := 160;
  ThumbView.SelectionColor   := $00CFA85F;  // warm highlight
  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;

Batchexport med kooperativ avbrytning

PDF till JPG för flera filer med status per fil och per sida

// Pattern used by Demo\Delphi\BatchExport, Demo\CBuilder\BatchExport,
// and Demo\Lazarus\BatchExport. One TPdf per file, IPdfCancellationToken
// for cancel-from-UI, TPdfStreamAdapter for buffered 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;

Visarens koordinater och träffsökning

Anpassa aktuell sida och inspektera text under musen

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;

Felhantering

Robusta PDF-operationer

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 och tillgänglighet

Upptäcka Tagged PDF och gå igenom strukturträdet

// IsTagged is a cheap catalog probe — True when /StructTreeRoot exists
// StructureElements materialises the tree into a flat array of
// TPdfStructureElement records with type, title, alternate text, actual
// text, expansion text, language, level, parent index, and 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;

Val av utskriftsläge

Ställa in utskriftsläge EMF / PostScript / bildmask

// SetPdfPrintMode is a global function that maps to PDFium's
// FPDF_SetPrintMode. Use the matching TPdfPrintMode value for the
// printer driver in use
SetPdfPrintMode(pmEmf);                   // GDI EMF (default)
// SetPdfPrintMode(pmTextOnly);           // text-only 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

Läsa författarens avsedda utskriftsinställningar

// PrintCopies, PrintPageRanges, PrintScaling, and PrintPaperHandling are
// the viewer-preference dictionary entries — they encode what the
// document author wanted PDF readers to default to
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 ranges
  for Range in Ranges do
    Log.Add(Format('Pages %d..%d', [Range.First, Range.Last]));

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

Dokumentets JavaScript-åtgärder

Räkna upp JavaScript i namnträdet

// Document-level JavaScript is stored in the /Names /JavaScript name
// tree. JavaScriptAction[i] returns one entry; JavaScriptActions returns
// the full 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;

Prestandatips

Optimera PDF-operationer

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 render path (default since v1.21.0): RenderPage writes
// directly into the destination TBitmap's DIB buffer when callers pass a
// pre-allocated bitmap, avoiding one width * height * 4 bytes copy
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;