該頁面可以包含自動翻譯的文字。

在 C# 和 VB.NET 中呈現與列印 PDF 文件

每個人談到閱讀 PDF 文件時,首先想到的都是 Adobe Reader。但如果你是軟體開發人員,並且想在應用程式中顯示 PDF 文件,該怎麼辦?你不會希望要求使用者先安裝 Adobe Reader,然後在那裡開啟文件。

你可能還需要實作其他與 PDF 相關的需求。例如,列印 PDF 文件。或者為上傳的 PDF 文件產生縮圖。或者在桌面或 Web 應用程式中支援 PDF 編輯。

你只需要一個能夠呈現並列印 PDF 文件的 PDF 程式庫。

在 C# 中列印 PDF

用於檢視、編輯或列印 PDF 文件的 .NET 程式庫

Docotic.Pdf 程式庫可讓你在 C# 和 VB.NET 中顯示、編輯和列印 PDF 文件。你可以使用三個核心功能來實作任何複雜的 PDF 呈現流程。

第一個功能是將 PDF 轉換為影像的能力。你幾乎可以根據這個功能實作一切,從 PDF 列印到在 HoloLens 上顯示 PDF,或將 PDF 發佈到 Instagram 都可以。這之所以可行,是因為影像幾乎到處都支援。

第二個關鍵功能是能夠在 System.Drawing.Graphics 的繪圖表面上繪製 PDF 頁面。它可讓你在 Windows Forms 或 WPF 應用程式中呈現並列印 PDF。若要使用此功能,請將 BitMiracle.Docotic.Pdf.Gdi 擴充 DLL 加入專案。

最後但同樣重要的是擷取 PDF 頁面物件的能力。此功能可讓你在 C# 或 VB.NET 應用程式中建立 PDF 檢視器或 PDF 編輯器。

請在 下載 C# .NET PDF 函式庫 頁面取得程式庫與免費的限時授權金鑰。

.NET 預設不支援列印 PDF 文件。你需要先將 PDF 文件轉換為影像、XPS 檔案,或將其繪製到 System.Drawing.Graphics 表面。然後,你就可以使用 .NET 類別,在 Windows Forms 或 WPF 應用程式中列印輸出。

在 Windows Forms 應用程式中,你可以使用 System.Drawing.Printing 命名空間中的類別。也有實用的 PrintDialogPrintPreviewDialog 類別可用來建構列印 UI。

請注意,不建議在 macOS 和 Linux 環境中使用 System.Drawing 命名空間中的任何內容。System.Drawing 在 macOS 和 Linux 上的實作不完整,且與 Windows 實作不同。如果你在 macOS 和 Linux 環境中使用 System.Drawing 命名空間,可能會得到不正確或不一致的結果。

WPF 提供了另一個 PrintDialog 類別,但沒有提供列印預覽類別。幸好,WPF 允許你使用來自 System.Windows.Forms.dll 的 PrintPreviewDialog 類別。因此,在 WPF 應用程式中使用 System.Windows.FormsSystem.Drawing.Printing 命名空間中的列印類別更容易。

看看提供 C# 和 VB.NET 版本、適用於 WinForms 和 WPF 的 在 .NET 中列印 PDF 範例應用程式。該應用程式示範如何:

  • 顯示 PDF 文件的列印預覽
  • 將 PDF 文件列印到選取的印表機
  • 設定紙張大小、縮放模式和其他列印設定

該應用程式使用 Docotic.Pdf 程式庫、BitMiracle.Docotic.Pdf.Gdi 擴充 DLL,以及來自 System.Windows.FormsSystem.Drawing.Printing 命名空間的列印類別。你可以在 WPF 或 Windows Forms 專案中使用其 PdfPrintDocumentPdfPrintHelper 類別。

PdfPrintDocument 類別描述主要列印邏輯。此類別將 Docotic.Pdf 與 System.Drawing.Printing.PrintDocument 類別連接起來。關鍵方法是 printDocument_PrintPage 事件處理常式:

private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
    Graphics gr = e.Graphics ?? throw new InvalidOperationException("No Graphics!");

    // 使用點為單位,以在所有情境下保持一致的單位:
    // 1. 印表機
    // 2. 列印預覽
    // 3. PDF
    gr.PageUnit = GraphicsUnit.Point;

    if (m_printAction == PrintAction.PrintToPreview)
    {
        gr.Clear(Color.LightGray);
        gr.FillRectangle(Brushes.White, m_printableAreaInPoints);
        gr.IntersectClip(m_printableAreaInPoints);

        gr.TranslateTransform(m_printableAreaInPoints.X, m_printableAreaInPoints.Y);
    }

    PdfPage page = m_pdf.Pages[m_pageIndex];
    PdfSize pageSizeInPoints = getPageSizeInPoints(page);

    if (m_printSize == PrintSize.FitPage)
    {
        float sx = (float)(m_printableAreaInPoints.Width / pageSizeInPoints.Width);
        float sy = (float)(m_printableAreaInPoints.Height / pageSizeInPoints.Height);
        float scaleFactor = Math.Min(sx, sy);

        centerContentInPrintableArea(gr, pageSizeInPoints, scaleFactor);
        gr.ScaleTransform(scaleFactor, scaleFactor);
    }
    else if (m_printSize == PrintSize.ActualSize)
    {
        centerContentInPrintableArea(gr, pageSizeInPoints, 1);
    }

    page.Draw(gr);

    ++m_pageIndex;
    e.HasMorePages = (m_pageIndex <= m_lastPageIndex);
}

