このページには自動翻訳されたテキストを含めることができます。

C# および VB.NET で PDF ドキュメントをレンダリングして印刷する

PDF ドキュメントの閲覧といえば、誰もが Adobe Reader を思い浮かべます。しかし、ソフトウェア開発者としてアプリケーション内で PDF ドキュメントを表示したい場合はどうでしょうか。ユーザーに Adobe Reader をセットアップして、そこで文書を開くよう求めたくはないはずです。

他の PDF 関連要件を実装する必要がある場合もあります。たとえば、PDF ドキュメントを印刷する。あるいはアップロードされた PDF ドキュメントのサムネイルを生成する。デスクトップアプリや Web アプリで PDF 編集をサポートする、といった場合です。

必要なのは、PDF ドキュメントをレンダリングして印刷できる PDF ライブラリだけです。

C# で PDF を印刷する

PDF ドキュメントを表示、編集、または印刷するための .NET ライブラリ

Docotic.Pdf library を使用すると、C# および VB.NET で PDF ドキュメントを表示、編集、印刷できます。3 つの基本機能を使って、複雑な PDF レンダリングフローを実装できます。

1 つ目は、PDF を画像に変換する機能です。この機能を基盤に、ほぼすべてを実装できます。PDF の印刷から、HoloLens での PDF 表示、Instagram への PDF 投稿まで対応できます。これは、画像があらゆる場所でサポートされているため可能です。

2 つ目の主要機能は、PDF ページを System.Drawing.Graphics の描画サーフェスに描画できることです。これにより、Windows Forms や WPF アプリケーションで PDF をレンダリングして印刷できます。この機能を使うには、BitMiracle.Docotic.Pdf.Gdi extension 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 名前空間のクラスを使用できます。印刷 UI を構築するための便利な PrintDialog と PrintPreviewDialog クラスもあります。

macOS および Linux 環境では、System.Drawing 名前空間のいかなる要素も使用しないことを推奨します。macOS および Linux の System.Drawing 実装は、Windows 実装と比べて不完全であり、動作も異なります。macOS および Linux 環境で System.Drawing 名前空間を使用すると、結果が不正確になったり、一貫性が失われたりする可能性があります。

WPF には別の PrintDialog クラスがありますが、印刷プレビュー用のクラスは提供されていません。幸い、WPF では System.Windows.Forms.dll の PrintPreviewDialog クラスを使用できます。そのため、WPF アプリケーションでは System.Windows.Forms と System.Drawing.Printing 名前空間の印刷クラスを使うほうが簡単です。

WinForms および WPF 向けに C# と VB.NET 版が用意されている Print PDF in .NET デモアプリケーションを確認してください。このアプリケーションは、次の内容を示します。

  • PDF ドキュメントの印刷プレビューを表示する
  • 選択したプリンターに PDF ドキュメントを印刷する
  • 用紙サイズ、スケーリングモード、その他の印刷設定を構成する

このアプリケーションは、Docotic.Pdf library、BitMiracle.Docotic.Pdf.Gdi extension DLL、および System.Windows.Forms と System.Drawing.Printing 名前空間の印刷クラスを使用します。WPF または Windows Forms プロジェクトでは、PdfPrintDocument と PdfPrintHelper クラスを使用できます。

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 拡張メソッドを使用して、現在の PDF ページを Graphics オブジェクトに描画します。

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 印刷を実装するには、次の手順に従います。

  • サンプル から PdfPrintDocument、PdfPrintHelper、PrintSize ファイルを追加する
  • Docotic.Pdf library への参照を追加する
  • BitMiracle.Docotic.Pdf.Gdi extension 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;

// 1 ページを保存する
pdf.Pages[0].Save("page0.png", options);

// 文書全体を複数ページの bitonal TIFF として保存する
options.Compression = ImageCompressionOptions.CreateTiff().SetBitonal();
pdf.SaveAsTiff("your_document.tiff", options);

その後、別の印刷フレームワークまたはツールを使って画像を印刷します。System.Drawing.Printing を使わずに PDF ドキュメントを印刷する方法を示す Print PDF in Eto.Forms デモアプリケーションを確認してください。

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 extension DLL を追加する必要があります。

.NET アプリケーションで PDF ビューアーまたは PDF エディターを作成する

Docotic.Pdf を使うと、PDF ページ上のすべてのオブジェクトについて詳細情報を取得できます。PDF ページからテキストチャンク、画像、ベクターパス、フォームコントロール、注釈を抽出できます。

その後、アプリケーション内で抽出したすべてのオブジェクトをレンダリングできます。また、レンダリングしたオブジェクトを選択・編集する機能も実装できます。

PDF からテキスト、画像、パスを抽出する サンプルを確認してください。System.Drawing.Graphics コンテキストにページオブジェクトを抽出して描画する方法を示します。

テキストオブジェクトをベクターパスとして抽出することもできます。その場合は、PdfPage.GetObjects(PdfObjectExtractionOptions) のオーバーロードを使用します。

結論

.NET プロジェクトで PDF ドキュメントを表示および印刷するには、Docotic.Pdf library を使用してください。関連する C# および VB.NET サンプルを確認してください。

PDF の印刷またはレンダリングについて質問がある場合は、お問い合わせください。