Windows 10 and above include Windows.Data.Pdf
APIs which permit printing and display of PDF files via Direct2D. No additional licenses or software are required, and the API's may be called from desktop and UWP applications.
Rmg.PdfPrinting
, a small wrapper which exposes that functionality to .Net, is available on Nuget which permits printing via:
var pdfPrinter = new Rmg.PdfPrinting.PdfPrinter();
await pdfPrinter.Print("Printer Name", "Example.pdf");
If you prefer to avoid the wrapper, P/Invokes to CreateDocumentPackageTargetForPrintJob
, PdfCreateRenderer
, and a few other native API's are required:
var pdfFile = await StorageFile.GetFileFromPathAsync("example.pdf");
var pdfDoc = await PdfDocument.LoadFromFileAsync(pdfFile);
// Initializing DXGI, D3D, D2D, and WIC are omitted for brevity
// See https://github.com/mgaffigan/D2DPdfPrintSample/blob/master/PrintPdfManaged/Program.cs#L55
// Initialize the job
ID2D1PrintControl printControl;
{
// Create a factory for document print job.
var documentTargetFactory = (IPrintDocumentPackageTargetFactory)new PrintDocumentPackageTargetFactory();
IPrintDocumentPackageTarget docTarget;
documentTargetFactory.CreateDocumentPackageTargetForPrintJob(
printerName, jobName, null, ArrayToIStream(ticket), out docTarget);
// Create a new print control linked to the package target.
d2dDevice.CreatePrintControl(pWic, docTarget, null, out printControl);
}
// Open the PDF Document
PInvoke.PdfCreateRenderer(dxgiDevice, out var pPdfRendererNative).ThrowOnFailure();
var renderParams = new PDF_RENDER_PARAMS();
// Write pages
for (uint pageIndex = 0; pageIndex < pdfDoc.PageCount; pageIndex++)
{
var pdfPage = pdfDoc.GetPage(pageIndex);
d2dContextForPrint.CreateCommandList(out var commandList);
d2dContextForPrint.SetTarget(commandList);
d2dContextForPrint.BeginDraw();
pPdfRendererNative.RenderPageToDeviceContext(pdfPage, d2dContextForPrint, &renderParams);
d2dContextForPrint.EndDraw();
commandList.Close();
printControl.AddPage(commandList, pdfPage.Size.AsD2dSizeF(), null);
}
printControl.Close();
A full sample without the wrapper in C# and C++ are available from Github.