【问题标题】:Printing PDF documents from Windows 8 App从 Windows 8 应用程序打印 PDF 文档
【发布时间】:2013-07-06 04:44:09
【问题描述】:

我正在尝试将 PDF 文件从我的 Windows 8 应用程序打印到连接的打印机。我正在使用 WinJS 进行编码,并且知道我必须创建一个打印任务才能从 Windows 8 应用程序启动打印。因此,在查看文档后,我有以下代码:

 onPrintTaskRequested: function (e) {
        var self = Application.navigator.pageControl,
            printTask = e.request.createPrintTask("Print Test Doc", function (args) {
                args.setSource(MSApp.getHtmlPrintDocumentSource(document));

                // Register the handler for print task completion event
                printTask.oncompleted = self.onPrintTaskCompleted;
            });
    }

According to the documentation, the MSApp.getHhtmlPrintDocumentSource method 接受一组特定的数据类型。如文档中所述:

这可以是根文档、IFrame 中的文档、文档 片段或 SVG 文档。请注意 htmlDoc 必须是文档, 不是元素。

显然我不能简单地将 getHtmlPrintDocumentSource 的参数设置为 .PDF 或 .PNG 二进制文件。所以,我很好奇:WinJS 库是否提供了一种打印方法,以便我可以将 PDF 文件打印到连接的打印机?任何人都可以提供一些实施技巧吗?

【问题讨论】:

    标签: pdf windows-8 winjs windows-8.1


    【解决方案1】:

    经过反复试验,我终于能够实现从 Windows 8 应用程序打印表示 PDF 二进制文件的 Base64 流。

    我正在用 HTML / CSS / WinJS 编写应用程序。基本上这里是对它是如何完成的简要说明:

    default.html 文件中创建一个新的<canvas> 元素。将它放在元素的 open 标记之后。像这样:

    <body role="application" class="app">
        <canvas id="pdf-render-output"></canvas>
        . 
        .
        .
    </body>
    

    然后在default.css 文件中,设置一些规则以及打印媒体查询。像这样:

    body > canvas {
        display: none;
    }
    
    .
    . /* all your app's default css styles */
    .
    
    @media print {
    
        body > * {
           display:none;
           max-width: 100%;
        }
    
        html {
           max-width: 100%;
           border-top-color: none;
           border-top: 0;
        }
    
        body > canvas {
            display: block;
            border: none;
            max-width: 100%;
            width: 100%;
            height: 100%;
            position: relative;
        }
    }
    

    值得注意的是在 CSS 中声明规则的顺序。在声明默认 CSS 规则之后放置打印媒体查询很重要。

    设置完成后,javascript 会处理其余部分。基本思想是将 PDF.js 输出渲染到 DOM 中的“隐藏”画布。当文档对象被发送到打印时,将查询 CSS 打印媒体声明,以便隐藏 &lt;body&gt; 下的所有元素,除了 canvas 元素。这是仅打印 PDF 第一页的 javascript:

     //Define a container for the Base64 data we'll use with PDF.js
     var pdfPrintData = {};
    
     //Function to render PDF to canvas and begin printing contract with Windows 8 OS
     printPrescription: function () {
    
            var self = Application.navigator.pageControl,
                printManager = Windows.Graphics.Printing.PrintManager.getForCurrentView();
    
            self.getPDF().done(function () {
                var pdfStream = pdfPrintData.base64,
                    pdfFile = convertDataURIToBinary(pdfStream);
    
                PDFJS.disableWorker = true;
                PDFJS.getDocument(pdfFile).then(function (pdf) {
    
                    var numPages = pdf.numPages,
                        renderCanvas = $('#pdf-render-output')[0];
    
                    //setup canvas
                    renderCanvas.height = pdf.getPage(1).data.getViewport(1).height;
                    renderCanvas.width = pdf.getPage(1).data.getViewport(1).width;
    
                    //Setup a render context for pdf.js to out a pdf file to the canvas.
                    var renderContext = {
                            canvasContext: renderCanvas.getContext('2d'),
                            viewport: pdf.getPage(1).data.getViewport(1)
                        };
    
                    //Bring up Windows 8 OS print after PDF is rendered to render context.
                    pdf.getPage(1).data.render(renderContext).then(function () {
                        printManager.onprinttaskrequested = self.onPrintTaskRequested;
                        Windows.Graphics.Printing.PrintManager.showPrintUIAsync();
                    });
    
                })
    
            });
    
    },
    onPrintTaskRequested: function (e) {
            var self = Application.navigator.pageControl,
                printTask = e.request.createPrintTask("Print Prescription", function (args) {
                    args.setSource(MSApp.getHtmlPrintDocumentSource(document));
                    printTask.oncompleted = self.onPrintTaskCompleted;
                });
    
    },
    onPrintTaskCompleted: function (e) {
            if (e.completion === Windows.Graphics.Printing.PrintTaskCompletion.failed) {
                console.log("[ERX]  :   Failed to print!");
            }
        }
    

    self.getPDF 方法只是一个检索 Base64 数据流的函数,该数据流在全局 pdfPrintData 对象的 .base64 属性上设置。出于某种原因,我无法使用 pdf.js 将 pdf 呈现到动态创建的文档中的动态创建画布上。我必须将 pdf.js 渲染方法的输出渲染到 DOM 中已经存在的画布上。

    【讨论】:

      【解决方案2】:

      据我所知,MSApp.getHtmlPrintDocumentSource(document) 旨在用于 HTML 文档对象,仅此而已。

      如果您可以使用 Windows 8.1,您可以尝试通过使用 PdfPage.RenderToStreamAsync 将每个页面导出为光栅图像来从 PDF 文件中组合一个新的 HTML 文档。有一个sample project in MSDN 用于使用此新 API 的 PDF 查看器,您可以在其中学习如何使用此方法。

      如果您不能假设 Windows 8.1 并且您需要支持普通的 Windows 8 或 Windows RT (ARM),您可能需要使用第三方库来创建光栅图像或一起进行打印。

      Amyuni PDF Creator for WinRT 例如can do the printing for you免责声明:我目前在开发库的公司工作

      【讨论】:

      • 感谢您的提示。我在谷歌搜索中找到了 Amyuni PDF Creator。是否有使用该软件的免费试用版?此外,您提到“您可能需要使用第三方库来创建光栅图像”。你的意思是像 PDF.js 这样的东西吗?
      • @ariestav 提供 30 天免费试用和免费支持。关于“第三方库”我的意思是您将无法单独使用 WinRT API 进行打印,所以我实际上是指任何第三方库,无论是商业的还是开源的。当我在 SO 中回答问题时,我会尽力做到公平。
      • 关于PDF.js,我或多或少知道它是做什么的,但我没有用过,所以不知道它是否可以用于打印或光栅化。
      • Amyuni 为不同的架构有单独的文件。我的构建在 VS2012 的配置管理器中设置为“AnyCPU”。考虑到我的构建过程,我将如何包含它?
      • @yms pdf.js 可能无法正常工作。我之前曾尝试过此方法来渲染 pdf,但遇到了未加载字体的问题。它尝试插入不适用于 winjs 的 &lt;script&gt; 标签。如果您尝试使用 pdf.js - 将很高兴分享您在 SO 上的发现。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-22
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多