`
kakarot_java
  • 浏览: 163712 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

web 打印

阅读更多
随心所欲的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动态生成,调整其位置使其打印时出现在第二页的左上角。

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

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条记录。

protected override void Render(HtmlTextWriter writer)
  {
   writer.Write("<HTML>");
   writer.Write("<body>"); 

   DataTable tabRY = GetCustomerInfo(); //读取数据库

   int Lines = 15;    //每页行数
   int Count = tabRY.Rows.Count;
   int TotalPage = Count/Lines + (Count%Lines==0?0:1);

   for(int CurrentPage =0; CurrentPage<TotalPage; CurrentPage++)
   {
    int StartRow = CurrentPage * Lines;
    int EndRow = StartRow + Lines;
    if(EndRow > Count) EndRow = Count;

    ProcessCurrentPage(writer,tabRY,StartRow,EndRow,CurrentPage,TotalPage);
   }
 
   writer.Write("</body>");
   writer.Write("</html>");
  }

  private void ProcessCurrentPage(HtmlTextWriter writer, DataTable tabRY, int StartRow, int EndRow, int

CurrentPage, int TotalPage)
  {
   if(CurrentPage != 0)
   {
    writer.Write("<p  style=page-break-before:always></p>");
              }
  
   writer.Write("<table  width=630 height=417 border=0>");
   writer.Write(" <tr>");
   writer.Write("  <td width=624 height=47><div align=center  style=font-size:24px>人员信息汇总

表</div></td>");
   writer.Write("  </tr>");
   writer.Write("  <tr>");
   writer.Write("  <td height=222>");

   writer.Write("   <table width=623  border=1 cellpadding=0 cellspacing=0>");
   writer.Write("   <tr>");
   writer.Write("    <td width=134><div align=center>姓名</div></td>");
   writer.Write("    <td width=134><div align=center>编号</div></td>");
   writer.Write("    <td width=134><div align=center>电话</div></td>");
   writer.Write("    <td width=134><div align=center>小灵通</div></td>");        
   writer.Write("   </tr>");

  for(int i=StartRow; i<EndRow; i++)
  {
   DataRow row = tabRY.Rows[i];
   string XM = row["MC"].ToString();
   string BH = row["BH"].ToString();
   string DH = row["LXDH"].ToString();if(DH.Length==0)DH="-";
   string XLT =  row["XLT"].ToString();

   writer.Write("   <tr>");
   writer.Write("    <td width=134><div align=center>" + XM + "</div></td>");
   writer.Write("    <td width=134><div align=center>" + BH + "</div></td>");
   writer.Write("    <td width=134><div align=center>" + DH + "</div></td>");
   writer.Write("    <td width=134><div align=center>" + XLT + "</div></td>");    

   
   writer.Write("   </tr>");
  }

   writer.Write("   </table>");

   writer.Write("  </td>");
   writer.Write("  </tr>");
   writer.Write("  <tr>");
   writer.Write("  <td height=37><div align=right>第" + (CurrentPage+1).ToString() +"页,共" +

TotalPage.ToString() + "页</div></td>");
   writer.Write("  </tr>");
   writer.Write("</table>");
  }


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

分享到:
评论

相关推荐

    Delphi WEB打印服务【支持打印设计、打印预览、打印】

    Delphi WEB打印服务是一种在Delphi开发环境中实现的高级功能,它允许用户通过Web接口进行打印操作,包括设计打印布局、预览打印效果以及实际的打印执行。这种服务的出现,使得开发者能够构建出跨平台的远程打印解决...

    楚琳Web打印控件、源码、使用说明

    楚琳Web打印控件是一款专为网页打印设计的软件组件,它使得在Web应用程序中实现打印功能变得更加便捷和高效。这款控件不仅提供了基础的打印服务,还包含了源码,以便开发者可以深入理解其工作原理并进行定制化开发。...

    非常不错的web打印程序(附示例程序)

    Web打印程序是一种允许用户在网页上直接进行打印操作的技术,它可以极大地提升用户体验,尤其是在需要大量打印文档或报表的场景中。本资源包含了一个优秀的Web打印程序,并提供了丰富的示例程序,便于开发者理解和...

    C#实现简单的Web打印控件

    在本文中,我们将深入探讨如何使用C#语言实现一个简单的Web打印控件。Web打印控件对于Web应用程序来说是至关重要的,它允许用户在浏览器环境中直接打印网页内容,而无需通过复制粘贴到其他应用程序中。传统的Web打印...

    JAVA的Web打印方式(PageOffice、POI、jacob,html打印等)

    JAVA的Web打印方式详解 JAVA的Web打印方式是指在Web应用程序中实现打印功能的各种方法和技术。本文将主要介绍使用PageOffice、POI、jacob、html打印等方式来实现Web打印。 一、使用浏览器自带的打印功能直接打印 ...

    asp.net实现web打印功能

    在ASP.NET中实现Web打印功能是一项常见的需求,它允许用户直接从网页上打印内容而无需先下载文件。本文将深入探讨如何在ASP.NET环境中构建这一功能,并基于描述中的"print.html"文件,推测这是一个用于演示Web打印...

    通过Web打印超市一样的小票

    在IT行业中,Web打印是一种利用Web技术实现远程打印的功能,尤其适用于需要跨设备或远程操作的场景。在超市环境中,小票打印是至关重要的环节,它涉及到收银、库存管理和客户体验。本篇将深入探讨如何通过Web技术来...

    非常好用的web打印插件 , 可以热敏打印

    在IT行业中,Web打印插件是一种非常实用的工具,它允许用户通过网页浏览器直接进行打印操作,无需离开当前页面或下载文件到本地。本篇将详细介绍一个被评价为“非常好用”的Web打印插件,特别适合热敏打印,并提供...

    【Delphi WEB打印服务】通过请求api,实现打印设计、打印预览、打印,即可做到本地和远程打印.zip

    【Delphi WEB打印服务】是基于Delphi开发的一款高级打印解决方案,它允许用户通过API请求进行打印设计、预览和实际打印操作,无论是本地还是远程环境都能轻松应对。这一技术在C#编程语言中同样适用,可以为C#开发者...

    Delphi web打印源码 WEBPrinter For Delphi 10.3 Rio

    《Delphi Web打印技术详解——基于WEBPrinter For Delphi 10.3 Rio》 在IT行业中,Delphi是一款强大的Windows应用程序开发工具,以其高效、易用和丰富的库支持著称。随着Web技术的发展,Delphi也逐步融入了Web相关...

    WEB 打印控件及实例

    【描述】:虽然描述信息为空,但根据标题和标签,我们可以推测这个资源可能包含了一个具体的WEB打印控件的实现和一个实例应用。博文链接可能提供了详细的技术实现和使用方法,包括如何在网页中集成该控件以及如何...

    一个完全免费的WEB打印插件控件,支持:C#/vb.net/asp/PHP/JSP,也有实例

    在IT行业中,Web打印是一个重要的需求,特别是在企业环境中,用户可能需要从网页上直接打印文档或报告。"一个完全免费的WEB打印插件控件,支持:C#/vb.net/asp/PHP/JSP,也有实例" 提供了一个解决方案,允许开发者在...

    免费web打印控件免费web打印控件

    Web打印控件是一种在网页上实现打印功能的技术解决方案,它允许用户无需下载任何客户端软件就能直接从浏览器打印网页内容。标题“免费web打印控件”指的是这样一种工具,它可以为网站提供无成本的打印功能,使得访问...

    Web打印控件(目前最强大最专业最新版本)

    22.如何构建自己的纯WEB打印预览见样例二十二 23.如何居中打印超文本见样例二十三 24.如何选择界面皮肤见样例二十四 25.如何指定输出到哪页或仅预览见样例二十五 26.如何提高多页打印的性能见样例二十六 27.如何导出...

    web打印方法 web打印方法

    web打印方法web打印方法web打印方法web打印方法web打印方法

    web打印,打印预览

    Web打印和打印预览是网页开发中的重要组成部分,它们允许用户在正式打印前查看文档的打印效果,确保格式正确无误。在这个过程中,开发者通常会利用浏览器提供的API和CSS技术来实现这一功能。下面我们将详细探讨这个...

    纯js在线WEB打印设计模块

    【纯js在线WEB打印设计模块】是一种基于JavaScript技术的网页打印解决方案,专为在线设计和打印快递模板、配货单模板等应用场景而设计。在现代电子商务和物流行业中,这种技术对于自动化业务流程、提高效率至关重要...

    web打印程序很好用

    Web打印是一种基于网络技术的打印解决方案,它允许用户通过网页浏览器或者其他Web应用程序来发送打印作业,无需安装特定的打印驱动程序。这种技术极大地简化了打印流程,尤其在多用户环境中,提高了工作效率并降低了...

    不需要插件的WEB打印

    在IT行业中,Web打印是一个重要的功能,特别是在开发各种业务系统时,例如提到的物业收费模块。Web打印允许用户直接从浏览器中打印网页内容或者特定的数据,而无需安装额外的插件或应用程序。以下是对"不需要插件的...

    简单方便的web打印编辑器

    "简单方便的web打印编辑器"是指一种能够帮助用户在浏览器环境下轻松编辑和打印内容的工具,它使得非技术用户也能便捷地创建、格式化和输出文档。本文将深入探讨JS打印编辑器的关键知识点,以及如何构建和实现这样的...

Global site tag (gtag.js) - Google Analytics