打印基础知识
打印简介
在 ActionScript 3.0 中,可以使用 PrintJob 类来创建显示内容的快照以转换为打印输出中
的墨水和纸张表示形式。在某些方面,设置要打印的内容与设置在屏幕上显示的内容是相同
的;即可以放置元素和调整其大小以创建所需的布局。但是,打印具有某些特性,而使其不
同于屏幕布局。例如,打印机使用的分辨率不同于计算机显示器;计算机屏幕的内容是动态
的并且可能会发生变化,而打印的内容本身静态的;在准备进行打印时,您需要考虑固定纸
张大小的限制以及多页打印的可能性。
即使这些差异看起来是显而易见的,但在使用 ActionScript 设置打印时一定要记住这些不
同之处。由于精确打印取决于您指定的值和用户打印机特性的组合,因此,您可以使用
PrintJob 类中包含的属性来确定需要考虑的重要用户打印机特性。
常见打印任务
本章介绍了以下常见的打印任务:
■ 启动打印作业
■ 在打印作业中添加页面
■ 确定用户是否取消了打印作业
■ 指定是使用位图还是矢量呈现
■ 设置页面大小、缩放和方向
■ 指定可打印的内容区域
■ 将屏幕大小转换为页面大小
■ 打印多页打印作业
重要概念和术语
以下参考列表包含将会在本章中使用的重要术语:
■ 后台处理程序 (Spooler):操作系统或打印机驱动程序软件的一部分,用于在等待打印页
面时跟踪页面,并在打印机可用时将其发送到打印机。
■ 页面方向 (Page orientation):打印的内容相对于纸张的旋转角度:水平(横向)或垂直
(纵向)。
■ 打印作业 (Print job):组成单个打印输出的页面或页面集。
打印页面
使用 PrintJob 类的实例来处理打印。要通过 Flash Player 打印基本页面,请依次使用下面
四个语句:
■ new PrintJob():创建指定的打印作业名称的新实例。
■ PrintJob.start():为操作系统启动打印过程(系统将为用户调用打印对话框),并填
充打印作业的只读属性。
■ PrintJob.addPage():包含有关打印作业内容的详细信息,其中包括 Sprite 对象(及
其包含的任何子级) 、打印区域的大小以及打印机应将图像打印为矢量图形还是位图图
像。您可以使用对 addPage() 的连续调用,在多个页面上打印多个 sprite。
■ PrintJob.send():将页面发送到操作系统的打印机。
例如,一个非常简单的打印作业脚本如下所示(包括用于编译的 package、import 和 class
语句):
package
{
import flash.printing.PrintJob;
import flash.display.Sprite;
public class BasicPrintExample extends Sprite
{
var myPrintJob:PrintJob = new PrintJob();
var mySprite:Sprite = new Sprite();
public function BasicPrintExample()
{
myPrintJob.start();
myPrintJob.addPage(mySprite);
myPrintJob.send();
如果您出于任何原因而需要清除 PrintJob 对象的属性,请将 PrintJob 变量设置为 null
(如 myPrintJob = null 中所示)。
Flash Player 任务和系统打印
由于 Flash Player 向操作系统的打印接口调度页面,因此您应了解 Flash Player 和操作系统
自身的打印接口所管理的任务范围。Flash Player 可启动打印作业,读取打印机的部分页面设
置,将打印作业的内容传递给操作系统,并验证用户或系统是否已取消打印作业。其它过程
(例如显示特定于打印机的对话框、取消后台打印作业或报告打印机的状态)都由操作系统处
理。如果出现打印作业启动或格式设置问题,Flash Player 能够做出响应,但只能报告操作系
统打印接口的某些属性或条件。作为开发人员,您编写的代码应能响应这些属性或条件。
处理异常和返回值
您应检查在用户已取消打印作业的情况下,在执行 addPage() 和 send() 调用之前
PrintJob.start() 方法是否返回 true。一种在继续之前检查是否已取消这些方法的简单
途径是,将它们包含在 if 语句中,如下所示:
if (myPrintJob.start())
{
// 此处为 addPage() 和 send() 语句
}
如果 PrintJob.start() 为 true,即表示用户已选择 Print (或者 Flash Player 已启用
Print 命令),则可以调用 addPage() 和 send() 方法。
另外,为了帮助管理打印过程, Flash Player 现在对 PrintJob.addPage() 方法引发异常,
以便您可以捕获错误并向用户提供信息和选项。如果 PrintJob.addPage() 方法失败,则可
以调用其它函数或停止当前打印作业。您可以通过将 addPage() 调用嵌入 try..catch 语句
来捕获这些异常,如下例所示。在该例中,[params] 是指定实际打印内容的参数的占位符:
if (myPrintJob.start())
{
try
{
myPrintJob.addPage([params]);
}
catch (error:Error)
{
// 处理错误,
}
myPrintJob.send();
}
打印作业启动后,您就可以使用 PrintJob.addPage() 添加内容,并查看是否生成异常(例
如,如果用户已取消打印作业)。如果生成异常,则可以向 catch 语句添加逻辑,以便向用
户(或 Flash Player)提供信息和选项,或者可以停止当前打印作业。如果成功添加了页面,
则可以继续使用 PrintJob.send() 将页面发送到打印机。
如果 Flash Player 在将打印作业发送到打印机时遇到问题(例如,如果打印机处于脱机状
态),则也可以捕获该异常并向用户(或 Flash Player)提供信息或更多选项(例如显示消
息文本或在 Flash 动画中提供警告)。例如,您可以为 if..else 语句中的文本字段分配新
文本,如以下代码所示:
if (myPrintJob.start())
{
try
{
myPrintJob.addPage([params]);
}
catch (error:Error)
{
// 处理错误。
}
myPrintJob.send();
}
else
{
myAlert.text = "Print job canceled";
}
有关运行正常的示例,请参阅第625 页的“示例:缩放、裁剪和拼接”。
处理页面属性
用户在“打印”对话框中单击“确定”且 PrintJob.start() 返回 true 后,您就可以访问
由打印机设置定义的属性。这些设置包括纸张宽度、纸张高度(pageHeight 和 pageWidth)
以及纸张上内容的方向。由于这些设置属于打印机设置,不受 Flash Player 控制,因此您无
法更改这些设置;但是,您可以使用它们将发送到打印机的内容对齐以与当前设置匹配。有
关详细信息,请参阅第621 页的“设置大小、缩放和方向”。
设置矢量或位图呈现
您可以将打印作业手动设置为将每个页面在后台处理为矢量图形或位图图像。在某些情况
下,矢量打印相对于位图打印而言会生成更小的后台文件和效果更佳的图像。但是,如果您
的内容包含位图图像,并且您要保留任何 Alpha 透明度或色彩效果,则应将页面打印为位图
图像。另外,非 PostScript 打印机会自动将任何矢量图形转换为位图图像。您可以在
PrintJob.addPage() 的第三个参数中指定位图打印,方法是传递一个 PrintJobOptions 对
象并将 printAsBitmap 参数设置为 true,如下所示:
var options:PrintJobOptions = new PrintJobOptions();
options.printAsBitmap = true;
myPrintJob.addPage(mySprite, null, options);
如果没有指定第三个参数的值,打印作业将使用默认设置,即矢量打印。
为打印作业语句定时
与 ActionScript 的先前版本不同,ActionScript 3.0 未将 PrintJob 对象限定在单帧。然而,
由于在用户单击“打印”对话框中的“确定”按钮之后,操作系统会向用户显示打印状态信
息,所以应尽快调用 PrintJob.addPage() 和 PrintJob.send(),以将页面发送到后台处理
程序。如果到达包含 PrintJob.send() 调用的帧时发生延迟,将会延迟打印过程。
在 ActionScript 3.0 中,脚本超时限制为 15 秒。因此,打印作业序列中各个主要语句间的
时间间隔不能超过 15 秒。也就是说, 15 秒脚本超时限制适用于以下时间间隔:
■ PrintJob.start() 和第一个 PrintJob.addPage() 之间
■ PrintJob.addPage() 和下一个 PrintJob.addPage() 之间
■ 最后一个 PrintJob.addPage() 和 PrintJob.send() 之间
如果以上任何一个间隔时间超过了 15 秒,则对 PrintJob 实例的下一次 PrintJob.start()
调用将返回 false,并且对 PrintJob 实例的下一个 PrintJob.addPage() 将使 Flash Player
引发运行时异常。
设置大小、缩放和方向
第617 页的“打印页面”一节详细介绍了基本打印作业的步骤,此作业的输出直接反映了与
指定的 sprite 的屏幕大小和位置等效的打印。然而,打印机使用不同的分辨率进行打印,并
且可以具有对打印 sprite 的外观有不利影响的设置。
Flash Player 可以读取操作系统的打印设置,但请注意,这些属性是只读的:虽然可以响应
它们的值,但无法进行设置。例如,您可以查明打印机的页面大小设置,并调整内容以适当
该大小。您还可以确定打印机的边距设置和页面方向。为响应打印机设置,您最好指定打印
区域,调整屏幕的分辨率与打印机的磅度量单位之间的差异,或转换内容以符合用户打印机
的大小或方向设置。
为打印区域使用矩形
使用 PrintJob.addPage() 方法可以指定要打印的 sprite 的区域。第二个参数 printArea
为 Rectangle 对象的形式。您可以选择三种方法来提供该参数的值:
■ 创建一个具有特定属性的 Rectangle 对象,然后将该矩形用于 addPage() 调用,如下例
所示:
private var rect1:Rectangle = new Rectangle(0, 0, 400, 200);
myPrintJob.addPage(sheet, rect1);
■ 如果您尚未指定 Rectangle 对象,则可以在该调用本身内指定,如下例所示:
myPrintJob.addPage(sheet, new Rectangle(0, 0, 100, 100));
■ 如果您打算为 addPage() 调用中的第三个参数提供值,但不想指定矩形,则可以对第二
个参数使用 null,如下所示:
myPrintJob.addPage(sheet, null, options);
比较磅和像素
矩形的宽度和高度以像素为单位。打印机使用磅来作为打印的度量单位。磅的实际大小是固
定的(1/72 英寸),但是在屏幕上,像素的大小取决于特定屏幕的分辨率。像素和磅之间的
转换比率取决于打印机设置以及 sprite 是否经过缩放。一个 72 个像素宽的 sprite 在未经缩
放的情况下打印输出将为一英寸宽,这时,一磅等于一个像素,且与屏幕分辨率无关。
您可以使用以下换算公式将英寸或厘米转换为缇或磅(1 缇为 1/20 磅):
■1 磅= 1/72 英寸 = 20 缇
■1 英寸=72 磅= 1440 缇
■1 厘米= 567 缇
如果省略了 printArea 参数或错误地传递了该参数,将打印 sprite 的整个区域。
缩放
如果要在打印前对 Sprite 对象进行缩放,请在调用 PrintJob.addPage() 方法之前设置缩
放属性(请参阅第346 页的“处理大小和缩放对象”),并在打印后将它们重新设置为原
始值。Sprite 对象的缩放与 printArea 属性无关。也就是说,如果指定一个 50 x 50 个像
素的打印区域,则会打印 2500 个像素。如果对 Sprite 对象进行缩放,则同样会打印 2500
个像素,但按缩放后的大小打印 Sprite 对象。
有关示例,请参阅第625 页的“示例:缩放、裁剪和拼接”。
横向或纵向打印
由于 Flash Player 可以检测方向设置,因此,您可以在 ActionScript 中构建逻辑来调整内
容大小或旋转以响应打印机设置,如下例所示:
if (myPrintJob.orientation == PrintJobOrientation.LANDSCAPE)
{
mySprite.rotation = 90;
}
响应页面高度和宽度
使用类似于处理打印机方向设置的策略,可以读取页面高度和宽度设置,并通过将某些逻辑
嵌入 if 语句中来响应这些设置。下面的代码显示了一个示例:
if (mySprite.height > myPrintJob.pageHeight)
{
mySprite.scaleY = .75;
}
此外,还可以通过比较页面尺寸和纸张尺寸来确定页面的边距设置,如下例所示:
margin_height = (myPrintJob.paperHeight - myPrintJob.pageHeight) / 2;
margin_width = (myPrintJob.paperWidth - myPrintJob.pageWidth) / 2;
示例:多页打印
打印多页内容时,可以将每一页内容与不同的 sprite (本例中为 sheet1 和 sheet2)关联,
然后为每个 sprite 使用 PrintJob.addPage()。以下代码说明了这种方法:
package
{
import flash.display.MovieClip;
import flash.printing.PrintJob;
import flash.printing.PrintJobOrientation;
import flash.display.Stage;
import flash.display.Sprite;
import flash.text.TextField;
import flash.geom.Rectangle;
public class PrintMultiplePages extends MovieClip
{
private var sheet1:Sprite;
private var sheet2:Sprite;
public function PrintMultiplePages():void
{
init();
printPages();
}
private function init():void
{
sheet1 = new Sprite();
createSheet(sheet1, "Once upon a time...", {x:10, y:50, 80,
height:130});
sheet2 = new Sprite();
createSheet(sheet2, "There was a great story to tell, and it ended
quickly.\n\nThe end.", null);
}
private function createSheet(sheet:Sprite, str:String,
imgValue:Object):void
{
sheet.graphics.beginFill(0xEEEEEE);
sheet.graphics.lineStyle(1, 0x000000);
sheet.graphics.drawRect(0, 0, 100, 200);
sheet.graphics.endFill();
var txt:TextField = new TextField();
txt.height = 200;
txt.width = 100;
txt.wordWrap = true;
txt.text = str;
if (imgValue != null)
{
var img:Sprite = new Sprite();
img.graphics.beginFill(0xFFFFFF);
img.graphics.drawRect(imgValue.x, imgValue.y, imgValue.width,
imgValue.height);
img.graphics.endFill();
sheet.addChild(img);
}
sheet.addChild(txt);
}
private function printPages():void
{
var pj:PrintJob = new PrintJob();
var pagesToPrint:uint = 0;
if (pj.start())
{
if (pj.orientation == PrintJobOrientation.LANDSCAPE)
{
throw new Error("Page is not set to an orientation of
portrait.");
}
sheet1.height = pj.pageHeight;
sheet1.width = pj.pageWidth;
sheet2.height = pj.pageHeight;
sheet2.width = pj.pageWidth;
try
{
pj.addPage(sheet1);
pagesToPrint++;
}
catch (error:Error)
{
// 响应错误。
}
try
{
pj.addPage(sheet2);
pagesToPrint++;
}
catch (error:Error)
{
// 响应错误。
}
if (pagesToPrint > 0)
示
{
pj.send();
}
}
}
}
}
示例:缩放、裁剪和拼接
在某些情况下,为消除在屏幕上与打印纸张上的显示差异,打印显示对象时您可能需要调整
显示对象的大小(或其它属性) 。在打印之前调整显示对象的属性(例如使用 scaleX 和
scaleY 属性来调整)时,请注意,如果对象缩放的尺度超出了为打印区域定义的矩形,该对
象将被裁剪。页面打印完毕后,您可能还需要重置属性。
以下代码对 txt 显示对象的尺寸进行缩放(但不缩放绿色背景框),结果将按照指定矩形的
尺寸对文本字段进行裁剪。打印后,文本字段将返回到在屏幕上显示的原始大小。如果用户
从操作系统的“打印”对话框取消打印作业,Flash Player 中的内容将更改以警告用户作业
已取消。
package
{
import flash.printing.PrintJob;
import flash.display.Sprite;
import flash.text.TextField;
import flash.display.Stage;
import flash.geom.Rectangle;
public class PrintScaleExample extends Sprite
{
private var bg:Sprite;
private var txt:TextField;
public function PrintScaleExample():void
{
init();
draw();
printPage();
}
private function printPage():void
{
var pj:PrintJob = new PrintJob();
txt.scaleX = 3;
txt.scaleY = 2;
if (pj.start())
{
trace(">> pj.orientation: " + pj.orientation);
trace(">> pj.pageWidth: " + pj.pageWidth);
trace(">> pj.pageHeight: " + pj.pageHeight);
trace(">> pj.paperWidth: " + pj.paperWidth);
trace(">> pj.paperHeight: " + pj.paperHeight);
try
{
pj.addPage(this, new Rectangle(0, 0, 100, 100));
}
catch (error:Error)
{
// 不执行任何操作。
}
pj.send();
}
else
{
txt.text = "Print job canceled";
}
// 重置 txt 缩放属性。
txt.scaleX = 1;
txt.scaleY = 1;
}
private function init():void
{
bg = new Sprite();
bg.graphics.beginFill(0x00FF00);
bg.graphics.drawRect(0, 0, 100, 200);
bg.graphics.endFill();
txt = new TextField();
txt.border = true;
txt.text = "Hello World";
}
private function draw():void
{
addChild(bg);
addChild(txt);
txt.x = 50;
txt.y = 50;
}
}
}
成功示例
private var pj:PrintJob; private var sp:Sprite; private function onPrint(evt:MouseEvent):void { //打印 var _model:MdImageMenu = ContentSwf.LinkContentSwf.theModel as MdImageMenu; var _displayObjectLoader:DisplayObjectLoader = _model.displayObjectLoader; pj = new PrintJob(); if(_model.conType == "img") { var _oldBitMpa:Bitmap = _displayObjectLoader.rawContent as Bitmap; var _newBitmap:Bitmap = new Bitmap(_oldBitMpa.bitmapData); sp = new Sprite(); sp.addChild(_newBitmap); } else if(_model.conType == "swf") { var _mc:MovieClip = _displayObjectLoader.rawContent as MovieClip; var _bitmapData:BitmapData = new BitmapData(_mc.width, _mc.height); _bitmapData.draw(_mc); var _newBitMap:Bitmap = new Bitmap(_bitmapData); sp = new Sprite(); sp.addChild(_newBitMap); } else { return; } if(pj.start()) { switch(pj.orientation) { case PrintJobOrientation.LANDSCAPE://水平 sp.height = sp.height; sp.width = sp.height*(5/3); break; case PrintJobOrientation.PORTRAIT://垂直 sp.width = pj.pageWidth; sp.height = sp.width*(3/5); break; } try { pj.addPage(sp); } catch(error:Error) { //错误 return; } pj.send(); } }