问一下搞三层的高手:你们如何解决纯web版的打印问题?(200分)

  • 主题发起人 主题发起人 barton
  • 开始时间 开始时间
B

barton

Unregistered / Unconfirmed
GUEST, unregistred user!
恕我对B/S不够熟悉。比如用友的web版(java编的)如何解决客户端的打印问题?有的打印格式
要求严格,有的甚至要求套打。浏览器的打印能解决精确打印吗?
 
我也一直没有解决这个问题,后来我采用了ActiveForm可以解决。不过此方式好象不是很好
只是能够达到目的罢了。
 
我一直认为ActiveForm不是真正的瘦客户,与一般应用程序没有太大的差别。没有达到
跨平台的效果。
 
一般生成相应的WORD或EXCEL文件,如果比较复杂的话要用OLE连接WORD模板来生成复杂报表
 
1.ocx 的active form 方式
2.ole 方式调用外部程序
 
哦。原来还是要依赖别的程序,那算什么瘦客户。
我这里有点看法:
外国人不怎么重视报表,什么格式都行,所以web免维护的特点就非常明显。
中国不行,对报表要求比较严。所以我认为在很多场合web版使用起来不是很实用。
 
[:)][red]提个要求:做成的话给我一份代码,部分就行[/red]

关于WEB应用程序的打印组件开发初探 时间:2001/01/10 10:56 作者:ChenHui 中国软件开发中心
 一、引言
  近些年来,随着互联网的普及和推广,传统的单机模式和局域中的c/s模式的应用程序越来越不能满足信息共享的要求。因此,一种新的基于浏览器的b/s的应用程序的开发方式被提了出来。新的开发方案以其客户端的免维护、免配置、程序能根据服务器的信息能够自动更新升级;服务器端多层模式的应有提高处理的效率和安全性越来越被广大的应用程序的开发者所看好。成为应用程序开发的一个新的发展方向。在windows的平台上,人们利用asp来开发服务的显示界面,而用组件来封装商业规则,在各种杂志上利用各种工具进行组件开发也是屡见不鲜。但介绍打印组开发却不怎么看到。笔者希望就自已开发打印组件的一点心得体会来抛砖引玉。
二、设想
  web打印组件要求是在一次为某单位开发信息管理系统中被提及的,这个系统中的一些票据需要打印。这样,如何对这些票据进行套打成了我们必须解决的问题。
  要在客户端打印一些用户要求的票据或其它的文字或图片资料,有两种方式:一种是利用delphi的active form来生成客户端的界面,由浏览器下载安装,并在客户端运行。(这种方式在开发多后台数据库中,较为常用。在国内许多新版本的财务软件都采用了这种方法,其缺点是对开发人员的要求太高),另一种是开发一个组件在客户端安装,然后,由服务器端来生成vbscript脚本,在客户端运行、创建相应的组件对象;利用组件对象来进行打印操作。(这种方法只要客户端的com组件开发完成,使用者只要熟悉vbscript或javascript脚本语言就可能方便的调用)。本文我们主要讨论第二种方式。
三、实现
  首先、运行delphi 5.0;选择file菜单中的new,在弹出的对话框中选择activex页,选择activex library创建activex库.然后,再往新建的库中加入一个automation object,操作步骤同上。在automation object wizard对话框中填入组件名prttest3;单击ok。
  然后、在弹出的prttest3.tlb窗口中,选择iprttest3。单击右键新增一个isinit的property,类型为long。再继续增加如下5个method:
  procedure prtcustompage(pagewidth: integer;
pageheight: integer);
       safecall;
  procedure prtstart;
safecall;
  procedure prtnewpage;
safecall;
  procedure prtend;
safecall;
  procedure prtdrawline(x1: integer;
y1: integer;
x2: integer;
y2:
       integer;
linewidth: integer);
safecall;
  procedure prtsetfont(const fontname: widestring;
fontsize:
       integer);
safecall;
  procedure prttextrect(valign: integer;
halign: integer;
rectleft:
       integer;
recttop: integer;rectright: integer;
rectbottom:
       integer;
const printstring: widestring);
safecall;

  它们意义是:prtcustompage 用来设置自定义纸张.传入的参数自定义纸张的宽度和高度。
        prtstart 用来初始化打印机。如果初始化成功,则将属性isinit置为真,反之则为假。 
        prtnewpage 用来使打印机换页。
        prtend     结束打印任务。
        prtdrawline 用来在页面上绘制一条线。(x1,y1)为起始点.(x2,y2)为终止点。linewidth为打印线的宽度。
        prtsetfont 用来设置打印的字体名及大小。
        prttextrect 用来指定的方框内的输出的指定的字符串。
