Click here to Skip to main content
15,879,535 members
Articles / Programming Languages / C#
Tip/Trick

Setting Printer Paper Size From Silverlight Application

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
11 Mar 2013CPOL2 min read 22.5K   4   5
Tips to control printer setting without printdialog in Silverlight

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.

  1. Create Windows Form Control library in VS 2010.
  2. Create a class PrinterController. Mark it with ClassInterfaceAttribute,ComVisibleAttribute,ProgIdAttribute.
    C#
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    [ComVisible(true)]<
    [ProgId("PrinterController")]
    public class PrinterController
  3. Add the necessary methods inside this class which accept printer page settings.
    C#
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    [ComVisible(true)]
    [ProgId("PrinterController")]
    public class PrinterController 
    {
     	private PrintDocument doc;
    	private Image image;
    	private PaperSize paperSize;
    /// <summary>
    /// Initializes a new instance of the <see cref="PrinterController"/> class.
    /// </summary>
    public PrinterController()
    {
    	doc = new PrintDocument();
    	doc.PrintPage += new PrintPageEventHandler(doc_PrintPage); 
    	doc.EndPrint += new PrintEventHandler(doc_EndPrint); 
    }
    
    /// <summary>
    /// Handles the EndPrint event of the doc control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Drawing.Printing.PrintEventArgs"/> 
    /// instance containing the event data.</param>
    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;
    }
    
    /// <summary>
    /// Sets the size of the paper.
    /// </summary>
    /// <param name="paperSizeName">Name of the paper size.</param>
    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;
    }
    /// <summary>
    /// Sets the printing image.
    /// </summary>
    /// <param name="data">The data.</param>
    public void SetPrintingImage(byte[] data)
    {
    	using (MemoryStream stream = new MemoryStream())
    	{
    		stream.Write(data, 0, data.Length);
    		image = Image.FromStream(stream);
    	}
    }
    
    /// <summary>
    /// Prints this instance.
    /// </summary>
    public void Print()
    { 
    	doc.Print();
    }
    
    /// <summary>
    /// Handles the PrintPage event of the doc control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Drawing.Printing.PrintPageEventArgs"/> 
    /// instance containing the event data.</param>
    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);
    } 
    }
  4. Check Register for COM interop in project properties.
  5. Deploy this DLL on client machine using regasm tool.
    In Silverlight application, where printing is required, create PrinterController object using the following method:
    C#
    dynamic obj = AutomationFactory.CreateObject("PrintController")
  6. The Silverlight application uses this interop to set up papersize and printing as follows:
    C#
    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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionI'm getting an error: Failed to create an object instance for the specified ProgID Pin
JorgeEscobarP22-Jul-13 4:58
JorgeEscobarP22-Jul-13 4:58 
AnswerRe: I'm getting an error: Failed to create an object instance for the specified ProgID Pin
JorgeEscobarP29-Aug-13 14:04
JorgeEscobarP29-Aug-13 14:04 
Resolved the problem, the DLL must be signed so it can be instanciated from silverlight.
GeneralRe: I'm getting an error: Failed to create an object instance for the specified ProgID Pin
Member 105692743-Feb-14 11:26
Member 105692743-Feb-14 11:26 
AnswerRe: I'm getting an error: Failed to create an object instance for the specified ProgID Pin
denesh kumar26-Mar-14 18:48
denesh kumar26-Mar-14 18:48 
GeneralMy vote of 5 Pin
Nitin Sonawane11-Mar-13 20:49
Nitin Sonawane11-Mar-13 20:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.