Introduction
Consider a drawing tool written in Silverlight, which accepts the paper size of the drawing area (e.g. A3). At the time of printing, many times users do not want to change the default printer setting again as they already provided paper size for drawing area and now they need to use this size for paper-size of printer (A3 which is set by user). User wants application to change the printer setting according to drawing area paper-size. Hiding interaction of user with PrintDialog
and allow the "Silent" printing experience in Silverlight involves security risk.
Background
Silverlight provides its own PrintDocument
class for printing, though it does not allow access to printer setting such as paper size, margin, etc. After calling Print
method of PrintDocument
, Silverlight opens PrintDialogBox
, which asks user for document setting.
Sometimes users do not want to interact with PrintDialog
. User wants application to set the default paper size and print the document. This requirement is not straight forward in Silverlight, and requires some work around. From trusted Silverlight application, we can call COM InterOp DLL to achieve this.
The article explains how to print in Silverlight without PrintDialog
and set paper size automatically.
Using the Code
The below code creates a C# COM-InterOp library which exposes Print
method and SetPaperSize
method. Print
method prints the document; SetPaperSize
sets the default paper size for the document. The class accepts byte array of an image to be printed, you can pass byte array of WritableBitmap
here.
The simple steps shown below instruct how to create, deploy and use the COM-interop library from Silverlight.
- Create Windows Form Control library in VS 2010.
- Create a class
PrinterController
. Mark it with ClassInterfaceAttribute
,ComVisibleAttribute
,ProgIdAttribute
.
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]<
[ProgId("PrinterController")]
public class PrinterController
- Add the necessary methods inside this class which accept printer page settings.
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]
[ProgId("PrinterController")]
public class PrinterController
{
private PrintDocument doc;
private Image image;
private PaperSize paperSize;
public PrinterController()
{
doc = new PrintDocument();
doc.PrintPage += new PrintPageEventHandler(doc_PrintPage);
doc.EndPrint += new PrintEventHandler(doc_EndPrint);
}
void doc_EndPrint(object sender, PrintEventArgs e)
{
doc.PrintPage -= new PrintPageEventHandler(doc_PrintPage);
doc.EndPrint -= new PrintEventHandler(doc_EndPrint);
image.Dispose();
doc.Dispose();
}
public void IsLandScapeMode(bool islandscape)
{
doc.DefaultPageSettings.Landscape = islandscape;
doc.PrinterSettings.DefaultPageSettings.Landscape = islandscape;
}
public void SetPaperSize(string paperSizeName)
{
paperSize = doc.PrinterSettings.PaperSizes.Cast<PaperSize>().FirstOrDefault
(a => a.PaperName.Equals(paperSizeName,
StringComparison.InvariantCultureIgnoreCase));
if(paperSize==null)
throw new ArgumentException(string.Format
("Papersize {0} not found.",paperSizeName));
doc.DefaultPageSettings.PaperSize = paperSize;
doc.PrinterSettings.DefaultPageSettings.PaperSize = paperSize;
}
public void SetPrintingImage(byte[] data)
{
using (MemoryStream stream = new MemoryStream())
{
stream.Write(data, 0, data.Length);
image = Image.FromStream(stream);
}
}
public void Print()
{
doc.Print();
}
void doc_PrintPage(object sender, PrintPageEventArgs e)
{
e.PageSettings.PaperSize = paperSize;
e.PageSettings.PrinterSettings.DefaultPageSettings.PaperSize = paperSize;
e.Graphics.DrawImage(image, doc.PrinterSettings.DefaultPageSettings.Bounds);
}
}
- Check Register for COM interop in project properties.
- Deploy this DLL on client machine using regasm tool.
In Silverlight application, where printing is required, create PrinterController
object using the following method:
dynamic obj = AutomationFactory.CreateObject("PrintController")
- The Silverlight application uses this interop to set up papersize and printing as follows:
dynamic obj = AutomationFactory.CreateObject("PrinterController");
ImageTools.Image image = this.ToImage();
StreamWriter reader = new StreamWriter(()
using (MemoryStream stream = new MemoryStream())
{
IImageEncoder encoder = Encoders.GetAvailableEncoders().FirstOrDefault();
encoder.Encode(image, stream);
byte[] array = new byte[stream.Length];
stream.Position = 0;
stream.Read(array, 0, array.Length);
obj.SetPrintingImage(array);
obj.SetPaperSize("A3");
}
obj.Print();
By extending this example further, you can create your own PrintDialog
in Silverlight and handle printing through it.