Click to See Complete Forum and Search --> : How to obtain the correct print preview image size


sylvainboisse@hotmail.com
November 23rd, 2008, 08:48 PM
I am trying to implement my own print preview using the PreviewPrintController class. However I cannot figure out how to correctly interpret the metafile obtained from it after calling Print() as its image size and the portion of the image that has been used in it don't seem to make any sense.

Copying and pasting the following code into a new C# console application project will reproduce my issue.

First, the metafile size approaches 5100 by 6600, which seems to correspond to inches multiplied by dpi (a 8.5x11 paper size with 600 dots per inch).

When printing, the graphics size and bounds are expressed in a totally different way (the size is 850 by 1100 instead of the above dimensions). If I draw a fullpage rectangle using page bounds, the resulting meta file does not end up with a full page rectangle. It only covers a small portion of the image, on the top left corner.

What I want is to obtain an image where the page bounds will fit exactly with the image size.


using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Runtime.InteropServices;

namespace PrintPreview
{
public class PreviewPrinter
{
public PreviewPrinter()
{
mPreviewPrintController = new PreviewPrintController();
mPrintDocument = new PrintDocument();
mPrintDocument.PrintController = mPreviewPrintController;

mPrintDocument.PrintPage += new PrintPageEventHandler(mPrintDocument_PrintPage);
}

public Image GetPrintPreview()
{
mPrintDocument.Print();

mMetafile = mPreviewPrintController.GetPreviewPageInfo()[0].Image as Metafile;

Graphics.EnumerateMetafileProc enumerateDelegate = new Graphics.EnumerateMetafileProc(EnumerateMetafile);

Bitmap printPreview = new Bitmap(mMetafile.Width, mMetafile.Height, PixelFormat.Format32bppArgb);
using (Graphics graphics = Graphics.FromImage(printPreview))
{
graphics.Clear(Color.White);
graphics.EnumerateMetafile(mMetafile, new Point(0, 0), enumerateDelegate);
}

return printPreview;
}

private bool EnumerateMetafile(EmfPlusRecordType recordType, int flags, int dataSize, IntPtr data, PlayRecordCallback callbackData)
{
byte[] dataArray = null;
if (data != IntPtr.Zero)
{
dataArray = new byte[dataSize];
Marshal.Copy(data, dataArray, 0, dataSize);
}

mMetafile.PlayRecord(recordType, flags, dataSize, dataArray);

return true;
}

private void mPrintDocument_PrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.FillRectangle(Brushes.Yellow, e.PageBounds);
e.Graphics.FillRectangle(Brushes.LightBlue, e.MarginBounds);
e.Graphics.DrawRectangle(new Pen(Brushes.Red), e.PageBounds);
}

PrintDocument mPrintDocument;
PreviewPrintController mPreviewPrintController;
Metafile mMetafile;
}

class Program
{
static void Main(string[] args)
{
foreach (string printerName in PrinterSettings.InstalledPrinters)
Console.WriteLine("Printer: " + printerName);

PreviewPrinter previewPrinter = new PreviewPrinter();
Image printtPreview = previewPrinter.GetPrintPreview();

printtPreview.Save("C:/test.jpg");

Console.WriteLine("Press a key to continue.");
Console.ReadKey();
}
}
}

sylvainboisse@hotmail.com
November 23rd, 2008, 09:00 PM
I also tried creating the bitmap for rendering the meta file using the following instead of what is being done in the code of the previous post:


Bitmap printPreview = new Bitmap(
(int) (mMetafile.Width / mMetafile.HorizontalResolution * 100),
(int) (mMetafile.Height / mMetafile.VerticalResolution * 100),
PixelFormat.Format32bppArgb);


Doing so creates an image of 850 by 1100 pixels. When drawing the meta file in it, I can see the bounds do not fit exactly the image size as I can see a white space at the bottom and at the right of the image that is not supposed to be there.

Any idea?

sylvainboisse@hotmail.com
November 23rd, 2008, 09:38 PM
Found it, I had to set the resolution on the printPreview bitmap using the following call:


printPreview.SetResolution(mMetafile.HorizontalResolution, mMetafile.VerticalResolution);


The pixels still do not match perfectly though. The border is missing on the bottom of the page and there is a small white line of pixels on the right, suggesting there is a tiny error of precision somewhere or something.