亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

隨心所欲的Web頁面打印技術(shù)

系統(tǒng) 1982 0

隨心所欲的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)在第二頁的左上角。

?1 public ? 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?窗體設(shè)計器生成的代碼 #region ?Web?窗體設(shè)計器生成的代碼
?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

注意:要保證存放圖片的目錄,有寫權(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條記錄。

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

???DataTable?tabRY?
= ?GetCustomerInfo();? // 讀取數(shù)據(jù)庫

???
int ?Lines? = ? 15 ;???? // 每頁行數(shù)
??? 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> " );
??}


感覺又回到了用記事本做網(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)試。

?

隨心所欲的Web頁面打印技術(shù)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产亚洲精品看片在线观看 | 一级毛片日本特黄97人人 | a毛片免费| 久久一区| 香蕉国产一区二区 | 久久久视 | 国产精品探花一区在线观看 | 国产乱码精品一区二区三区四川 | 国产高清久久99 | 国产1区2区三区不卡 | 中文精品久久久久中文 | 国内视频精品 | avtt亚洲一区中文字幕 | 亚洲一区视频在线播放 | 黄色在线观看www | 成人在线激情视频 | 久久久网站 | 人人精品久久 | 日本大臿亚洲香蕉大片 | 亚洲精品久中文字幕 | 国产伦精品一区二区三区免费观看 | 色综合视频一区二区三区 | 亚洲国产精品视频 | 精品香蕉99久久久久网站 | 一级午夜| 国产一级在线免费观看 | 夜色综合| 国产系列 视频二区 | 嫩操影院 | 久久国产精品久久国产精品 | 在线精品一区二区三区 | 欧美成人性色xxxx视频 | 成人免费网站视频www | 免费永久国产在线视频 | 日本免费视屏 | 日日摸天天摸狠狠摸视频 | 香蕉久久综合 | 成人性生交大片免费看午夜a | 欧美国产日韩在线播放 | 精品福利一区二区三区免费视频 | 99久久99这里只有免费的精品 |