四、调用
在脚本中调用这个组件的方法:
(1)、利用createobject函数创建一个打印对象。
(2)、调用prtcustompage来指定定制的纸张的大小(以0.1毫米为基本单位)。如果,不是定制的纸张则不需要调用这个过程(即以打印默认的纸张大小进行打印)。
(3)、调用prtstart进行打印机的初始化工作。如果打印机初始化成功,则会将isinit属性置为真,表示初始化成功;否则,表示打印机正在忙或有别的应用程序正在使用打印机,初始化不能成功。
(4)、判断isinit标志。如果为真,则继续执行打印段。
(5)、执行打印段。可以在利用打印机画线、和在指定位置输出文字。
(注:在组件接中的所有位置单位都是0.1毫米。例如.prtobject.prtdrawlien 0,0,1000,1000 表示从左上角(0,0)毫米到右下角(100,100)毫米处,画一条直线)
(6)、利用prtend结束打印任务。
< script language="vbscript">
< !--
sub testprtobject
dim prtobject
set prtobject=createobject("prttest3.prttest3")
prtobject.prtcustompage 1000,1000
prtobject.prtstart
if prtobject.isinit then

prtobject.prtdrawline 0,0,1000,1000,1
prtobject.prtdrawline 500,700,1000,1000,1
prtobject.prtsetfont "宋体",16
prtobject.prttextrect 2,2,0,0,1000,500,"web应用程序打印测试"
prtobject.prtend
end if
set prtobject=nothing
end sub
testprtobject()
//-->
< /script>
五、代码解析
  在这个组件中,我们所要解决的几个问题:
(1)、在delphi的应用程序设计中自定义打印纸张的设置,delphi中自身带了一个quickreport的打印设计程序,这个程序在一定的程度上方便了打印的设计,但这个设计程序对于自定义纸张的设定和打印支持却不是很好。因此,在这个组件中我们采用手工代码来设定自定义纸张大小。
function tprttest3.initprintpaper:boolean;
var
device:array [0..cchdevicename-1] of char;
driver:array [0..(max_path-1)] of char;
port:array [0..32] of char;
hdmode:thandle;
pdmode:pdevmode;
begin

result:=true;
if prtiscustompaper then

begin

{设置打印机段}
printer.getprinter(device,driver,port,hdmode);
if hdmode<>0 then
begin

try
pdmode:=globallock(hdmode);
if pdmode<>nil then
begin

//设定打印的方向为纵向或横向
if paperorientation<>0 then

        pdmode^.dmorientation:=dmorient_landscape
else
pdmode^.dmorientation:=dmorient_portrait;
       //设置拷贝份数为1份.
pdmode^.dmcopies:=1;
       //以毫米为单位的纸张大小.
pdmode^.dmpaperlength:= paperheight*10;
pdmode^.dmpaperwidth:=paperwidth*10;
       //设置纸张类型为用户自定义.
pdmode^.dmpapersize:=dmpaper_user;
end;

globalunlock(hdmode);
printer.setprinter(device,driver,port,hdmode);
except
result:=false;
end;

end else
begin

result:=false;
end;

end;

end;

(2)、打印位置的确定:由于组件是以图形方式进行打印,这就使得我们可以精确指向打印文件的输出位置,以便于进行对某些票据的套打。但这样就产生一个问题,我们是以打印的像素位置指定输入位置,还是以打印尺寸来指定位置。显然,利用像素来输出打印位置,对于编制程序来说是比较方便的。但由于一般用户对像素的概念并不理解,因此会带来使用上的困难;而且每一种打印机的分辩率是不一样的,因此,会出现在不同打印机上打印的效果不一样的问题。而以打印尺寸来指定位置并在程序中妥善加以处理就不会有上面的问题。具体的处理方法是,由用户输入尺寸位置。然后,在打印时,首先取得当前打印机的分辩率(注意:分辨率是以每英寸多少像素为单位的),再计算得出实际输入的像素位置后进行打印,这样就可以使得组件更加实用,而且,保持打印幅面的一致。具体的函数如下。
function tprttest3.mmtoprintpixel(inputpoint:tpoint):tpoint;
begin

result.x:=mmtoprintpixelx(inputpoint.x);
result.y:=mmtoprintpixely(inputpoint.y);
end;

function tprttest3.mmtoprintpixelx(inputx:integer):integer;
begin

