在Winform中显示PDF文件

26

我正在用C#(Windows窗体)创建一个简单的计算器。

我已经创建了一个“用户帮助”文件,它是一个pdf文件。我想要的是,在用户单击WinForm中的“帮助”按钮时显示该pdf文件。假设用户的计算机上预安装了Adobe Reader....

如何在WinForm中的按钮点击时打开pdf文件?

我不打算将此pdf文件提供给用户的硬盘驱动器。这意味着我必须将此pdf嵌入到计算器(WinForm)中,并在按钮单击时显示它。

请指导我在WinForm中显示嵌入文件的最佳实践。


为什么你不想把PDF作为一个单独的文件呢? - SurDin
因为如果考虑到“分发”,那么开发一个实用程序就不应该是分散的。只有exe文件(无需安装)将完美地作为一个简单的“计算器”工作,提供与之相关的文件片段并不是一个好的做法,我认为。如果我错了,请纠正我。 - gsvirdi
11个回答

24

您可以引用Adobe Reader ActiveX控件并将其捆绑到您的应用程序中。

只需从COM组件选项卡(右键单击工具箱,然后单击“选择项目...”)添加AcroPDF.PDF.1到您的工具箱中,然后将一个实例拖放到您的Winform上,设计师会为您创建代码。或者,在添加必要的引用之后,您可以使用以下代码:

AxAcroPDFLib.AxAcroPDF pdf = new AxAcroPDFLib.AxAcroPDF();
pdf.Dock = System.Windows.Forms.DockStyle.Fill;
pdf.Enabled = true;
pdf.Location = new System.Drawing.Point(0, 0);
pdf.Name = "pdfReader";
pdf.OcxState = ((System.Windows.Forms.AxHost.State)(new System.ComponentModel.ComponentResourceManager(typeof(ViewerWindow)).GetObject("pdfReader.OcxState")));
pdf.TabIndex = 1;

// Add pdf viewer to current form        
this.Controls.Add(pdf);

pdf.LoadFile(@"C:\MyPDF.pdf");
pdf.setView("Fit");
pdf.Visible = true;

5
如果用户选择使用第三方控件来阅读PDF文档,那么这并不是很好。 - Ian Ringrose
@Ian,你是在暗示一个WinForms计算器应用程序应该从同一台机器上的IE继承配置吗?我希望不是这样。 - Winston Smith
Adobe Reader ActiveX控件是否支持“注册免费COM”,还是用户需要安装它? - Ian Ringrose
1
@Winsten,不过它不应该更改IE/Firefox已设置使用的PDF阅读器,安装应用程序时安装Adobe Reader可能会更改各种设置(了解Adobe!) - Ian Ringrose
@Ian - 用户的设置肯定不会被更改,也不会安装Adobe Reader。这种方法只是意味着将两个DLL文件与您的应用程序捆绑在一起(AxInterop.AcroPDFLib.dllInterop.AcroPDFLib.dll),它用于显示PDF。 - Winston Smith
1
@WinstonSmith,我在COM选项卡和Adobe文件夹中都没有找到这两个DLL文件,你知道它们在哪里吗?有什么建议吗? - Ahmad Hajjar

11
您可以使用WebBrowser控件,如果机器上已安装PDF阅读器,则可以让IE为您加载。但是,上次我尝试时,我必须先将PDF文件写入磁盘,以便可以将WebBrowser控件指向它。

3
如果你的用户更喜欢使用Firefox,那就不太好了;-) - Winston Smith
1
@Winston,由于WebBrowser控件没有IE工具栏,如果您禁用了右键菜单,大多数用户将无法确定它是IE。 - Ian Ringrose
这听起来很简单......那你是怎么做到的呢?我认为要实现这个,我需要将文件与应用程序捆绑在一起。然后在“按钮点击”事件中,应用程序(.exe)应该检查>>> if (File.Exists("user manual.pdf")) // then display else //extract the pdf to the same directory. //and then display it in the browser. 我知道关于“添加现有项作为引用”,但如何通过C#代码将其复制到输出目录呢? - gsvirdi

