使用Windows 8应用程序打印PDF文档

3

我正在尝试从我的Windows 8应用程序中将PDF文件打印到已连接的打印机。 我正在使用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;
            });
    }

根据文档,MSApp.getHtmlPrintDocumentSource方法接受一组特定的数据类型。如文档所述:

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

显然,我不能简单地将getHtmlPrintDocumentSource的参数设置为.PDF或.PNG二进制文件。那么,WinJS库是否提供了打印方法,以便我可以将PDF文件打印到连接的打印机上?有人能提供一些实现的技巧吗?

2个回答

3

经过反复尝试,我最终成功实现了在Windows 8应用程序中打印代表PDF二进制码的Base64流。我使用HTML/CSS/WinJS编写这个应用程序。下面是简要说明:

default.html 文件中创建一个新的 <canvas> 元素。把它放在 <body> 元素的开标签之后,像这样:

<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打印媒体声明,以便在``下的所有元素都被隐藏,除了画布元素。以下是仅打印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中已经存在的画布中。


0
据我所知,MSApp.getHtmlPrintDocumentSource(document)是用来与HTML文档对象一起使用的,其他情况不适用。
如果你可以假设Windows 8.1,你可以尝试通过使用PdfPage.RenderToStreamAsync将每一页导出为光栅图像,从而从PDF文件中组装一个新的HTML文档。在MSDN上有一个示例项目,是一个使用这个新API的PDF阅读器,你可以学习如何使用这个方法。
如果你不能假设Windows 8.1,并且需要支持纯Windows 8或Windows RT(ARM),你可能需要使用第三方库来创建光栅图像或进行打印操作。

Amyuni PDF Creator for WinRT 例如 可以为您打印免责声明:我目前在开发该库的公司工作


@ariestav 有30天的免费试用期和免费支持。 关于“第三方库”,我的意思是您将无法仅使用WinRT API打印,因此我实际上指的是任何第三方库,商业或开源。 当我在SO中回答问题时,我会尽力做到公平。 - yms
关于PDF.js,我大致知道它的功能,但我从未使用过,所以不清楚它是否可用于打印或光栅化。 - yms
@yms pdf.js可能不会像现在这样工作。我之前尝试过使用它来呈现pdf,但遇到了字体无法加载的问题。它会尝试插入在winjs中无法使用的<script>标签。如果您尝试使用pdf.js,分享您在SO上的发现将是很好的。 - Sushil
我知道的另一个选项是只保留一个项目,但它需要在文本编辑器中手动编辑项目文件。有关更多详细信息,请参见此问题:在Visual Studio中构建时有条件地使用32/64位引用 - yms
我尝试通过javascript创建一个空白的HTML文档,然后将PDF渲染到该HTML文档内的canvas容器中,然后将其作为getHtmlPrintDocumentSource方法的源参数使用。我正在使用PDF.js的render方法进行渲染,但它不起作用。有人知道pdf.js是否需要在应用程序中显示可视化的dom元素吗? - ariestav
显示剩余3条评论

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