读书人

从心所欲的Web页面打印技术

发布时间: 2012-12-09 10:53:33 作者: rapoo

随心所欲的Web页面打印技术

一.概述
? 对基于B/S架构的应用程序而言,客户端的页面打印一直是比较头疼的问题,简单的做法是:1.使用IE的打印功能;2.使用水晶报表。但以上两种办法,都有很大的局限性,很难实现特殊要求的排版和精确的定位,所以不能满足一些特殊客户的BT要求。为此,本人总结了自己在使用Web打印上的一点经验,和大家分享。
? 本文涉及以下技术:javascript、ActiveX、ASP.NET、GDI+。

二.基本架构
? 首先,我们不能使用IE的打印功能,必须自己设计‘打印’按钮。很多人习惯将‘打印’按钮放在要打印的页面上,打印时为了不把这个按钮打印出来,采用办法如下:1.打印前隐藏按钮;2.打印;3.显示按钮。
我觉得这样比较麻烦,所以我采用框架。一共有三个页面:
1.main.htm?:框架页面,上面是打印按钮,下面是要显示的页面。
2.header.htm?:标题栏,至少包含一个打印按钮。
3.report.aspx?:要打印的页面,由用户生成。

//main.htm
<html>
?<head>
??<title></title>??
?</head>?
??<frameset rows="10%,90%" frameborder="0" border="0" frameSpacing="0">
??<frame id="header" name="header" src="Header.htm" noresize scrolling="no">
??<frame id="report" name="report" src="Report.aspx" noresize scrolling="auto">
?</frameset>?
</html>

//header.htm
<html>
?<head>??
??<script id=clientEventHandlersJS language=javascript>
??<!--
??function btnPrint_onclick()
??{? ?
? ???parent.report.focus();
? ???parent.report.print(); ?
??}
??//-->
??</script>
?</head>
?<body>?
??<INPUT id="btnPrint" type="button" value="Print" name="Print" onclick="return btnPrint_onclick()">??
?</body>
</html>

? 这样,在点击‘打印’按钮时,将直接打印report.aspx页面的内容,既简单又直观。

三.打印
?要完全控制打印,就必须由程序设定页眉、页脚、页边距。每个客户端的IE设置都不尽相同,你可以要求你的客户修改他们的打印设置为你指定的值,显然这不现实。所以正确的做法是:
1.备份客户打印页面设置;
2.设置页眉页脚上下左右边距为自己需要的值;
3.打印;
4.恢复原来的打印页面设置。

?这里用到一个叫ScriptX的控件。你需要下载一个文件:smsx.cab,下载地址:http://www.meadroid.com/scriptx/sxdownload.asp。这个地址并不能保证长期有效,你可以在搜索引擎上搜索‘ScriptX’以获得更多相关信息。

在“header.htm”中增加该控件的引用:
<OBJECT id="factory" style="DISPLAY: none" codeBase="http://localhost/WebApplication1/smsx.cab#VVersion=6,3,434,12"
?classid="clsid:1663ed61-23eb-11d2-b92f-008048fdd814" viewastext>
</OBJECT>
注意CodeBase指向你的实际存放文件的位置,在客户端第一次浏览该页面时,将下载并安装该控件,请确定客户端的安全设置允许安装控件。
那么此时 header.htm 的内容如下。

//header.htm
<html>
<head>
?<script id="clientEventHandlersJS" language="javascript">
?<!--
?function btnPrint_onclick()
?{
? //备份客户打印机设置
?? var h = factory.printing.header;
?? var f = factory.printing.footer;
?? var t = factory.printing.topMargin;
?? var b = factory.printing.bottomMargin;
?? var l = factory.printing.leftMargin;
?? var r = factory.printing.rightMargin;
?
?? //设置页眉页脚上下左右边距?
?? factory.printing.header = "";
? ? factory.printing.footer = "";
? ? factory.printing.topMargin="0";
?? factory.printing.bottomMargin="0";
?? factory.printing.leftMargin="0";
?? factory.printing.rightMargin="0";
?
?? //打印
?? parent.report.focus();
?? parent.report.print()
?
?? //恢复原来的打印设置
?? factory.printing.header = h;
?? factory.printing.footer = f;
? ? factory.printing.topMargin=t;
?? factory.printing.bottomMargin=b;
?? factory.printing.leftMargin=l;
?? factory.printing.rightMargin=r;?
?}
?//-->
?</script>
?
?<OBJECT id="factory" style="DISPLAY: none" codeBase="http://localhost/WebApplication1/smsx.cab#VVersion=6,3,434,12"
??classid="clsid:1663ed61-23eb-11d2-b92f-008048fdd814" viewastext>
?</OBJECT>
</head>
<body bgColor="#9999cc">
?<INPUT id="btnPrint" type="button" value="Print" name="Print" onclick="return btnPrint_onclick()">???
</body>
</html>

