Teknisk artikel

Udskriv en indlæst PDF i Delphi med HotPDF og TPrinter

HotPDF udskriver en indlæst PDF til a fysisk printer, enhver Windows-enhedskontekst eller udklipsholderen via tre kald: PrintLoadedDocument driver en VCL TPrinter, RenderLoadedPageToDC maler en side direkte i enhver HDC, og RenderLoadedPageToClipboard kopierer en side som et bitmap eller en vektormetafil. HotPDF er en indfødt VCL PDF-komponent til Delphi og C++Builder, og den tilføjede denne førsteklasses udskrivningssti i v2.331.0 og forfinede den i v2.348.0, så du ikke længere selv behøver at forbinde en TPrinter-løkke omkring en bitmap-renderer. Alle tre kald tegner sidens vektorindhold direkte, hvor det tæller, så en udskrift forbliver så skarp, som printeren kan gengive den

Hvorfor tegne en PDF-side direkte i printeren i stedet for et bitmap?

En PDF-side er et program af vektortegningsoperatorer — stier, tekst og billeder udført mod grafikmodellen ISO 32000-1 — ikke et gitter af pixels. Den indlysende måde at udskrive en på er at rasterisere siden til et bitmap og overføre dette bitmap til printerens lærred, og det virker, men det smider den ene ting væk, som en printer er god til. En moderne laserprinter klarer 600 eller 1200 DPI; et bitmap rasteriseret ved 150 eller 300 DPI og derefter strakt for at passe ankommer uskarpt med takkede tekstkanter og synlig interpolation. RenderLoadedPageToDC tager den bedre vej: Den genafspiller sidens indholdsstrøm som GDI-kald, der sendes direkte ind i målenhedens kontekst, så vektortekst og stregkunst når printeren som vektorer og rasteriseres én gang af printeren ved printerens egen opløsning

Hvordan udskriver du en indlæst PDF til en fysisk printer i Delphi?

HotPDF udskriver et indlæst dokument med PrintLoadedDocument(Printer, Options), som tager en tildelt VCL TPrinter og en THPDFPrintOptions-post, udskriver de valgte sider og returnerer antallet af sendte sider. Indstil Printer.PrinterIndex først, så der vælges en enhed, udfyld en post for indstillinger — klassefunktionen THPDFPrintOptions.Default giver dig fornuftige værdier — og kald den én gang. Modulerne åbner jobbet med Printer.BeginDoc, gennemgår sideområdet og udsender en Printer.NewPage mellem siderne, og lukker det med Printer.EndDoc, så du aldrig administrerer printjobbets livscyklus i hånden

uses Printers;

var
  Pdf: THotPDF;
  Opts: THPDFPrintOptions;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('invoice.pdf') > 0 then
    begin
      Printer.PrinterIndex := -1;         // -1 selects the default printer
      Opts := THPDFPrintOptions.Default;  // all pages, 300 DPI, FitPage, colour
      Opts.PageRange := '1,3-5';          // one-based; empty prints every page
      Opts.Copies := 2;
      Pdf.PrintLoadedDocument(Printer, Opts);
    end;
  finally
    Pdf.Free;
  end;
end;

Strengen PageRange er 1-baseret og læses på samme måde som en udskriftsdialogboks: '1,3-5' udskriver side 1 og side 3 til 5, og en tom streng udskriver hele dokumentet. Copies kortlægges direkte til Printer.Copies. Vær dog ærlig over for dig selv om Collate: Fordi VCL eksponerer sortering inkonsekvent på tværs af Delphi-versioner, indstiller HotPDF antallet af kopier og lader sorteringen være op til printerdriverens standard, så når du har brug for en garanteret sorteringsrækkefølge, skal du indstille den på driveren via TPrinterSetupDialog frem for at stole på, at flaget bærer den

Hvordan bestemmer DPI og FitPage udskriftsstørrelsen?

