欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

web打印技术选型的烦恼与折衷方案 打印ActiveXScriptX横向WScript.Shell 

程序员文章站 2022-07-14 08:46:23
...

 


一、 讨论范围:

 

基于web网页、浏览器限于IE

 

二、  引子:

 

我们团队在做项目的过程中,碰到不同情况的打印需求;我这里把打印需求分成四种。

1)、复杂的报表打印,需要做套打。

2)、最简单的网页内容打印。

3)、简单设置后的网页内容打印。

4)、简单设置后(包括横向、纵向)自动设置后的网页内容打印。

之所以把34分开,是因为这两者研究的过程中两者看似小的差别,但技术实现上还是有不一样的地方,我们团队在项目过程中刚好碰到了第4种需求,进行一翻技术研究后,发觉第4种需求技术解决方案着实让人烦恼。但是再进一步在用户体验的角度来看,第4种和第3种虽说都能实现,但体验差不多一样糟糕。因此最终的折衷方案适合于第3、4种需求。

                   这里先对前两种需求的技术选型做出简单说明,然后再进一步讨论第3、4种需求及我们的折衷方案。

        

1)复杂的报表打印,需要做套打

开发ActiveX控件;或者使用开源;或者购买商用控件。我们团队使用的是自己开发的ActiveX控件。

2)最简单的网页内容打印

使用IE自带的打印,或者简单的使用js调用

Webbrowser

 

三、 展开讨论--web页面设置

 

ie浏览器->打印->页面设置界面,可以看到有以下元素可以设置:

1)纸张大小

2)纵向/横向

3)打印背景颜色和图像

4)启用缩小字体填充

5)页眉

6)页脚

7)左边距

8)右边距

9)上边距

10)下边距

11)字体大小

在设置并保存后,退出ie后,再次进入界面会发现纵向/横向和纸张大小这两个保存会丢掉,其他的都能保存住上次设置的状态。或许因为纵向/横向和纸张大小在打印设置那里还可以设置,所以这个值就没有被存入注册表。来看一下注册表

HKEY_CURRENT_USER/SOFTWARE/Microsoft/Internet Explorer/PageSetup,可以看到以下键值(中文作者加上)

font(字体大小)

footer(页脚)

header(页眉)

margin_bottom(下边距)

margin_left(左边距)

margin_right(右边距)

margin_top(下边距)

Print_Background(打印背景颜色和图像)

Shrink_To_Fit(启用缩小字体填充)

通过页面设置和注册表对比,可以很清楚看到纸张大小和纵向/横向不被存入注册表。因此就有了引子里讲到的第3和第4种需求的区别,第3种需求是指不设置纸张大小和纵向/横向设置。第4种需求则多了这两项。

 

四、如何修改页面设置注册表

 

基于第3种需求,主要是修改注册表,javascript代码如下:

 

<script type="text/javascript">
    var hkey_root,hkey_path,hkey_key  
    hkey_root="HKEY_CURRENT_USER";
    hkey_path="\\Software\\Microsoft\\Internet Explorer\\PageSetup\\";
      //这个是用来设置打印页眉页脚的,你可以设置为空或者其它
      try{  
            var RegWsh = new ActiveXObject("WScript.Shell");
             
            hkey_key="header";
            RegWsh.RegWrite(hkey_root+hkey_path+hkey_key,"");
           
            hkey_key="footer";
            RegWsh.RegWrite(hkey_root+hkey_path+hkey_key,"");
      }catch(e){
      alert(e.description);
      }
</script>
 

 

五、 如何修改页面设置纵向/横向及纸张大小

 

能否不通过第三方的activeX,直接利用javascript直接修改这两个属性呢?在网上折腾了两天后,只找到一种办法,还是使用WScript.Shell,代码例子如下

 

<script type="text/javascript">
                   try{
var RegWsh = new ActiveXObject("WScript.Shell");
RegWsh.sendKeys('%fu');//按下Alt+F+U键
RegWsh.sendKeys('%a');//按下了ALT+A键
RegWsh.sendKeys('{ENTER}');//按下Enter键
}catch(e){
      alert(e.description);
}
</script>
 

 

在执行时,可以看到有弹出页面设置的界面然后保存关闭的过程。

如果大家有其他体验更好的解决方案,希望能补充。

 

六、用户体验带来的烦恼

 

1、以上不管是哪种方案,都会提示用户安全上的确认,如果我们的ActiveX是通过官方认证的,相对来说安全级别是较高的,大部分用户是能接受的。

2、而第四、五点的实现在一般用户的安全设置情况下,会报出错误提示”automation服务器不能创建对象

客户端可以通过以下三种办法排查:

1)、如果是Scripting.FileSystemObject (FSO 文本文件读写)被关闭了, 开启FSO功能即可,在“运行”中执行regsvr32 scrrun.dll即可。

2)、安全模式设置成“中”,如果javascript脚本中报这个错误,还应将IE的安全设置“不允许运行未标记为安全的activeX控件”启用即可。注意如果您将相应的网站设成“受信任的站点”, 必须对“受信任的站点”进行相应的IE安全设置,此时如果对“InternetIE设置将是徒劳的。

3)、有些脚本需要微软的 MSXML 控件才能进入。当使用 IE 5 以上版本的缺省安全模式时,会提示是否接受 MSXML 控件, 如果接受,MSXML 将自动安装到您的机器上(得等上几分钟) 如果自动安装不成功,可以自行下载和安装 MSXML 3.0 SP7。有时是由于msxml 3服务被关掉了,使用regsvr32 msxml3.dll即可。

但是这样的体验无疑是用户无法忍受的,除非你的系统是后台内部少数人使用的场景,即便客户端的设置不弹出错误提示”automation服务器不能创建对象,但第五点的实现会看到打开页面时,自动弹出页面设置窗口并自动关闭的过程,我想这样的体验也是用户所厌恶的。

 

七、令人不爽的折衷方案

 

         讲了这么多,可能还没讲清楚我到底想要个什么样的打印需求,再次描述:我们想要一个简单的页面打印,比如某个网页上有个打印按钮,然后点击打印,能自动设置好纸张大小、纵向/横向及其他页面设置元素,并直接打印出页面上某个对象(其他不打印的对象可以通过cssjs控制不被打印出来)。

     令人遗憾的是,通过以上的阐述,通过JavascriptWScript.Shell直接实现的方式,用户体验太差。放弃!

折衷方案一、降低需求标准,通过javascript调用Webbrowser弹出打印设置,让用户自行设置纵向/横向及其他设置后再打印。体验较差,我们在项目过程中,由于时间的原因,做为临时解决方案。

折衷方案二、采用ActiveX,一般第三方的打印控件比较大,而我们的第34种需求方案实际上非常简单,用不到一般商用的庞大复杂的报表功能,因此可以做个简单但够用的体积又很小的ActiveX控件是最好的解决方案。ActiveX控件,免不了客户端第一次打开时下载和信任确认问题,这是ActiveX都无法避免的问题,但这种方案完全满足了用户的需求,但ActiveX开发需要的时间多,正式签名等过程复杂。我们将在下个sprint中考虑采用ActiveX

 

八、发文目的

 

         因为花了我2天多时间,本想通过javascript来实现本文中简单的自动打印设置并打印(即本文所提到的第34种需求),结果引出了这一系列技术问题及用户体验问题,如果大家有更好的解决方案,请予以分享。如果有碰到我同样需求又需要做出技术选型的朋友,希望本文能让你有所参考少走弯路。

 

--董柏 于2011.11.15中午