? 此时,不管客户端IE设置如何,都能正确打印页面,打印内容将完全取决于页面:report.aspx。

四.动态页面生成
1. 如果你的页面是静态页面,或者页面元素为固定数量,那就非常简单了。只要调整好各个元素位置就行了,绝对所见即所得。要注意的是一个A4纸的大小为21cm×29.7cm,对应象素大约为 794×1123 (系统分辨率96DPI) 。

2.如果你要生成一些图表,可以使用GDI+,你自己绘制的图片绝对能满足客户需求。下面给一个例子,我在页面放一个Label,一个Image。Image动态生成,调整其位置使其打印时出现在第二页的左上角。

?1从心所欲的Web页面打印技术public?class?Report?:?System.Web.UI.Page
?2从心所欲的Web页面打印技术从心所欲的Web页面打印技术?从心所欲的Web页面打印技术{
?3从心所欲的Web页面打印技术??protected?System.Web.UI.WebControls.Image?Image1;
?4从心所欲的Web页面打印技术??protected?System.Web.UI.WebControls.Label?Label1;
?5从心所欲的Web页面打印技术?
?6从心所欲的Web页面打印技术从心所欲的Web页面打印技术??Web?窗体设计器生成的代码#region?Web?窗体设计器生成的代码
?7从心所欲的Web页面打印技术??override?protected?void?OnInit(EventArgs?e)
?8从心所欲的Web页面打印技术从心所欲的Web页面打印技术??从心所欲的Web页面打印技术{???
?9从心所欲的Web页面打印技术???InitializeComponent();
10从心所欲的Web页面打印技术???base.OnInit(e);
11从心所欲的Web页面打印技术??}
12从心所欲的Web页面打印技术??private?void?InitializeComponent()
13从心所欲的Web页面打印技术从心所欲的Web页面打印技术??从心所欲的Web页面打印技术{????
14从心所欲的Web页面打印技术???this.Load?+=?new?System.EventHandler(this.Page_Load);
15从心所欲的Web页面打印技术??}
16从心所欲的Web页面打印技术??#endregion
17从心所欲的Web页面打印技术
18从心所欲的Web页面打印技术??private?void?Page_Load(object?sender,?System.EventArgs?e)
19从心所欲的Web页面打印技术从心所欲的Web页面打印技术??从心所欲的Web页面打印技术{???
20从心所欲的Web页面打印技术???if(!Page.IsPostBack)
21从心所欲的Web页面打印技术从心所欲的Web页面打印技术???从心所欲的Web页面打印技术{
22从心所欲的Web页面打印技术????InitImage();
23从心所欲的Web页面打印技术???}
24从心所欲的Web页面打印技术??}
25从心所欲的Web页面打印技术
26从心所欲的Web页面打印技术??private?void?InitImage()
27从心所欲的Web页面打印技术从心所欲的Web页面打印技术??从心所欲的Web页面打印技术{
28从心所欲的Web页面打印技术???Bitmap?bmp?=?new?Bitmap(800,1120);
29从心所欲的Web页面打印技术???Graphics?g?=??Graphics.FromImage(bmp);
30从心所欲的Web页面打印技术
31从心所欲的Web页面打印技术???g.FillRectangle(Brushes.Gray,0,0,800,1120);
32从心所欲的Web页面打印技术
33从心所欲的Web页面打印技术???g.FillRectangle(Brushes.RoyalBlue,0,0,100,600);
34从心所欲的Web页面打印技术???g.FillRectangle(Brushes.Aqua,600,0,100,600);
35从心所欲的Web页面打印技术???g.FillRectangle(Brushes.Coral,700,0,100,600);?
36从心所欲的Web页面打印技术?
37从心所欲的Web页面打印技术???g.FillRectangle(Brushes.YellowGreen,0,800,800,100);
38从心所欲的Web页面打印技术???g.FillRectangle(Brushes.Beige,0,900,800,100);
39从心所欲的Web页面打印技术???g.FillRectangle(Brushes.SkyBlue,0,1000,800,100);
40从心所欲的Web页面打印技术???g.FillRectangle(Brushes.Tomato,0,1100,800,20);
41从心所欲的Web页面打印技术
42从心所欲的Web页面打印技术???string?filename?=?Server.MapPath("TempImages\\img1.jpg");???
43从心所欲的Web页面打印技术
44从心所欲的Web页面打印技术???bmp.Save(filename,?System.Drawing.Imaging.ImageFormat.Jpeg);
45从心所欲的Web页面打印技术
46从心所欲的Web页面打印技术???this.Label1.Text?=?filename;
47从心所欲的Web页面打印技术???this.Image1.ImageUrl?=?filename;
48从心所欲的Web页面打印技术???this.Image1.Attributes["style"]="POSITION:?absolute;?LEFT:?0cm;??TOP:?29.7cm";?//定位
49从心所欲的Web页面打印技术??}??
50从心所欲的Web页面打印技术?}
51从心所欲的Web页面打印技术
52从心所欲的Web页面打印技术

