Monday, July 7, 2008

A simple Flex print button

Recently i am working on a Flex project that i have created a simple print button in order to simply print my flash movie into one single A4 paper. It sounds interesting at first coz no one would think about to print a "moving" picture. However as the project requests, i have to make this possible and make it as simple as possible.

Straight to the code. Firstly i create a simple "PrintButton" that extends the existing UI button and also with a printing function.


package jiang.example {
import flash.events.MouseEvent;
import mx.controls.Button;
import mx.core.UIComponent;
import mx.printing.FlexPrintJob;
import mx.printing.FlexPrintJobScaleType;

public class PrintButton extends Button {
//component attributes
public var component:UIComponent;
public var paper:String;

public function PrintButton():void {
super();
addEventListener(MouseEvent.CLICK, printJobInvocation);
}

// Define private click event handler.
private function printJobInvocation(event:MouseEvent):void {
var printJob:FlexPrintJob = new FlexPrintJob();

//Start the print job
if (printJob.start() != true) return;

if(paper == "OnePage") {
printJob.addObject(component,
FlexPrintJobScaleType.SHOW_ALL);
}
else if(paper == "FillPage") {
printJob.addObject(component,
FlexPrintJobScaleType.FILL_PAGE);
}
else if(paper == "MatchHeight") {
printJob.addObject(component,
FlexPrintJobScaleType.MATCH_HEIGHT);
}
else if(paper == "MatchWidth") {
printJob.addObject(component,
FlexPrintJobScaleType.MATCH_WIDTH);
}
else if(paper == "None") {
printJob.addObject(component,
FlexPrintJobScaleType.NONE);
}
//default print paper setting
else {
printJob.addObject(component,
FlexPrintJobScaleType.SHOW_ALL);
}

//output to hardware
printJob.send();
}
}
}


This simple class can be compiled in both Flex 2 and 3. Put it into the right folder. Next in my simple MXML application,


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
xmlns:="jiang.example.*"
backgroundGradientColors="[#ffffff, #ffffff]"
backgroundColor="#FFFFFF">
<mx:VBox>
<mx:VBox id="Template_box" verticalGap="0" ...>
... ... ...
</mx:VBox>
<mx:Spacer height="15"/>
<PrintButton component="{this.Template_box}"
label="Print" borderColor="#000000" fillAlphas="[1.0, 1.0]"
fillColors="[#FFFFFF, #FFFFFF, #FFFFFF, #D6F5D1]"/>
</mx:VBox>
</mx:Application>

Remember one thing before you try this little application. Click Flex's "Project" in the menu bar, and then "Properties", and then click "Flex Compiler" in the left-hand menu, add -default-background-color #FFFFFF (look out the space) to the compiler arguments. This argument will set the application's default color from haloblue to white. Also notice that i have used backgroundColor="#FFFFFF" in my Application tag, this one also helps me to change the default color to white.

Turn back to my PrintButton tag, it takes two cousmized attributes:
  1. component: takes any UIComponent that you want to print, e.g. VBox, button, textarea etc.
  2. paper: tell printer how you want to print it, in one page, multiple page?
My upper example print the "Template_box" component and all its children and it print all of them in one paper (shirk it if its too large). This button can also works with dynamic contents: it will print whatever Template_box has in the screen when you click it. So if your mxml has some runtime WYSIWYG functions, it also works.

However, i found a very annoy problem: the damn halo blue color. I have to set up all parent Boxes to have backgroudcolor = #FFFFFF, otherwise it will print halo blue as the default background color for Box component. I hope i can find an easy and possible solution for this soon.

3 comments:

Harry LAI said...

I love this print button! I wonder how to set the page not to refresh when I hit the print button. I wish I could borrow that knowlege from you. Thanks.

yijia l.

Monali said...

Hi,

In this post I found exactly what I was looking for.

Thanks a lot!


Thanks!
Monali

Meenu said...

Hi,

Seems to be a nice sample.But i would like to know if we can get output that spans multiple pages even if we have components like trees or datagrids within the vbox.

Thanks,
Meenakshi