目录

打印

本指南介绍如何使用打印 API。

概述 

可以通过以下方式打印网页:

  1. window.print() JavaScript 函数。它可以从网页上的 JavaScript 代码中调用。
  2. DotNetBrowser API 的 IFrame.Print() 方法。它请求打印 frame。如果您需要打印整个页面,请在主框架中调用 Print()方法。请参阅以下代码示例:
C#
VB
browser.MainFrame?.Print();
If browser.MainFrame IsNot Nothing Then
    browser.MainFrame.Print()
End If

网页不会立即打印。RequestPrintHandler 将被调用以告知引擎如何处理打印请求。默认情况下,所有打印请求都会被取消。

配置打印 

有三种处理程序可用于配置打印:

  • RequestPrintHandler 用于确定如何处理打印请求。此处理程序可用于完全取消打印、显示打印预览或告诉浏览器以编程方式打印内容。
  • PrintHtmlContentHandler 用于配置如何以编程方式打印 HTML 内容。
  • PrintPdfContentHandler 用于配置如何以编程方式打印 PDF 内容。

取消打印 

要取消任何打印请求或完全禁用打印,请按以下代码示例所示注册 RequestPrintHandler

C#
VB
browser.RequestPrintHandler =
    new Handler<RequestPrintParameters, RequestPrintResponse>(p =>
    {
        return RequestPrintResponse.Cancel();
    });
browser.RequestPrintHandler = 
    New Handler(Of RequestPrintParameters, RequestPrintResponse)(Function(p)
        Return RequestPrintResponse.Cancel()
    End Function)

打印预览 

要允许打印请求并显示打印预览对话框,请使用以下代码示例:

C#
VB
browser.RequestPrintHandler =
    new Handler<RequestPrintParameters, RequestPrintResponse>(p =>
    {
        return RequestPrintResponse.ShowPrintPreview();
    });
browser.RequestPrintHandler = 
    New Handler(Of RequestPrintParameters, RequestPrintResponse)(Function(p)
        Return RequestPrintResponse.ShowPrintPreview()
    End Function)

打印预览中,您可以选择首选的打印选项:

打印预览

还可以使用 Print Preview 对话框将内容打印为 PDF。 在对话框中,您需要单击 Destination 部分中的 Change… 按钮,然后选择 Save as PDF。 按下 Save 按钮后,网页将被保存。

打印预览事件 

要在打印预览对话框打开或关闭时获得通知,请使用 PrintPreviewOpened and PrintPreviewClosed 事件:

C#
VB
Browser.PrintPreviewOpened += (sender, args) =>
{
    // 打印预览对话框已打开。
};

Browser.PrintPreviewClosed += (sender, args) =>
{
    // 打印预览对话框已关闭
};
AddHandler Browser.PrintPreviewOpened, Sub(sender, args)
    ' 打印预览对话框已打开。
End Sub

AddHandler Browser.PrintPreviewClosed, Sub(sender, args)
    ' 打印预览对话框已关闭。
End Sub

以编程方式打印内容 

要以编程方式打印内容,并在不显示任何对话框的情况下配置打印设置,需要使用多个处理程序。

首先,您需要注册 RequestPrintHandler,如以下代码示例所示:

C#
VB
browser.RequestPrintHandler =
    new Handler<RequestPrintParameters, RequestPrintResponse>(p =>
    {
        return RequestPrintResponse.Print();
    });
browser.RequestPrintHandler = 
    New Handler(Of RequestPrintParameters, RequestPrintResponse)(Function(p)
        Return RequestPrintResponse.Print()
    End Function)

当 Chromium 被告知以编程方式执行打印时,它将使用 PrintHtmlContentHandlerPrintPdfContentHandler 来确定应如何打印内容。

将被调用的处理程序取决于当前加载到浏览器中的内容 - 对于常规网页将使用 PrintHtmlContentHandler,而对于打印 PDF 文件将使用 PrintPdfContentHandler

选择打印机 

PrintHtmlContentHandlerPrintPdfContentHandler 的参数包含 Printers 属性 - 一组当前可用于打印的打印机。 例如,以下是如何在 PrintHtmlContentHandler 实现中获取您所需的打印机:

