隨心所欲的Web頁面打印技術(shù)
一.概述
? 對基于B/S架構(gòu)的應(yīng)用程序而言,客戶端的頁面打印一直是比較頭疼的問題,簡單的做法是:1.使用IE的打印功能;2.使用水晶報表。但以上兩種辦法,都有很大的局限性,很難實現(xiàn)特殊要求的排版和精確的定位,所以不能滿足一些特殊客戶的BT要求。為此,本人總結(jié)了自己在使用Web打印上的一點經(jīng)驗,和大家分享。
? 本文涉及以下技術(shù):javascript、ActiveX、ASP.NET、GDI+。
二.基本架構(gòu)
? 首先,我們不能使用IE的打印功能,必須自己設(shè)計‘打印’按鈕。很多人習(xí)慣將‘打印’按鈕放在要打印的頁面上,打印時為了不把這個按鈕打印出來,采用辦法如下:1.打印前隱藏按鈕;2.打??;3.顯示按鈕。
我覺得這樣比較麻煩,所以我采用框架。一共有三個頁面:
1.main.htm?:框架頁面,上面是打印按鈕,下面是要顯示的頁面。
2.header.htm?:標(biāo)題欄,至少包含一個打印按鈕。
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頁面的內(nèi)容,既簡單又直觀。
三.打印
?要完全控制打印,就必須由程序設(shè)定頁眉、頁腳、頁邊距。每個客戶端的IE設(shè)置都不盡相同,你可以要求你的客戶修改他們的打印設(shè)置為你指定的值,顯然這不現(xiàn)實。所以正確的做法是:
1.備份客戶打印頁面設(shè)置;
2.設(shè)置頁眉頁腳上下左右邊距為自己需要的值;
3.打印;
4.恢復(fù)原來的打印頁面設(shè)置。
?這里用到一個叫ScriptX的控件。你需要下載一個文件:smsx.cab,下載地址: http://www.meadroid.com/scriptx/sxdownload.asp 。這個地址并不能保證長期有效,你可以在搜索引擎上搜索‘ScriptX’以獲得更多相關(guān)信息。
在“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指向你的實際存放文件的位置,在客戶端第一次瀏覽該頁面時,將下載并安裝該控件,請確定客戶端的安全設(shè)置允許安裝控件。
那么此時 header.htm 的內(nèi)容如下。
//header.htm
<html>
<head>
?<script id="clientEventHandlersJS" language="javascript">
?<!--
?function btnPrint_onclick()
?{
? //備份客戶打印機(jī)設(shè)置
?? 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;
?
?? //設(shè)置頁眉頁腳上下左右邊距?
?? 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()
?
?? //恢復(fù)原來的打印設(shè)置
?? 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設(shè)置如何,都能正確打印頁面,打印內(nèi)容將完全取決于頁面:report.aspx。
四.動態(tài)頁面生成
1. 如果你的頁面是靜態(tài)頁面,或者頁面元素為固定數(shù)量,那就非常簡單了。只要調(diào)整好各個元素位置就行了,絕對所見即所得。要注意的是一個A4紙的大小為21cm×29.7cm,對應(yīng)象素大約為 794×1123 (系統(tǒng)分辨率96DPI) 。
2.如果你要生成一些圖表,可以使用GDI+,你自己繪制的圖片絕對能滿足客戶需求。下面給一個例子,我在頁面放一個Label,一個Image。Image動態(tài)生成,調(diào)整其位置使其打印時出現(xiàn)在第二頁的左上角。

?2

?3

?4

?5

?6

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

注意:要保證存放圖片的目錄,有寫權(quán)限。
3.以上技術(shù)只適合于頁面元素為固定數(shù)量的情況,對于頁面內(nèi)容大小不定的情況,例如,要打印一份人員信息的清單,人員數(shù)量為1~1000不等,每頁顯示20條記錄,要有規(guī)定的頁眉、頁腳,此時該如何處理。
? 思路:ASP.NET頁面都有一個基類System.Web.UI.Page,該類有一個保護(hù)方法叫void Render(HtmlTextWriter writer),就是通過這個方法,ASP.NET在后臺把WEB服務(wù)器端控件的屬性轉(zhuǎn)換成HTML代碼,并發(fā)送到客戶端供瀏覽器顯示。我們的辦法就是“劫持”該方法,完全手工生成所需頁面標(biāo)記代碼。
先看一個例子:
?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>");
??}
?}
? 編譯并運(yùn)行以上程序,可以看到一行一號字體的"Hello,world!",查看頁面源文件,內(nèi)容如下:
?<HTML><body><h1>Hello,world!</h1></body></html>
? 對照上面代碼,應(yīng)該非常好理解,下面我們就做一個實際的例子,將信息從數(shù)據(jù)庫讀出,顯示在頁面上,每頁顯示15條記錄。

















































































感覺又回到了用記事本做網(wǎng)頁的年代,手工生成HTML代碼,是不是真正叫“隨心所欲”。
幾點說明:
(1)在每一頁(除了第一頁)的頭部加入 writer.Write("<p? style=page-break-before:always></p>"); 目的是控制在打印時,打印機(jī)在此換頁。這里通過強(qiáng)制打印機(jī)換頁來實現(xiàn)頁面的布局,與上面的絕對定位的辦法不同。該標(biāo)記只影響打印,不影響顯示。
(2)用記事本做網(wǎng)頁絕對很痛苦,而且HTML標(biāo)記也很不好用,我的辦法是:用Dreamweaver生成需要的頁面,再參照其HTML代碼進(jìn)行編程。
(3)盡量使用HtmlTextWriter類提供的一些其它方法如WriteBeginTag等取代Write方法,這樣可以提高頁面在客戶端的兼容性。同時在每個標(biāo)記后加入writer.WriteLine();進(jìn)行換行,以便于調(diào)試。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