if queryprintlogpixel then

begin

pddix:=getdevicecaps(printer.handle,logpixelsx);
pddiy:=getdevicecaps(printer.handle,logpixelsy);
queryprintlogpixel:=false;
end;

result:=trunc(inputx/253.8*pddix+0.5);
end;

function tprttest3.mmtoprintpixely(inputy:integer):integer;
begin

if queryprintlogpixel then

begin

pddix:=getdevicecaps(printer.handle,logpixelsx);
pddiy:=getdevicecaps(printer.handle,logpixelsy);
queryprintlogpixel:=false;
end;

result:=trunc(inputy/253.8*pddiy+0.5);
end;

getdevicecaps:为windows系统中取得指定设备信息的函数。函数的原型如下
int getdevicecaps(
hdc hdc, // 设置的句柄
int nindex // 查询的设备参数。
);

其中,hdc为想要查询的打印机的句柄,logpixelsx、logpixelsy表示要查询的内容是打印机横向、纵向的每英寸的像素点数。
六、组件的注册
  如果是在delphi编写了这个组件的,则可以选择run菜单下的register activex server来进行这个组件的注册。
  对于不开发机器的注册则可使用:点击“开始”→“运行”;在运行对话框中输入以下命令:
 regsvr32 < 文件名 > 注册一个activex控件
  regsvr32 /u < 文件名 > 解除某activex控件的注册
七、其它应用
  组件的扩展:以上列出的仅仅是编写这个组件的框架,功能比较有限。根据需要我们还可以添加上画圆、椭圆,矩形,甚至图片等功能。有兴趣的读者就请自行添加。
因为,组件是采用com的方式运行,所以,我们还在window script hosts(wsh)中应用这个组件,结合wsh原有(通过ado对象)访问外部数据库的能力,就可能做出在windows下功能强大的wsh的脚本程序。
 
java也要依赖其环境,跟activeform相差不大(他也够肥的),呵呵
记得css里有专门有关打印的,你可以去查查看
 
可以用VB做一个控件,然后嵌入到ASP中。
 
看来要学VB了,
 
如果你是用纯页面方式可以用javascript中的"self.print();"
至于排版可以用HTML中的表格来定位.
 
我记得好象有用Java Applet实现打印的
 
其实方法也就那么几个:
1)直接用当前HTML格式进行打印,简单方便。
2)在客户端做手脚,搞个程序出来,或者是自己编,或者是直接用Office的
Web Component,基本的原理都是一样的。
3)上面说的,在Server端搞好了文件,让人下载打印,其实跟2)的是差不多的,
就是在操作搬到Server端罢了,但是在客户端还是要可以打开这些文件的哦,
不然,还是没有办法进行打印。
各位看看还有什么新的注意没有。
 
可以在服务器端生成do
c 格式或者 pdf 格式。
 
看见一篇文章,不知有用不?
关于在页面中解决打印的几个问题
/*
豆腐制作 都是精品
http://www.asp888.net 豆腐技术站
如转载请保留完整版权信息
*/
我们都知道,现在的B/S应用越来越多,我们做程序的时候经常会遇到需要打印报表的情况,但是
我们知道我们很难对IE的客户端的打印机进行控制,我们除了对Window.print 的控制以外。没有
其他的任何的办法,而有的时候我们又必须是先预览,然后打印,有的时候我们也必须页面设置后
进行打印,怎么办?
有的朋友可能已经发现,在IE的 File 菜单下,这些都是有的,但是怎么通过脚本程序来调用这些菜单呢?
经过CafeCat的Sample的提示,终于发现使用一个ActiveX控件是可以实现这个功能的,请看下面的Code
<OBJECT classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 id=WB width=0></OBJECT>
这个Object 其实就是 IEWebBrowser 设定 Width 和 Height 以后,我们在界面上就看不到控件的形状了
然后,我们就可以使用 这个object 实现我们选纸和预览的功能了
<script language="JavaScript">
functiondo
PrintSetup(){
//打印设置
WB.ExecWB(8,1)
}
functiondo
PrintPreview(){
//打印预览
WB.ExecWB(7,1)
}
</script>
当然,这样并不能完全解决客户端的打印问题,豆腐将在以后的文章中就这个问题进行进一步的探讨

作者:豆腐(原创)
添加时间:Mar 12 2001 8:42AM
 
CrystalReport有支持Web打印的OCX嵌入方式。
 
oldppp:能不能把方法讲的详细点,好象你的思路对头。
 
后退
顶部