C#
VB
browser.PrintHtmlContentHandler 
    = new Handler<PrintHtmlContentParameters, PrintHtmlContentResponse>(p =>
    {
        // 获取可用打印机的集合。
        var printers = p.Printers;
        // 获取环境中的默认打印机。
        var defaultPrinter = printers.Default;
    
        // 获取内置 PDF 打印机。
        var pdfPrinter = printers.Pdf;
    
        // 通过设备名称查找打印机。
        var xpsPrinter = printers.FirstOrDefault(pr => pr.DeviceName.Contains("XPS"));
    
        // 使用特定打印机打印内容。
        return PrintHtmlContentResponse.Print(xpsPrinter);
    });
browser.PrintHtmlContentHandler = 
    New Handler(Of PrintHtmlContentParameters, PrintHtmlContentResponse)(Function(p)
        ' 获取可用打印机的集合。
        Dim printers = p.Printers

        ' 获取环境中的默认打印机。
        Dim defaultPrinter = printers.Default

        ' 获取内置 PDF 打印机。
        Dim pdfPrinter = printers.Pdf

        ' 通过设备名称查找打印机。
        Dim xpsPrinter = 
            printers.FirstOrDefault(Function(pr) pr.DeviceName.Contains("XPS"))

        ' 使用特定打印机打印内容。
        Return PrintHtmlContentResponse.Print(xpsPrinter)
    End Function)

处理程序中的 Print() 响应用于指定使用哪台打印机进行打印。

每台打印机都有自己的功能,包括特定打印机支持的纸张大小、颜色模式和双面模式。例如,以下是检查打印机是否支持 A4 的方法:

C#
VB
bool a4Supported = xpsPrinter.Capabilities.PaperSizes.Contains(PaperSize.IsoA4);
Dim a4Supported As Boolean = xpsPrinter.Capabilities.PaperSizes.Contains(PaperSize.IsoA4)

配置打印设置 

每台打印机都包含一个表示当前打印操作的 PrintJob。特定打印操作的打印设置可作为打印作业的一部分使用。下面介绍如何自定义和应用打印设置:

C#
VB
pdfPrinter.PrintJob.Settings.Apply((s) =>
{
    s.Orientation = Orientation.Landscape;
    s.PageRanges = new[] { new PageRange(2, 5) };
    s.PaperSize = PaperSize.IsoA4;
    s.PdfFilePath = pdfFilePath;
    // 其他设置。
});
pdfPrinter.PrintJob.Settings.Apply(Sub(s)
    s.Orientation = Orientation.Landscape
    s.PageRanges = { New PageRange(2, 5) }
    s.PaperSize = PaperSize.IsoA4
    s.PdfFilePath = pdfFilePath
    ' 其他设置。
End Sub)

在应用打印设置期间,进行页面布局,并重新生成稍后将发送到打印机的打印预览文档。因此,Apply() 调用可能需要一些时间来执行。

如果处理程序实现应用的设置与打印机功能不匹配,则会抛出异常。

在使用内置 PDF 打印机打印时需要通过 PdfFilePath 指定完全限定的路径。如果未设置路径,则打印操作将被取消。

PageCountUpdated 事件 

页面布局完成后,将触发 PageCountUpdated 事件,从而提供生成的页数。以下是如何为特定打印机订阅此事件的方法:

C#
VB
printer.PrintJob.PageCountUpdated += (s, e) => 
{
    int newPageCount = e.PageCount;
};
AddHandler printer.PrintJob.PageCountUpdated, Sub(s, e)
    Dim newPageCount As Integer = e.PageCount
End Sub

PrintCompleted 事件 

通过 PrintHtmlContentResponse.Print()PrintPdfContentResponse.Print() 选择要打印的打印机后,一旦打印操作完成,就会为其打印作业触发 PrintCompleted 事件。以下是订阅此事件的方法:

C#
VB
printer.PrintJob.PrintCompleted += (s, e) => 
{
    var printJob = e.PrintJob;
    bool completed = e.IsCompletedSuccessfully;
};
AddHandler printer.PrintJob.PrintCompleted, Sub(s, e)
    Dim printJob = e.PrintJob
    Dim completed As Boolean = e.IsCompletedSuccessfully
End Sub

以编程方式将网页打印为 PDF 

以下代码片段演示了以编程方式将网页打印为 PDF 的一般方法:

C#
VB

