using System; using System.IO; using System.Printing; namespace Elwig.Helpers.Printing { public class PdfPrinter { public string PrinterName { get; init; } public PdfPrinter(string? printerName = null) { PrinterName = printerName ?? GetDefaultPrinterName() ?? throw new InvalidOperationException("No default Windows printer is configured."); } public void Print(string pdfPath, int copies = 1, bool doublePaged = false) { if (!File.Exists(pdfPath)) throw new FileNotFoundException("PDF file not found.", pdfPath); IntPtr document = PdfiumNative.FPDF_LoadDocument(pdfPath, null); if (document == IntPtr.Zero) throw new InvalidOperationException("PDFium could not open the PDF."); try { int pageCount = PdfiumNative.FPDF_GetPageCount(document); if (pageCount <= 0) return; using var printer = new Win32Printer.Printer(PrinterName); printer.TrySetDuplex(doublePaged ? Duplexing.TwoSidedLongEdge : Duplexing.OneSided); for (int i = 0; i < copies; i++) { printer.StartDocument(Path.GetFileName(pdfPath)); bool documentStarted = true; try { for (int j = 0; j < pageCount; j++) { PrintPage(document, printer, j); } printer.EndDocument(); documentStarted = false; } finally { if (documentStarted) printer.AbortDocument(); } } } finally { PdfiumNative.FPDF_CloseDocument(document); } } private static void PrintPage(IntPtr document, Win32Printer.Printer printer, int pageIndex) { if (!PdfiumNative.FPDF_GetPageSizeByIndex(document, pageIndex, out double pageWidthPt, out double pageHeightPt)) { throw new InvalidOperationException($"Unable to obtain PDF page {pageIndex} size."); } IntPtr page = PdfiumNative.FPDF_LoadPage(document, pageIndex); if (page == IntPtr.Zero) throw new InvalidOperationException($"Unable to load PDF page {pageIndex}."); try { int renderWidth = (int)Math.Round(pageWidthPt / 72.0 * printer.DpiX); int renderHeight = (int)Math.Round(pageHeightPt / 72.0 * printer.DpiY); int offsetX = (printer.PrintableWidth - renderWidth) / 2; int offsetY = (printer.PrintableHeight - renderHeight) / 2; printer.StartPage(); try { PdfiumNative.FPDF_RenderPage(printer.Hdc, page, offsetX, offsetY, renderWidth, renderHeight, 0, PdfiumNative.FPDF_PRINTING | PdfiumNative.FPDF_ANNOT); } finally { printer.EndPage(); } } finally { PdfiumNative.FPDF_ClosePage(page); } } private static string? GetDefaultPrinterName() { using var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\Windows"); string? printer = key?.GetValue("Device") as string; if (string.IsNullOrWhiteSpace(printer)) return null; // Device has the form: // Printer Name,winspool,PORT int comma = printer.IndexOf(','); return comma >= 0 ? printer[..comma] : printer; } } }