アプリ内部で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);
}