首先,我們設定已列印頁面 Graphics 物件的轉換。必須正確處理「符合頁面」與「實際大小」設定。我們也會在列印預覽對話框中顯示印表機的硬邊界。接著,我們使用 PdfPage.Draw 擴充方法在 Graphics 物件上繪製目前的 PDF 頁面。

PdfPrintHelper 類別可讓你搭配用於列印的 UI 類別使用 PdfPrintDocument。例如,你可以像這樣為 PDF 文件顯示列印對話框:

using (var pdf = new PdfDocument("your_document.pdf"))
    action(pdf, getPrintSize());

public static DialogResult ShowPrintDialog(PdfDocument pdf, PrintSize printSize)
{
    using (var printDialog = new PrintDialog())
    {
        printDialog.AllowSomePages = true;
        printDialog.AllowCurrentPage = true;
        printDialog.AllowSelection = true;

        printDialog.PrinterSettings.MinimumPage = 1;
        printDialog.PrinterSettings.MaximumPage = pdf.PageCount;
        printDialog.PrinterSettings.FromPage = printDialog.PrinterSettings.MinimumPage;
        printDialog.PrinterSettings.ToPage = printDialog.PrinterSettings.MaximumPage;

        var result = printDialog.ShowDialog();
        if (result == DialogResult.OK)
        {
            using (var printDocument = new PdfPrintDocument(pdf, printSize))
                printDocument.Print(printDialog.PrinterSettings);
        }

        return result;
    }
}

就是這樣。若要在 Windows Forms 或 WPF 應用程式中實作 PDF 列印,請執行以下步驟:

  • 範例 加入 PdfPrintDocumentPdfPrintHelperPrintSize 檔案
  • 加入 Docotic.Pdf 程式庫的參考
  • 加入 BitMiracle.Docotic.Pdf.Gdi 擴充 DLL 的參考
  • (僅限 WPF)加入 System.Windows.Forms 和 System.Drawing 組件的參考

System.Drawing.Printing 命名空間中的類別在 Windows Forms 和 WPF 應用程式中表現良好。不過,有些情況下你不能或不應該使用 System.Drawing.Printing

例如,不應在 Windows 服務或 ASP.NET 應用程式中使用 System.Drawing.Printing。在 Linux 或 macOS 上列印時,System.Drawing.Printing 可能會產生不一致的結果。而且你無法在 Eto.Forms 或 Avalonia 應用程式中使用 System.Drawing.Printing

在這些情況下,你需要先將 PDF 文件轉換為影像。這個 C# 範例示範如何將 PDF 頁面儲存為 PNG 影像,或將整份 PDF 文件轉換為多頁 TIFF:

using var pdf = new PdfDocument(@"your_document.pdf");

PdfDrawOptions options = PdfDrawOptions.Create();
options.HorizontalResolution = printerDpi;
options.VerticalResolution = printerDpi;

// 儲存一頁
pdf.Pages[0].Save("page0.png", options);

// 將整份文件儲存為多頁雙色調 TIFF
options.Compression = ImageCompressionOptions.CreateTiff().SetBitonal();
pdf.SaveAsTiff("your_document.tiff", options);

然後,使用替代的列印架構或工具列印影像。看看 在 Eto.Forms 中列印 PDF 範例應用程式,它示範如何在不使用 System.Drawing.Printing 的情況下列印 PDF 文件。

在 C# 和 VB.NET 中呈現 PDF

在應用程式中顯示 PDF 與列印類似。在 ASP.NET、WPF、Eto.Forms、Avalonia 或任何其他應用程式類型中,先將 PDF 轉換為影像,再顯示該影像。

在 Windows Forms 應用程式中,你可以從任何控制項在 System.Drawing.Graphics 內容上繪製 PDF 頁面。或者,你也可以將 PDF 頁面轉換為 System.Drawing.Bitmap,再將點陣圖顯示在 PictureBox 中。

此範例示範如何在 C# 中將 PDF 頁面轉換為 Bitmap

using var pdf = new PdfDocument("render.pdf");
const float TargetResolution = 300;

PdfPage page = pdf.Pages[0];
double scaleFactor = TargetResolution / page.Resolution;

using var bitmap = new Bitmap((int)(page.Width * scaleFactor), (int)(page.Height * scaleFactor));
bitmap.SetResolution(TargetResolution, TargetResolution);

using (Graphics gr = Graphics.FromImage(bitmap))
    page.Draw(gr);

bitmap.Save("result.png");

上述程式碼需要你在專案中加入 BitMiracle.Docotic.Pdf.Gdi 擴充 DLL

在 .NET 應用程式中建立 PDF 檢視器或 PDF 編輯器

Docotic.Pdf 可讓你取得 PDF 頁面上每個物件的詳細資訊。你可以從 PDF 頁面擷取文字區塊、影像、向量路徑、表單控制項和註解。

接著,在應用程式中,你可以呈現所有已擷取的物件。你也可以實作選取並編輯已呈現物件的能力。

請參考 從 PDF 擷取文字、影像與路徑 範例。它示範如何將頁面物件擷取並繪製到 System.Drawing.Graphics 內容。

你也可以將文字物件擷取為向量路徑。為此請使用 PdfPage.GetObjects(PdfObjectExtractionOptions) 多載。

結論

使用 Docotic.Pdf 程式庫在 .NET 專案中顯示和列印 PDF 文件。請參考相關的 C# 和 VB.NET 範例:

如果你對 PDF 列印或呈現有任何問題,請聯絡我們