FitPage og DPI interagerer på en måde, der er værd at forstå, før du leverer. Med FitPage sat til True — standarden — læser HotPDF hver sides MediaBox, skalerer den til Printer.PageWidth og Printer.PageHeight under bevarelse af højde-bredde-forholdet, og renderer i den skala, der får siden til at udfylde papiret. I den tilstand tilsidesættes Options.DPI reelt af tilpasningsskalaen, fordi outputtet skal matche printerens fysiske sidedimensioner. Med FitPage sat til False renderer HotPDF hver side 1:1 at præcis Options.DPI, hvilket kortlægger 72 PDF-enheder til DPI-enhedspixels, hvilket er det, du ønsker, når kildesiden og papiret allerede har samme størrelse, og du går op i en præcis opløsning. Grib til FitPage, når kildesidens størrelse og skuffens størrelse er forskellige; grib til 1:1, når de matcher, og du ønsker en deterministisk skalering

To indstillinger tilføjet i v2.348.0 retter de udskrifter, der ser næsten rigtige ud. Enhver fysisk printer har en hård margen — en ikke-printbar kant, som hardwaren ikke kan nå — og som standard lander sidens startpunkt inden for den, så en side til kant mister en strimmel af to kanter. Sæt IgnoreHardMargin til True, og HotPDF forespørger printerens PHYSICALOFFSETX og PHYSICALOFFSETY, og forskyder derefter enhedens startpunkt for at annullere denne forskydning, så sidens startpunkt kortlægges til det sande papirhjørne. Den anden indstilling, AutoRotate, er slået til som standard: Den læser hver sides MediaBox, og når en side er bredere end den er høj, skifter den printeren til liggende format, så en bred side udskrives uden at blive beskåret til stående. AutoRotate træder til side i det øjeblik, du indstiller Orientation eksplicit, så et bevidst valg af retning altid vinder

Hvordan renderer du en PDF-side i enhver enhedskontekst?

RenderLoadedPageToDC(PageIndex, DC, DPI, W, H) er den primitive del under udskrivningsløkken, og den er nyttig i sig selv. PrintLoadedDocument kalder den én gang pr. side mod printerens lærred, men målet kan være enhver Windows-HDC: En hukommelses-DC uden for skærmen, en kontrolelements lærred i en brugerdefineret fremviser eller en overflade til visning af udskrift. PageIndex is 0-baseret, W og H er enhedsenhederne på måloverfladen, og rendereren gennemgår sidens /Contents og sender GDI-kald ind i din DC. Én bevidst adfærd er værd at kende: Den tegner intet baggrundsfyld. Kalderen ejer overfladen, så hvis du vil have hvidt papir bag siden, skal du selv udfylde din DC før rendering, hvilket er præcis det, der lader dig sammensætte en side over et eksisterende lærred, når du ønsker det

// Draw page 1 into an off-screen 24-bit surface at 150 DPI
var
  Surface: TBitmap;
begin
  Surface := TBitmap.Create;
  try
    Surface.PixelFormat := pf24bit;
    Surface.SetSize(1275, 1650);           // 8.5 x 11 in at 150 DPI
    Surface.Canvas.Brush.Color := clWhite;
    Surface.Canvas.FillRect(Surface.Canvas.ClipRect);  // caller paints the background
    Pdf.RenderLoadedPageToDC(0, Surface.Canvas.Handle, 150, Surface.Width, Surface.Height);
    // Surface now holds the composited page, ready to blit or save
  finally
    Surface.Free;
  end;
end;

Når du bare har brug for et færdigt TBitmap — en miniature, en billed-eksport, en forhåndsvisning du vil cache — skal du i stedet række ud efter RenderLoadedPageToBitmap, dækket i den ledsagende artikel om rendering af PDF-sider til et bitmap. Forskellen er, hvem der ejer overfladen: Bitmap-kaldet tildeler og returnerer en pixelbuffer, mens RenderLoadedPageToDC tegner i en enhedskontekst, du allerede har, hvilket er præcis, hvad et printerlærred eller en tegnehåndtering giver dig. Begge deler den samme indholdsstrømsfortolker og indlejrede glyf-motor, så tekst kommer ud med de præcise indlejrede konturer i begge tilfælde