9
如果您想在应用程序内显示PDF文档,WebBrowser控件可能比Adobe Reader控件更可取,因为它会在PDF阅读器中或IE默认的pdf打开方式中非常流畅地打开文件。您只需将WebBrowser控件添加到现有或新的窗体中并浏览到PDF文件即可。
永远不要假设用户安装了Adobe或其他任何第三方控件或库,始终将它们与您的可执行文件一起打包,否则可能会出现问题。
明显地,Adobe Reader控件无法像内置的Windows组件那样与.NET集成。通常情况下,我总是倾向于使用内置的.NET控件而不是第三方供应商的控件。关于将文件嵌入实际的可执行文件中,这不会发生,直到Microsoft决定可以将任意旧的PDF文件加入到CLS中,并编译为MSIL。在.NET中开发任何应用程序时,您拥有的是可以编译为中间MSIL的代码,CLR在运行时将其翻译为本地代码并在操作系统中执行。
WebBrowser1.Navigate("SomePDF.pdf");

非常感谢您的回复。 - gsvirdi

9

我会把它放在我的程序文件夹中,在我的开始菜单文件夹中添加一个链接以允许直接访问(而无需启动我的工具),仅在某个点击事件上使用System.Diagnostics.Process.Start(@".\Manual.pdf");

更新

好的,现在我们来到一个全新的问题:如何将文件嵌入到我的应用程序并启动它?

对于这个问题,你已经在这里找到了几个答案,但这是简短的版本:

  1. 右键单击项目,选择添加 - 现有项目
  2. 选择您的文件(不要双击它
    • 点击“添加”按钮旁边的小箭头,选择添加为链接
  3. 双击属性 - Resources.resx
  4. 点击“添加资源”旁边的小箭头,选择添加现有文件
  5. 在打开的对话框中再次选择相同的文件
  6. 现在,您可以从Properties.Resources.NameOfResource中访问byte[]格式的文件

通过这些步骤,您可以引用您的文件,无论它存在于您的结构中的任何位置。如果您希望将pdf文件的副本放入项目的子文件夹Resources中,只需跳过上面列表中的第一和第二点。

要现在打开您的pdf文件,您需要将byte[]写入磁盘(可能使用Path.GetTempFileName()),然后使用Adobe Reader启动它。(不要忘记在使用后删除文件)


我同意Process方法完美地工作。Process.Start("C:\Documents and Settings\gsv\Desktop\manual.pdf");但正如我所说...在这种情况下,我需要提供一个单独的pdf文件与这个calculator.exe。是否可能将文件嵌入到exe本身中? - gsvirdi

8

在Google Code上有一个C# PDF查看器项目。http://code.google.com/p/pdfviewer-win32/该项目包含了一个查看器和一个库,它们使用mupdf和xpdf来呈现PDF文档,可以在WinForms程序中使用。我目前正在开发一个用户控件库,供人们使用并将其放入他们的程序中以实现PDF查看功能。它运行得非常好。


嵌入到我的自己的WinForm 中并不像看起来那么容易,但是还是可以做到的 :) 谢谢! - Ch'nycos

6

如果用户在他们的计算机上安装了Adobe Reader(或任何其他PDF阅读器),则可以使用:

System.Diagnostics.Process.Start(
       "My-PDF-file.pdf");

希望这可以帮到您。

注意:如果用户没有安装任何PDF阅读器应用程序,显然这将失败。


我同意Process方法完美地工作。 Process.Start("C:\Documents and Settings\gsv\Desktop\manual.pdf"); 但正如我所说...在这种情况下,我将需要提供一个单独的pdf文件与这个calculator.exe一起使用!!!有可能将文件嵌入到exe本身中吗?然后在“Button_Click”事件上,应用程序可以将pdf提取到相同的文件夹中,然后显示它?如何将文件提取到同一用户目录中? - gsvirdi
1
啊,是的 - 这是可能的。但由于我无法使其正常工作,我不建议这样做。 - Tommy