注意:要保证存放图片的目录,有写权限。

3.以上技术只适合于页面元素为固定数量的情况,对于页面内容大小不定的情况,例如,要打印一份人员信息的清单,人员数量为1~1000不等,每页显示20条记录,要有规定的页眉、页脚,此时该如何处理。
? 思路:ASP.NET页面都有一个基类System.Web.UI.Page,该类有一个保护方法叫void Render(HtmlTextWriter writer),就是通过这个方法,ASP.NET在后台把WEB服务器端控件的属性转换成HTML代码,并发送到客户端供浏览器显示。我们的办法就是“劫持”该方法,完全手工生成所需页面标记代码。
先看一个例子:
?public class FrmRYInfo : System.Web.UI.Page
?{
??private void Page_Load(object sender, System.EventArgs e)
??{???
??}
??protected override void Render(HtmlTextWriter writer)
??{
???writer.Write("<HTML>");
???writer.Write("<body>");?
???writer.Write("<h1>Hello,world!</h1>");??
???writer.Write("</body>");
???writer.Write("</html>");
??}
?}
? 编译并运行以上程序,可以看到一行一号字体的"Hello,world!",查看页面源文件,内容如下:
?<HTML><body><h1>Hello,world!</h1></body></html>
? 对照上面代码,应该非常好理解,下面我们就做一个实际的例子,将信息从数据库读出,显示在页面上,每页显示15条记录。