Hvordan indsætter du en PDF-side i Word eller et billedredigeringsprogram?

RenderLoadedPageToClipboard(PageIndex, DPI, AsMetafile) placerer én side på Windows-udklipsholderen, klar til at blive sat ind i Word, PowerPoint, en e-mail eller et billedredigeringsprogram. Flaget AsMetafile vælger formatet, og valget betyder mere, end det ser ud til. Send False, og HotPDF placerer et 24-bit enhedsbitmap (CF_BITMAP) renderet ved din DPI — et fast gitter af pixels, der kan indsættes hvor som helst, men bliver pixeleret, når modtageren skalerer det op. Send True, og den placerer en forbedret metafiler (CF_ENHMETAFILE), hvor sidens tekst og vektor-kunst rejser som GDI-tegnekommandoer, så det indsatte resultat forbliver skarpt ved enhver zoom og tilpasser sig den størrelse, som måldokumentet giver det

// Copy page 2 as a scalable vector metafile for pasting into Word
Pdf.RenderLoadedPageToClipboard(1, 300, True);

// Copy the same page as a fixed 300-DPI bitmap instead
Pdf.RenderLoadedPageToClipboard(1, 300, False);

Tommelfingerreglen er enkel. Hvis et menneske vil indsætte siden i et dokument og måske ændre størrelsen på den — en figur i en rapport, en klausul droppet ind i et kontraktudkast — skal du bruge metafilen, fordi vektortekst udskriver og zoomer rent. Hvis destinationen kun forstår rasterdata, eller du specifikt ønsker et fastfrosset øjebliksbillede i en kvend opløsning, skal du bruge bitmap. Hvis du vil trække ordene ud af en side i stedet for et billede af dem, er det en helt anden opgave, der håndteres af API'en til tekstudtrækning, som returnerer tegnene og deres positioner i stedet for et renderet billede

Hvor udskrivningsstien ophører

Alt på denne side er kun til Windows, og det er værd at sige tydeligt. PrintLoadedDocument, RenderLoadedPageToDC og RenderLoadedPageToClipboard er bygget på TPrinter, GDI-enhedskontekstmodellen, Windows-udklipsholderen og forbedrede metafiler — alle Win32- og Win64-konstruktioner. På andre målplatforme opretter, redigerer og læser resten af HotPDF stadig PDF, men denne GDI-støttede udskrivnings- og udklipsholderflade er ikke tilgængelig. Rendereren sigter også mod den fælles dokument-delmængde af tekst, stier og billeder, så gradienttunge designkorrekturark og ICC-styrede farver udskrives som en trofast forhåndsvisning snarere end en kolorimetrisk korrektur, den samme grænse som bitmap-rendereren bærer

Ved batch-udskrivning på tværs af mange filer skal du indlæse og udskrive hvert dokument efter tur og holde øje med hukommelsesforbruget: PrintLoadedDocument renderer én side ad gangen, men selve grafen for det indlæste dokument lever i hukommelsen under hele jobbet. Når du driver en udskriftskø over hundredvis af store filer, den streamende Direct File API til store PDF-workflows passer vel sammen med udskrivningsstien — opdel, flet eller vælg de sider, du har brug for på disken først, og indlæs derefter kun det slanke resultat for at udskrive. Det er sådan, PrintLoadedDocument, RenderLoadedPageToDC og RenderLoadedPageToClipboard leveres som en del af HotPDF Component til Delphi og C++Builder — et indfødt VCL-bibliotek uden eksterne DLL-afhængigheder, der dækker PDF-oprettelse, redigering, tekstudtrækning, rendering og nu udskrivning direkte til TPrinter, enhver enhedskontekst eller udklipsholderen