Printing a Picture

Code samples and article discussion

Moderators: Frank Hileman, Anne Szyjan

Post Reply
User avatar
Frank Hileman
Site Admin
Posts: 1400
Joined: Sun Jul 25, 2004 8:16 pm
Location: California
Contact:

Printing a Picture

Post by Frank Hileman » Mon Mar 26, 2007 8:57 am

In the full version, use the Picture.RenderTo function to print. The Lite version has no printing support.

You will need code to initialize the transformation and clipping on the printer graphics. Here is a sample:

Printing Sample

Here is an extract from the above sample. PageSetup and Print are the entry methods:

Code: Select all

	public class PrintableCanvas : Canvas
	{
		private PrintDialog printDialog;
		private PrintDocument printDocument;
		private PageSetupDialog pageSetupDialog;

		public void PageSetup()
		{
			SetupPrintDocument();
			if (pageSetupDialog == null)
			{
				pageSetupDialog = new PageSetupDialog();
				pageSetupDialog.Document = printDocument;
			}
			pageSetupDialog.ShowDialog();
		}

		public void Print()
		{
			SetupPrintDocument();
			if (printDialog == null)
			{
				printDialog = new PrintDialog();
				printDialog.Document = printDocument;
			}
			if (printDialog.ShowDialog() != DialogResult.OK)
				return;
			printDocument.Print();
		}

		private void SetupPrintDocument()
		{
			if (printDocument == null)
			{
				printDocument = new PrintDocument();
				printDocument.PrintPage += new PrintPageEventHandler(PrintDocumentPrintPage);
			}
			// NOTE: you may use any document name instead of Picture.Name
			printDocument.DocumentName = Picture.Name;
		}

		private void PrintDocumentPrintPage(object sender, PrintPageEventArgs e)
		{
			e.HasMorePages = false;			// fit into a single page
			Graphics g = e.Graphics;
			FRectangle port;

			if (g.VisibleClipBounds.X < 0) // print preview
				port = e.MarginBounds;
			else
				port = new FRectangle(
					e.MarginBounds.Left - (e.PageBounds.Width - g.VisibleClipBounds.Width) / 2,
					e.MarginBounds.Top - (e.PageBounds.Height - g.VisibleClipBounds.Height) / 2,
					e.MarginBounds.Width, e.MarginBounds.Height);
			ScalingTranslation st = new ScalingTranslation(Picture.Bounds, port, true);
			Transformation old = Picture.Transformation;
			try
			{
				// make sure transformation reference is origin, or
				// calculations are broken
				Picture.TransformationReference = TransformationReference.Origin;
				Picture.ResetTransformation();
				Picture.TransformBy(st);
				Picture.RenderTo(g);
			}
			finally { Picture.Transformation = old; }
		}
	}
This code:

Code: Select all

ScalingTranslation st = new ScalingTranslation(Picture.Bounds, port, true);
centers the picture Bounds in the port.

Tips:
  • Use Stroke.Width of 1, not 0, if you wish to have a consistent line width. 0 means, "1 pixel" -- on a printer one pixel is far too small, and you may not see the line at all.
  • If you wish to print some other portion of the Picture, you will need to adjust the ScalingTranslation, st, in the code above. To print to a particular zoomed in area, assuming you have that area in the Picture child coordinate space, you substitute that rectangle for the Picture.Bounds in the ScalingTranslation calculation:

    Code: Select all

    ScalingTranslation st = new ScalingTranslation(zoomedArea, port, true); 
    You need to compute zoomedArea in the Picture child space. If you want that to be the visible area in the Canvas, take an FRectangle of (0, 0, canvas.Width, canvas.Height), use the Picture RectangleDeviceToChild method to convert that to child coordinates. That is the zoomedArea above.

Post Reply