/// <summary> /// Adds a new metafile page, selects it as the current metafile, and /// returns its graphics object. The caller is responsible for disposing /// the returned Graphics instance. The unit of measurement in the /// returned Graphics instance is GraphicsUnit.Inch. /// </summary> /// <param name="pageSize">The size of the page, in inches.</param> /// <returns>a Graphics instance to render the page onto; the caller is /// responsible for disposing of this Graphics instance</returns> protected Graphics GetNextPage(SizeF pageSize) { IntPtr deviceContextHandle; Graphics offScreenBufferGraphics; Graphics metafileGraphics; MetafileHeader metafileHeader; KeyValuePair<Metafile, MemoryStream> pair; this.currentStream = new MemoryStream(); using (offScreenBufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero)) { deviceContextHandle = offScreenBufferGraphics.GetHdc(); this.currentMetafile = new Metafile( this.currentStream, deviceContextHandle, new RectangleF(0, 0, pageSize.Width, pageSize.Height), MetafileFrameUnit.Inch, EmfType.EmfOnly); pair = new KeyValuePair<Metafile, MemoryStream>( this.currentMetafile, this.currentStream); this.metafiles.Add(pair); offScreenBufferGraphics.ReleaseHdc(); metafileGraphics = Graphics.FromImage(this.currentMetafile); metafileHeader = this.currentMetafile.GetMetafileHeader(); metafileGraphics.ScaleTransform( metafileHeader.DpiX / metafileGraphics.DpiX, metafileHeader.DpiY / metafileGraphics.DpiY); metafileGraphics.PageUnit = GraphicsUnit.Inch; metafileGraphics.SetClip(new RectangleF(0, 0, pageSize.Width, pageSize.Height)); } return metafileGraphics; }/// <summary> /// Prints the given document. /// </summary> /// <param name="document">the document, which is guaranteed not to be /// null in and in a language that the printer supports</param> /// <param name="copies">the number of copies, which is guaranteed to be /// a positive number</param> protected override void DoPrint(PrinterDocumentBase document, int copies) { IntPtr deviceContext; NativeMethods.DOCINFO documentInfo; int hardMarginLeft; int hardMarginTop; int pagesCount; documentInfo = new NativeMethods.DOCINFO(); documentInfo.fwType = 0; documentInfo.lpszDatatype = null; documentInfo.lpszDocName = document.Name; documentInfo.lpszOutput = null; documentInfo.cbSize = Marshal.SizeOf(documentInfo); pagesCount = document.Prepare(); deviceContext = NativeMethods.CreateDC( "WINSPOOL", this.Name.Normalize(), null, IntPtr.Zero); if (deviceContext != IntPtr.Zero) { hardMarginLeft = NativeMethods.GetDeviceCaps( deviceContext, NativeMethods.DeviceCap.PHYSICALOFFSETX); hardMarginTop = NativeMethods.GetDeviceCaps( deviceContext, NativeMethods.DeviceCap.PHYSICALOFFSETY); hardMarginLeft = (int)(hardMarginLeft * 100F / NativeMethods.GetDeviceCaps(deviceContext, NativeMethods.DeviceCap.LOGPIXELSX)); hardMarginTop = (int)(hardMarginTop * 100F / NativeMethods.GetDeviceCaps(deviceContext, NativeMethods.DeviceCap.LOGPIXELSY)); for (int copyIdx = 0; copyIdx < copies; ++copyIdx) { if (NativeMethods.StartDoc(deviceContext, documentInfo) > 0) { for (int i = 0; i < pagesCount; ++i) { byte[] data; data = document.GetPage(i); using (var ms = new MemoryStream(data)) using (var metafile = Metafile.FromStream(ms)) { using (var g = Graphics.FromHdcInternal(deviceContext)) { g.TranslateTransform(-hardMarginLeft, -hardMarginTop); if (NativeMethods.StartPage(deviceContext) > 0) { g.DrawImage(metafile, 0, 0); g.Flush(); if (NativeMethods.EndPage(deviceContext) <= 0) { throw new Win32Exception(); } } else { throw new Win32Exception(); } } } } if (NativeMethods.EndDoc(deviceContext) <= 0) { throw new Win32Exception(); } } } } else { throw new Win32Exception(); } if (deviceContext != IntPtr.Zero) { NativeMethods.DeleteDC(deviceContext); } }