5
我建议将您的pdf文件转换为Microsoft帮助文件,这样您就不需要安装Adobe Reader(它很容易出错,而且存在太多安全问题)。您不能期望用户拥有这个。
回复发起者的评论:
是的,您需要将帮助文件创建为HTML文档,而不是pdf。没有简单的方法可以将pdf转换为HTML。

嗯......我同意你的观点,不能指望用户安装PDF阅读器,但是因为我只是一个学习者,所以这个简单的“计算器实用程序”不会成为广泛传播(流行)的应用程序。我只是在学习编码。我刚刚安装了Microsoft帮助文件创建器,但我无法轻松使用它。它要求HTML文件(输入)。我认为我需要仔细查看帮助文件创建器中的所有内容。 - gsvirdi

4
将文本翻译成中文: 取出嵌入的文件应该不是问题。这不取决于它是 .pdf 格式,你可以寻找另外的解决方案。
对于显示,除非你知道已安装 Acrobat 或类似程序(现在甚至 Edge 也可以打开这些文件),或者希望在 WinForms 应用程序中嵌入显示文件,那么就有一个 Codeproject 解决方案。

https://www.codeproject.com/Articles/37458/PDF-Viewer-Control-Without-Acrobat-Reader-Installe

使用VB编写,依赖许多(部分为商业库,如果您的解决方案是商业的)库。 PdfiumViewer

https://github.com/pvginkel/PdfiumViewer

是很棒的,而且可以通过NuGet获取。

The PdfiumViewer library primarily consists out of three components:
•The  PdfViewer  control. This control provides a host for the  PdfRenderer  control and has a default toolbar with limited functionality;
•The  PdfRenderer  control. This control implements the raw PDF renderer. This control displays a PDF document, provides zooming and scrolling functionality and exposes methods to perform more advanced actions;
•The  PdfDocument  class provides access to the PDF document and wraps the Pdfium library.

这是一个全方位的显示解决方案,采用更友好的Apache 2.0许可证。
编辑,增加示例代码,为了您的方便 :) 我包含了以下内容。
data = File.ReadAllBytes(@"C:\temp\abc.pdf");
PdfiumViewer.PdfDocument doc;
using (Stream stream = new MemoryStream(data))
{
    doc = PdfiumViewer.PdfDocument.Load(stream);
    var viewer = new PdfiumViewer.PdfViewer();
    viewer.Document = doc;
    var form = new System.Windows.Forms.Form();
    form.Size = new Size(600, 800);
    viewer.Dock = System.Windows.Forms.DockStyle.Fill;
    form.Controls.Add(viewer);
    form.ShowDialog();
}

这将动态生成一个表单,当然您也可以使用设计工具。

3

你可以将Adobe Reader作为一个ActiveX组件嵌入到表单中。但这意味着你必须确保客户端机器上已安装了Reader才能正常工作。

如果不一定需要严格嵌入,你可以直接启动PDF文件,让用户使用自己的阅读器打开它。


即使未安装Adobe Reader,我认为我们可以通过Try {} catch {}语句来处理此情况,并在读取器不存在时弹出消息。不用担心。我唯一想知道的是将文件“嵌入”到exe中并在不提供它作为单独文件放在用户硬盘上的情况下显示它的使用。 - gsvirdi

2

如何使用相对路径打开PDF文件

在本例中,创建的应用程序必须在多台计算机上运行。要引用不在网络中但在程序文件夹本身中的文件,请使用以下代码片段:

首先包含以下库:

using System.IO;

然后使用一个按钮图片框或者其它控件来创建一个Click事件,并使用下面的代码片段:

    private void pictureBox2_Click(object sender, EventArgs e)
    {
        //get current folderpath of the .exe
        string ProgramPath = AppDomain.CurrentDomain.BaseDirectory;
        //jump back relative to the .exe-Path to the Resources Path
        string FileName = string.Format("{0}Resources\\Master_Thesis_Expose.pdf", Path.GetFullPath(Path.Combine(ProgramPath, @"..\..\")));

        //Open PDF
        System.Diagnostics.Process.Start(@"" + FileName + "");

    }

|点赞|


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接