从心所欲的Web页面打印技术?protected?override?void?Render(HtmlTextWriter?writer)
从心所欲的Web页面打印技术从心所欲的Web页面打印技术??从心所欲的Web页面打印技术{
从心所欲的Web页面打印技术???writer.Write("<HTML>");
从心所欲的Web页面打印技术???writer.Write("<body>");??
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术???DataTable?tabRY?=?GetCustomerInfo();?//读取数据库
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术???int?Lines?=?15;????//每页行数
从心所欲的Web页面打印技术???int?Count?=?tabRY.Rows.Count;
从心所欲的Web页面打印技术???int?TotalPage?=?Count/Lines?+?(Count%Lines==0?0:1);
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术???for(int?CurrentPage?=0;?CurrentPage<TotalPage;?CurrentPage++)
从心所欲的Web页面打印技术从心所欲的Web页面打印技术???从心所欲的Web页面打印技术{
从心所欲的Web页面打印技术????int?StartRow?=?CurrentPage?*?Lines;
从心所欲的Web页面打印技术????int?EndRow?=?StartRow?+?Lines;
从心所欲的Web页面打印技术????if(EndRow?>?Count)?EndRow?=?Count;
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术????ProcessCurrentPage(writer,tabRY,StartRow,EndRow,CurrentPage,TotalPage);
从心所欲的Web页面打印技术???}
从心所欲的Web页面打印技术??
从心所欲的Web页面打印技术???writer.Write("</body>");
从心所欲的Web页面打印技术???writer.Write("</html>");
从心所欲的Web页面打印技术??}
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术??private?void?ProcessCurrentPage(HtmlTextWriter?writer,?DataTable?tabRY,?int?StartRow,?int?EndRow,?int?
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术CurrentPage,?int?TotalPage)
从心所欲的Web页面打印技术从心所欲的Web页面打印技术??从心所欲的Web页面打印技术{
从心所欲的Web页面打印技术???if(CurrentPage?!=?0)
从心所欲的Web页面打印技术从心所欲的Web页面打印技术???从心所欲的Web页面打印技术{
从心所欲的Web页面打印技术????writer.Write("<p??style=page-break-before:always></p>");
从心所欲的Web页面打印技术??????????????}
从心所欲的Web页面打印技术???
从心所欲的Web页面打印技术???writer.Write("<table??width=630?height=417?border=0>");
从心所欲的Web页面打印技术???writer.Write("?<tr>");
从心所欲的Web页面打印技术???writer.Write("??<td?width=624?height=47><div?align=center??style=font-size:24px>人员信息汇总
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术表</div></td>");
从心所欲的Web页面打印技术???writer.Write("??</tr>");
从心所欲的Web页面打印技术???writer.Write("??<tr>");
从心所欲的Web页面打印技术???writer.Write("??<td?height=222>");
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术???writer.Write("???<table?width=623??border=1?cellpadding=0?cellspacing=0>");
从心所欲的Web页面打印技术???writer.Write("???<tr>");
从心所欲的Web页面打印技术???writer.Write("????<td?width=134><div?align=center>姓名</div></td>");
从心所欲的Web页面打印技术???writer.Write("????<td?width=134><div?align=center>编号</div></td>");
从心所欲的Web页面打印技术???writer.Write("????<td?width=134><div?align=center>电话</div></td>");
从心所欲的Web页面打印技术???writer.Write("????<td?width=134><div?align=center>小灵通</div></td>");?????????
从心所欲的Web页面打印技术???writer.Write("???</tr>");
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术??for(int?i=StartRow;?i<EndRow;?i++)
从心所欲的Web页面打印技术从心所欲的Web页面打印技术??从心所欲的Web页面打印技术{?
从心所欲的Web页面打印技术???DataRow?row?=?tabRY.Rows[i];
从心所欲的Web页面打印技术???string?XM?=?row["MC"].ToString();
从心所欲的Web页面打印技术???string?BH?=?row["BH"].ToString();
从心所欲的Web页面打印技术???string?DH?=?row["LXDH"].ToString();if(DH.Length==0)DH="-";
从心所欲的Web页面打印技术???string?XLT?=??row["XLT"].ToString();
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术???writer.Write("???<tr>");
从心所欲的Web页面打印技术???writer.Write("????<td?width=134><div?align=center>"?+?XM?+?"</div></td>");
从心所欲的Web页面打印技术???writer.Write("????<td?width=134><div?align=center>"?+?BH?+?"</div></td>");
从心所欲的Web页面打印技术???writer.Write("????<td?width=134><div?align=center>"?+?DH?+?"</div></td>");
从心所欲的Web页面打印技术???writer.Write("????<td?width=134><div?align=center>"?+?XLT?+?"</div></td>");?????
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术????
从心所欲的Web页面打印技术???writer.Write("???</tr>");
从心所欲的Web页面打印技术??}
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术???writer.Write("???</table>");
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术???writer.Write("??</td>");
从心所欲的Web页面打印技术???writer.Write("??</tr>");
从心所欲的Web页面打印技术???writer.Write("??<tr>");
从心所欲的Web页面打印技术???writer.Write("??<td?height=37><div?align=right>第"?+?(CurrentPage+1).ToString()?+"页,共"?+?
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术TotalPage.ToString()?+?"页</div></td>");
从心所欲的Web页面打印技术???writer.Write("??</tr>");
从心所欲的Web页面打印技术???writer.Write("</table>");
从心所欲的Web页面打印技术??}
从心所欲的Web页面打印技术
从心所欲的Web页面打印技术

感觉又回到了用记事本做网页的年代,手工生成HTML代码,是不是真正叫“随心所欲”。
几点说明:
(1)在每一页(除了第一页)的头部加入 writer.Write("<p? style=page-break-before:always></p>"); 目的是控制在打印时,打印机在此换页。这里通过强制打印机换页来实现页面的布局,与上面的绝对定位的办法不同。该标记只影响打印,不影响显示。
(2)用记事本做网页绝对很痛苦,而且HTML标记也很不好用,我的办法是:用Dreamweaver生成需要的页面,再参照其HTML代码进行编程。
(3)尽量使用HtmlTextWriter类提供的一些其它方法如WriteBeginTag等取代Write方法,这样可以提高页面在客户端的兼容性。同时在每个标记后加入writer.WriteLine();进行换行,以便于调试。

?

?

?

读书人网 >Web前端

热点推荐