[转载]也谈WEB打印(三):抛开IE,实现我们自己的打印模板 – 悼念死难同胞 – 博客园.
在上一篇文章《也谈WEB打印(二):简单的分析一下IE的打印原理并实现简单的打印和预览》中,我们剖析了IE的打印原理,并学会了如何调用IE的打印功能,在这篇文章中, 我们实现写自己的打印模板。
从IE5.5开始,你可以定制WebBrowser控件和IE如何打印 和预览文档。打印和预览的机制有打印模板控制,这是一些HTML文件,他 们可以由开发人员可以使用由打印模板行为暴露的对象模型来生成。MSDN上 说,如果打印模板是HTML文件的时候,定制的打印模板只能由C++语言从发布或拦截IDM_PRINT/IDM_PRINTPREVIEW命令的程序或控件中使用(打印模板的路径由IOleCommandTarget::Exec的pvaIn参数 指定)。但实际上,Delphi、C#语言也是可以的,我已经做过测试了。至于VB可不可以,我没有试验过,不敢肯定。缺省情况下,IE使用自己的打印模板,就是说,如果IOleCommandTarget::Exec的pvaIn参数 为NULL的时候,IE就会调用自己的打印模板进行打印。
我们可以用打印模板做一 些什么事情呢?
1、 控制打印和预览时页面的版面,打印以及预览的内容;
2、 控制打印任务如何被处理,例如以何种顺序打印页面;
3、 控制打印预览窗口的外观,在打印用户界面上放置定制的控 件。
有了打印模板,我们可以加入一些非常酷的功能,例如加入公司的Logo,法律声明,广告;定制页眉页脚的位置和样式;安排打印计划进行定时打印,如此等等。
一个打印模板其实就是一个标准的HTML文件,与其他的HTML文件不同的是,他有4个声明模板的基本元素:LAYOUTRECT,DEVICERECT,TEMPLATEPRINTER和HEADERFOOTER。下面讲解一下这4个 模板元素的作用:
LAYOUTRECT:为打印和预览模板中的文档内容生成容器.
DEVICERECT:为LAYOUTRECT元素和打印模板中的其他内容提供一个容器。位于DEVICERECT之外的内容都不会被打印。
TEMPLATEPRINTER:提供一个打印模板以获取页 面设置和打印设置,并且可以控制从打印模板初始化出来的打印作业。
HEADERFOOTER:提供一个工具以便打印模板可以把 页眉和页脚的格式化字符串转换为格式化的HTML文本。
下面,我们先写一个最小的具有预览但是不能打印的模板(模板代码来自于MSDN,我只做了一点点说明):
2这个模板展示了一个最小的模板,他支持打印预览,但不能打印。它只包含2个DEVICERECT元素,每个元素有包含一个 LAYOUTRECT元素。在预览的时候,他并没有完全显示原文档,LAYOUTRECT元素的样式表定义了必须的宽度和高度属性。其他属性则不是必须 的。LAYOUTRECT和DEVICERECT元素包含颜色和边框属性(分别是白色和黄色)使得容易辨认他们边界。DEVICERECT元素尺寸是 8.5 x 11英寸,这并不是IE“页面设置”里的实际值。
3–>
4<HTML XMLNS:IE>
5<HEAD>
6<?IMPORT NAMESPACE=”IE” IMPLEMENTATION=”#default”>
7<STYLE TYPE=”text/css”>
8.lorstyle
9{
10 width:5.5in;
11 height:8in;
12 margin:1in;
13 background:white;
14 border:1 dashed gray;
15}
16.pagestyle
17{
18 width:8.5in;
19 height:11in;
20 background:#FFFF99;
21border-left:1 solid black;
22border-top:1 solid black;
23border-right:4 solid black;
24border-bottom:4 solid black;
25 margin:10px;
26}
27</STYLE>
28</HEAD>
29<BODY>
30<IE:DEVICERECT ID=”page1″ CLASS=”pagestyle” MEDIA=”print”>
31 <IE:LAYOUTRECT ID=”layoutrect1″ CONTENTSRC=”document” CLASS=”lorstyle” NEXTRECT=”layoutrect2″/>
32</IE:DEVICERECT>
33<IE:DEVICERECT ID=”page2″ CLASS=”pagestyle” MEDIA=”print”>
34 <IE:LAYOUTRECT ID=”layoutrect2″ CLASS=”lorstyle”/>
35</IE:DEVICERECT>
36</BODY>
37</HTML>
38
把上面的代码保存,然户运行我在上一篇文章中所是的代码,才Document Address框中输入www.cnblogs.com,然后单击Preview,其效果如下图:
上面的例子还很不完善,打印预览只会显示2个页面,不管你有多少个页面,他也只会显示前2页。而且,页面也是固定了的,不管你实际页面的大小是多少,或者你在IE的“页面设置”里设置的大小是多少,他都不会调整,只会按8 x 11.5英寸的页面大小显示。另外,还不支持打印,即使你按下“Print”按钮,他也不会打印,而只是执行预览的动作。
我们注意到,每个标签都以一个命名空间声明开始(IE:),一个打印模板必须在第一行一如下的形式声明他的命名空间:
<HTML XMLNS:IE>
<HEAD>
<?IMPORT NAMESPACE=“IE” IMPLEMENTATION=“#default”>
在这里,HTML标签的XMLNS属 性为模板声明了一个叫做IE的命名空间,你也可以把“IE”替换成任何你喜欢的名字,当然,在后面的所有命名空间也必须相应的改成你喜欢的那个名字。IMPORT标签然后导入了Internet Explorer对IE命名空间的实 现,使得打印模板上的元素的行为对模板有效。
值得注意的是,LAYOUTRECT没有结束标签,在他的结束括号之前必须放一个反斜线,这类似于XML文档中没有结束标签的元素的语法一样。LAYOUTRECT中不能包含任何HTML,例如,如下的语句不会有效:
layoutrect1.innerHTML = “<B>Hi there!</B>”;
现在我们来看看属性。ID属性和CLASS属 性是大家所熟知的,值得注意的是,CLASS指定的样式中必须包含有Width和Height。 在本例中,这2个值都不符合实际。当然,我们可以从TemplatePrinter 行为中取得正确的值。不过我们先不讨论这个。另外一个属性就是MEDIEA,大家都知道他的含义,不过,在这里,我们必须指定MEDIA属性的值是“print”,这是强制性的。另外就是CONTENTSRC,如果他的值 是“document”,则表示需要打印或预览的是IE当 前显示的页面,如果不想打印这个文档,那么,可以指定其他的URL,例如http://yahong111.cnblogs.com,这样的话,就会打印或预览http://yahong111.cnblogs.com的内容,而不是当前页面。最后一个是NEXTRECT,他表示如果当前页满了时候,下一个LAYOUTRECT的名字,在本例中,“layoutrect1”的NEXTRECT就 是“layoutrect2”,如果当前页是最后一页,那么就不要指定NEXTRECT的值。被打印或预览的文档有多少页,我们就必须有多少个LAYOUTRECT。在本例中,我们只指定了2个LAYOUTRECT,所以,只会显示2页,而且,即使被打印文档只有一页,他也会显示2页。
下面是DEVICERECT和LAYOUTRECT的图解。
那么,我们如何知道当前被打印或预览的文档需要多少个LAYOUTRECT呢?我们如何正确设置每个DEVICERECT和LAYOUTRECT的Width和Height呢?这是我们下一篇文章所讨论的内容。
参考文档:《Beyond Print Preview: Print Customization for Internet Explorer 5.5》
另,附上增强的DLPrinter.CAB组件,现在组件可以设置页眉、页脚和纸张的走向了(横向/纵向)。因不支持.cab文件上传,所以把DLPrinter.CAB,改成了DLPrinter.cab.rar,请大家把文件名改过来就可以用了。
使用方法如下:
<OBJECT ID=”DLPrinter” CLASSID=”CLSID:5C230622-45E5-4e3c-893C-3BFDDC4DB5E4″ height=”0″ width=”0″ codebase=”DLPrinter.cab” ></OBJECT>
<script>
DLPrinter.MarginLeft=20;
DLPrinter.PageHeader=”这是测试的页眉“;
DLPrinter.PageFooter=”这是测试的页脚“;
DLPrinter.IsLandScape=1; //把页面设置为横向
//DLPrinter.ContentURL=http://www.cnblogs.com/Yahong111/archive/2007/09/19/898326.html;
</script>
<input type=”button” id=”btnPrint” value=”Print Preview” onclick=”DLPrinter.PrintPreview()” />
欢迎大家拍砖!