posts - 25,  comments - 396,  trackbacks - 35
     在上一篇文章《也谈WEB打印(二):简单的分析一下IE的打印原理并实现简单的打印和预览》中,我们剖析了IE的打印原理,并学会了如何调用IE的打印功能,在这篇文章中,我们实现写自己的打印模板。

IE5.5开始,你可以定制WebBrowser控件和IE如何打印和预览文档。打印和预览的机制有打印模板控制,这是一些HTML文件,他们可以由开发人员可以使用由打印模板行为暴露的对象模型来生成。MSDN上说,如果打印模板是HTML文件的时候,定制的打印模板只能由C++语言从发布或拦截IDM_PRINT/IDM_PRINTPREVIEW命令的程序或控件中使用(打印模板的路径由IOleCommandTarget::ExecpvaIn参数指定)。但实际上,DelphiC#语言也是可以的,我已经做过测试了。至于VB可不可以,我没有试验过,不敢肯定。缺省情况下,IE使用自己的打印模板,就是说,如果IOleCommandTarget::ExecpvaIn参数为NULL的时候,IE就会调用自己的打印模板进行打印。

我们可以用打印模板做一些什么事情呢?
     1、 控制打印和预览时页面的版面,打印以及预览的内容;
     2、 控制打印任务如何被处理,例如以何种顺序打印页面;
     3、 控制打印预览窗口的外观,在打印用户界面上放置定制的控件。

有了打印模板,我们可以加入一些非常酷的功能,例如加入公司的Logo,法律声明,广告;定制页眉页脚的位置和样式;安排打印计划进行定时打印,如此等等。
     一个打印模板其实就是一个标准的HTML文件,与其他的HTML文件不同的是,他有4个声明模板的基本元素:LAYOUTRECTDEVICERECTTEMPLATEPRINTERHEADERFOOTER。下面讲解一下这4个模板元素的作用:   
      LAYOUTRECT:为打印和预览模板中的文档内容生成容器.
      DEVICERECT:为LAYOUTRECT元素和打印模板中的其他内容提供一个容器。位于DEVICERECT之外的内容都不会被打印。
      TEMPLATEPRINTER:提供一个打印模板以获取页面设置和打印设置,并且可以控制从打印模板初始化出来的打印作业。
      HEADERFOOTER:提供一个工具以便打印模板可以把页眉和页脚的格式化字符串转换为格式化的HTML文本。
    下面,我们先写一个最小的具有预览但是不能打印的模板(模板代码来自于MSDN,我只做了一点点说明):    

 1<!-- Template1.htm: 最小的模板(只能预览)
 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 ExplorerIE命名空间的实现,使得打印模板上的元素的行为对模板有效。

值得注意的是,LAYOUTRECT没有结束标签,在他的结束括号之前必须放一个反斜线,这类似于XML文档中没有结束标签的元素的语法一样。LAYOUTRECT中不能包含任何HTML,例如,如下的语句不会有效:
    layoutrect1.innerHTML = "<B>Hi there!</B>";
   现在我们来看看属性。ID属性和CLASS属性是大家所熟知的,值得注意的是,CLASS指定的样式中必须包含有WidthHeight。在本例中,这2个值都不符合实际。当然,我们可以从TemplatePrinter 行为中取得正确的值。不过我们先不讨论这个。另外一个属性就是MEDIEA,大家都知道他的含义,不过,在这里,我们必须指定MEDIA属性的值是“print”,这是强制性的。另外就是CONTENTSRC,如果他的值是“document”,则表示需要打印或预览的是IE当前显示的页面,如果不想打印这个文档,那么,可以指定其他的URL,例如http://yahong111.cnblogs.com,这样的话,就会打印或预览http://yahong111.cnblogs.com的内容,而不是当前页面。最后一个是NEXTRECT,他表示如果当前页满了时候,下一个LAYOUTRECT的名字,在本例中,“layoutrect1”的NEXTRECT就是“layoutrect2”,如果当前页是最后一页,那么就不要指定NEXTRECT的值。被打印或预览的文档有多少页,我们就必须有多少个LAYOUTRECT。在本例中,我们只指定了2LAYOUTRECT,所以,只会显示2页,而且,即使被打印文档只有一页,他也会显示2页。
    下面是DEVICERECTLAYOUTRECT的图解。
 
   
   那么,我们如何知道当前被打印或预览的文档需要多少个LAYOUTRECT呢?我们如何正确设置每个DEVICERECTLAYOUTRECTWidthHeight呢?这是我们下一篇文章所讨论的内容。
   参考文档:《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()" />

     欢迎大家拍砖!

posted on 2007-10-11 16:50  永红  阅读(13926)  评论(37编辑  收藏