public static async Task Main()
{
    var engineOptions = new EngineOptions.Builder
    {
        RenderingMode = RenderingMode.OffScreen,
        LicenseKey = "your license key"
    }.Build();

    using var engine = EngineFactory.Create(engineOptions);
    using var browser = engine.CreateBrowser();

    await browser.Navigation.LoadUrl(Path.GetFullPath("template.html"));
...

    var whenPrintCompleted = ConfigurePrinting(browser);
    browser.MainFrame.Print();
    var resultPath = await whenPrintCompleted.Task;
    Console.WriteLine($"PDF is generated: {resultPath}");
    Console.WriteLine("Press any key to terminate...");
    Console.ReadKey();
}

private static TaskCompletionSource<string> ConfigurePrinting(IBrowser browser)
{
    // 让浏览器自动打印,而不是显示打印预览。
    browser.RequestPrintHandler = new Handler<RequestPrintParameters, RequestPrintResponse>(
       p => RequestPrintResponse.Print()
    );

    TaskCompletionSource<string> whenCompleted = new();
    // 配置浏览器打印 HTML 页面的方式。
    browser.PrintHtmlContentHandler = new Handler<PrintHtmlContentParameters, PrintHtmlContentResponse>(
        parameters =>
        {
            // 使用 PDF 打印机。
            var printer = parameters.Printers.Pdf;
            var job = printer.PrintJob;

            // 为 PDF 文件生成一个随机名称。
            var guid = Guid.NewGuid();
            var path = Path.GetFullPath($"{guid}.pdf");
            job.Settings.PdfFilePath = path;

            // 移除页面两侧的空白区域。
            job.Settings.PageMargins = PageMargins.None;
            // 移除浏览器默认的页眉和页脚。
            job.Settings.PrintingHeaderFooterEnabled = false;
            job.PrintCompleted += (_, e) =>
            {
                if (e.IsCompletedSuccessfully)
                {
                    whenCompleted.SetResult(path);
                }
                else
                {
                    whenCompleted.SetException(
                        new InvalidOperationException("Printing to PDF has failed."));
                }
            };

            // 使用 PDF 打印机继续打印。
            return PrintHtmlContentResponse.Print(printer);
        });
    return whenCompleted;
}

Public Shared Sub Main()
    Dim engineOptions As New EngineOptions.Builder With {
            .RenderingMode = RenderingMode.OffScreen,
            .LicenseKey = "your license key"
            }

    Using engine = EngineFactory.Create(engineOptions.Build())
        Using browser = engine.CreateBrowser()

            browser.Navigation.LoadUrl(Path.GetFullPath("template.html")).Wait()
...

            Dim whenPrintCompleted = ConfigurePrinting(browser)
            browser.MainFrame.Print()
            Dim resultPath = whenPrintCompleted.Task.Result
            Console.WriteLine($"PDF is generated: {resultPath}")
            Console.WriteLine("Press any key to terminate...")
            Console.ReadKey()
        End Using
    End Using
End Sub

Private Shared Function ConfigurePrinting(browser As IBrowser) _
    As TaskCompletionSource(Of String)
    ' 让浏览器自动打印,而不是显示打印预览。
    browser.RequestPrintHandler =
        New Handler(Of RequestPrintParameters, RequestPrintResponse)(
            Function(p) RequestPrintResponse.Print())

    Dim whenCompleted As New TaskCompletionSource(Of String)()
    ' 配置浏览器打印 HTML 页面的方式。
    browser.PrintHtmlContentHandler =
        New Handler(Of PrintHtmlContentParameters, PrintHtmlContentResponse)(
            Function(parameters)
                ' 使用 PDF 打印机。
                Dim printer = parameters.Printers.Pdf
                Dim job = printer.PrintJob

                ' 为 PDF 文件生成一个随机名称。
                Dim guid As Guid = Guid.NewGuid()
                Dim path As String = IO.Path.GetFullPath($"{guid}.pdf")
                job.Settings.PdfFilePath = path

                ' 移除页面两侧的空白区域。
                job.Settings.PageMargins = PageMargins.None
                ' 移除浏览器默认的页眉和页脚。
                job.Settings.PrintingHeaderFooterEnabled = False
                AddHandler job.PrintCompleted,
                    Sub(o, e)
                        If e.IsCompletedSuccessfully Then
                            whenCompleted.SetResult(path)
                        Else
                            whenCompleted.SetException(
                                New InvalidOperationException("Printing to PDF has failed."))
                        End If
                    End Sub

                ' 使用 PDF 打印机继续打印。
                Return PrintHtmlContentResponse.Print(printer)
            End Function)
    Return whenCompleted
End Function