アプリ内部でPDFを表示する

オープンソースとなったChromeのエンジン、PDFuimを使うと簡単です。 ただし、C++で書かれているライブラリなので、C#から使うにはPdfiumViewerのようなラッパーか、.NETの相互運用機能を利用する必要があります。 ここでは両方の方法を示します。

■ PdfiumViewerを利用する方法
1.Visual Studioの新しいプロジェクトでWindowsフォームアプリケーションを作成
2.ツール → NuGetパッケージマネージャー → ソリューションのNuGetパッケージ管理
3.参照 で PdfiumViewer を検索して、以下をインストール
 PdfiumViewer
 dfiumViewer.Native.x86.v8-xfa または PdfiumViewer.Native.x86_64.v8-xfa
4.フォームにボタンを配置
5.参照を解決するために以下を追加
 using PdfiumViewer;
 using System.Drawing.Imaging;
6.ボタンのクリックイベントに以下を挿入
 PdfDocument pdfDoc = PdfDocument.Load("C:\\work\\Sample.pdf");
 Image img = pdfDoc.Render(0, 300, 300, false);
 img.Save("C:\\work\\SampleImage.png", ImageFormat.Png);

■ C#からNative DLLを直接使う方法
処理コード自体はこちらの方法でも大して変わりませんが、DLLのメソッドの定義をするのが大変です(当たり前といえば当たり前。それを代行してくれるのが先のPdfuimViewerのようなラッパーですから)。 しかし、一ページ表示するだけの単純な処理なら、以下に記載した内容で可能です。
「DLL や Win32 API の関数を C# から呼び出す」の項も参照してください。

まず、以下から、PDFiumの Pre-compiled binaries を取得します。
https://github.com/bblanchon/pdfium-binaries

プログラムコードは以下のようなものでページのイメージを取得できます。
[DllImport("pdfium.dll", EntryPoint = "FPDF_InitLibrary", CallingConvention = CallingConvention.Cdecl)]
public static extern void FPDF_InitLibrary();

[StructLayout(LayoutKind.Sequential)]
public struct FPDF_LIBRARY_CONFIG
{
    public int version;
    public IntPtr m_pUserFontPaths;
    public IntPtr m_pIsolate;
    public uint m_v8EmbedderSlot;
}

[DllImport("pdfium.dll", EntryPoint = "FPDF_InitLibraryWithConfig", CallingConvention = CallingConvention.Cdecl)]
public static extern void FPDF_InitLibraryWithConfig(ref FPDF_LIBRARY_CONFIG config);

[DllImport("pdfium.dll", EntryPoint = "FPDF_DestroyLibrary", CallingConvention = CallingConvention.Cdecl)]
public static extern void FPDF_DestroyLibrary();

[DllImport("pdfium.dll", EntryPoint = "FPDF_LoadDocument", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr FPDF_LoadDocument(string file_path, string password);

[DllImport("pdfium.dll", EntryPoint = "FPDF_CloseDocument", CallingConvention = CallingConvention.Cdecl)]
public static extern void FPDF_CloseDocument(IntPtr document);

[DllImport("pdfium.dll", EntryPoint = "FPDF_GetPageCount", CallingConvention = CallingConvention.Cdecl)]
public static extern int FPDF_GetPageCount(IntPtr document);

[DllImport("pdfium.dll", EntryPoint = "FPDF_LoadPage", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr FPDF_LoadPage(IntPtr document, int page_index);

[DllImport("pdfium.dll", EntryPoint = "FPDF_GetPageWidth", CallingConvention = CallingConvention.Cdecl)]
public static extern double FPDF_GetPageWidth(IntPtr page);

[DllImport("pdfium.dll", EntryPoint = "FPDF_GetPageHeight", CallingConvention = CallingConvention.Cdecl)]
public static extern double FPDF_GetPageHeight(IntPtr page);

[DllImport("pdfium.dll", EntryPoint = "FPDF_RenderPage", CallingConvention = CallingConvention.Cdecl)]
public static extern void FPDF_RenderPage(IntPtr hDC, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, int flags);

[DllImport("pdfium.dll", EntryPoint = "FPDF_RenderPageBitmap", CallingConvention = CallingConvention.Cdecl)]
public static extern void FPDF_RenderPageBitmap(IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, int flags);

[DllImport("pdfium.dll", EntryPoint = "FPDFBitmap_Create", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr FPDFBitmap_Create(int width, int height, bool isUseAlpha);


public Bitmap CreatePdfPageImage(string pdfFilePath, int pageNo)
{
    Bitmap bitmap = null;
    FPDF_InitLibrary();
    IntPtr pdfDocument = FPDF_LoadDocument(pdfFilePath, null);
    if (pdfDocument != null)
    {
        int Dpi = 96;
        int pages = FPDF_GetPageCount(pdfDocument);
        if (pageNo < pages)
        {
            IntPtr pdfPage = FPDF_LoadPage(pdfDocument, pageNo);
            int pageWidth = PointToPixel(Dpi, FPDF_GetPageWidth(pdfPage));
            int pageHeight = PointToPixel(Dpi, FPDF_GetPageHeight(pdfPage));
            bitmap = new Bitmap(pageWidth, pageHeight);
            bitmap.SetResolution(Dpi, Dpi);
            Graphics g = Graphics.FromImage(bitmap);
            g.FillRectangle(Brushes.White, 0, 0, pageWidth, pageHeight);
            IntPtr hDC = g.GetHdc();
            FPDF_RenderPage(hDC, pdfPage, 0, 0, pageWidth, pageHeight, 0, 0);
            g.ReleaseHdc();
            g.Dispose();
        }
        FPDF_CloseDocument(pdfDocument);
    }
    FPDF_DestroyLibrary();
    return bitmap;
}

private int PointToPixel(int Dpi, double value)
{
    return (int)((value * Dpi) / 72);
}