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();
}
}
}
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();
}
}
}