Print active view
.PrintActiveViewCS_Net\PrintActiveViewCS_Net.cs
// Copyright 2006 ESRI
//
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
//
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
//
// See the use restrictions.
//
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Drawing.Printing;
using System.Diagnostics;
using ESRI.ArcGIS.ADF.BaseClasses;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.SystemUI;
using System.Collections;
using System.Windows.Forms;
namespace PrintActiveViewCS_Net
{
/// <summary>
/// PrintActiveViewCS_Net creates a command which will print the active view to the default printer's default page.
/// </summary>
[Guid("c18e5cf0-7a6f-484e-ae25-bea6559072e1")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("PrintActiveViewCS_Net.PrintActiveViewCS_Net")]
public sealed class PrintActiveViewCS_Net : BaseCommand
{
#region COM Registration Function(s)
[ComRegisterFunction()]
[ComVisible(false)]
static void RegisterFunction(Type registerType)
{
// Required for ArcGIS Component Category Registrar support
ArcGISCategoryRegistration(registerType);
//
// TODO: Add any COM registration code here
//
}
[ComUnregisterFunction()]
[ComVisible(false)]
static void UnregisterFunction(Type registerType)
{
// Required for ArcGIS Component Category Registrar support
ArcGISCategoryUnregistration(registerType);
//
// TODO: Add any COM unregistration code here
//
}
#region ArcGIS Component Category Registrar generated code
/// <summary>
/// Required method for ArcGIS Component Category registration -
/// Do not modify the contents of this method with the code editor.
/// </summary>
private static void ArcGISCategoryRegistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
MxCommands.Register(regKey);
ControlsCommands.Register(regKey);
}
/// <summary>
/// Required method for ArcGIS Component Category unregistration -
/// Do not modify the contents of this method with the code editor.
/// </summary>
private static void ArcGISCategoryUnregistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
MxCommands.Unregister(regKey);
ControlsCommands.Unregister(regKey);
}
#endregion
#endregion
/* GDI callback to GetDeviceCaps and CreateDC function */
[DllImport("GDI32.dll")]
public static extern int GetDeviceCaps(int hdc, int nIndex);
[DllImport("GDI32.dll")]
public static extern int CreateDC(string strDriver, string strDevice, string strOutput, IntPtr pData);
[DllImport("User32.dll")]
public static extern int ReleaseDC(int hWnd, int hDC);
/* reference to the application itself */
IHookHelper m_hookHelper;
public PrintActiveViewCS_Net()
{
base.m_category = "Developer Samples";
base.m_caption = "Print Active View CSharp.NET";
base.m_message = "Prints the Active View to DEFAULT printer with CSharp.Net";
base.m_toolTip = "Print Active View CSharp.NET";
base.m_name = base.m_category + "_" + base.m_caption;
try
{
// the bitmap for the tool's icon
string bitmapResourceName = GetType().Name + ".bmp";
base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");
}
}
#region Overriden Class Methods
/// <summary>
/// Occurs when this command is created
/// </summary>
/// <param name="hook">Instance of the application</param>
public override void OnCreate(object hook)
{
if (m_hookHelper == null)
m_hookHelper = new HookHelperClass();
m_hookHelper.Hook = hook;
}
/// <summary>
/// Occurs when this command is clicked
/// </summary>
public override void OnClick()
{
PrintActiveViewParameterized(3);
}
#endregion
public void PrintActiveViewParameterized(long iResampleRatio)
{
/* Prints the Active View of the document to selected output format. */
//
IActiveView docActiveView = m_hookHelper.ActiveView;
IPrinter docPrinter;
long iPrevOutputImageQuality;
IOutputRasterSettings docOutputRasterSettings;
tagRECT deviceRECT;
IPaper docPaper;
/* printdocument is from the .NET assembly system.drawing.printing */
System.Drawing.Printing.PrintDocument sysPrintDocumentDocument;
short iNumPages;
IEnvelope docPrinterBounds;
IEnvelope VisibleBounds;
docPrinterBounds = new EnvelopeClass();
VisibleBounds = new EnvelopeClass();
// save the previous output image quality, so that when the export is complete it will be set back.
docOutputRasterSettings = docActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
iPrevOutputImageQuality = docOutputRasterSettings.ResampleRatio;
SetOutputQuality(docActiveView, iResampleRatio);
/* Now we need to get the default printer name. Since this is a generic command,
* we can't use the printername property of the document. So instead, we use the
* System.Drawing.Printing objects to find the default printer.
*/
docPrinter = new EmfPrinterClass();
sysPrintDocumentDocument = new System.Drawing.Printing.PrintDocument();
docPaper = new PaperClass();
/* testing to see if printer instantiated in sysPrintDocumentDocument is the
* default printer. It SHOULD be, but this is just a reality check.
*/
bool isDefault = sysPrintDocumentDocument.PrinterSettings.IsDefaultPrinter;
if (isDefault)
{
//Set docPaper's printername to the printername of the default printer
docPaper.PrinterName = sysPrintDocumentDocument.PrinterSettings.PrinterName;
}
else
{
//if we get an unexpected result, return.
MessageBox.Show("Error getting default printer info, exiting...");
return;
}
//make sure the paper orientation is set to the orientation matching the current view.
docPaper.Orientation = m_hookHelper.PageLayout.Page.Orientation;
/* Now assign docPrinter the paper and with it the printername. This process is two steps
* because you cannot change an IPrinter's printer except by passing it as a part of
* the IPaper. That's why we setup docPrinter.Paper.PrinterName first.
*/
docPrinter.Paper = docPaper;
//set the spoolfilename (this is the job name that shows up in the print queue)
docPrinter.SpoolFileName = "PrintActiveViewSample";
// Get the printer's hDC, so we can use the Win32 GetDeviceCaps fuction to
// get Printer's Physical Printable Area x and y margins
int hInfoDC;
hInfoDC = CreateDC(docPrinter.DriverName, docPrinter.Paper.PrinterName, "", IntPtr.Zero);
// Find out how many printer pages the output will cover.
if (m_hookHelper.ActiveView is IPageLayout)
{
m_hookHelper.PageLayout.Page.PrinterPageCount(docPrinter, 0, out iNumPages);
}
else
{
iNumPages = 1;
}
for (short lCurrentPageNum = 0; lCurrentPageNum < iNumPages; lCurrentPageNum++)
{
m_hookHelper.PageLayout.Page.GetDeviceBounds(docPrinter, lCurrentPageNum, 0, docPrinter.Resolution, docPrinterBounds);
//Transfer PrinterBounds envelope, offsetting by PHYSICALOFFSETX
// the Win32 constant for PHYSICALOFFSETX is 112
// the Win32 constant for PHYSICALOFFSETY is 113
deviceRECT.bottom = (int)(docPrinterBounds.YMax - GetDeviceCaps(hInfoDC, 113));
deviceRECT.left = (int)(docPrinterBounds.XMin - GetDeviceCaps(hInfoDC, 112));
deviceRECT.right = (int)(docPrinterBounds.XMax - GetDeviceCaps(hInfoDC, 112));
deviceRECT.top = (int)(docPrinterBounds.YMin - GetDeviceCaps(hInfoDC, 113));
// Transfer offsetted PrinterBounds envelope back to the deviceRECT
docPrinterBounds.PutCoords(0, 0, deviceRECT.right - deviceRECT.left, deviceRECT.bottom - deviceRECT.top);
if (m_hookHelper.ActiveView is IPageLayout)
{
//get the visible bounds for this layout, based on the current page number.
m_hookHelper.PageLayout.Page.GetPageBounds(docPrinter, lCurrentPageNum, 0, VisibleBounds);
}
else
{
//if it's not a page layout, export whatever's on screen at the printer's dpi.
//get the page
IPage pPage;
pPage = m_hookHelper.PageLayout.Page;
//get paper object
docPaper = docPrinter.Paper;
if (docPaper == null)
{
MessageBox.Show("no paper defined");
return;
}
//create an envelope for the bounds of the printer's page size in device units.
IEnvelope pDeviceFrame;
pDeviceFrame = new EnvelopeClass();
pPage.GetDeviceBounds(docPrinter, 1, 0, docPrinter.Resolution, pDeviceFrame);
//create and populate an envelope with the bounds of the printer page.
WKSEnvelope wksdevice;
pDeviceFrame.QueryWKSCoords(out wksdevice);
//transfer the envelope to the deviceRECT.
deviceRECT.left = (int)Math.Round(wksdevice.XMin);
deviceRECT.top = (int)Math.Round(wksdevice.YMin);
deviceRECT.right = (int)Math.Round(wksdevice.XMax);
deviceRECT.bottom = (int)Math.Round(wksdevice.YMax);
//since this is a data view, not a pagelayout, we don't need VisibleBounds, so set it to NULL.
VisibleBounds = null;
}
//Here's where the printing actually begins:
//==========================================
//The docPrinter.StartPrinting method returns the hDC of the printer, which we then
//use as the hDC parameter of activeview.output. ActiveView.Output is the function that
//draws the content on the active view, at the specified resolution, to the deviceRECT specified.
//VisibleBounds can be null, which means "print the active view", or can be set to a zoom extent.
if (iNumPages == 1)
{
VisibleBounds = null;
}
m_hookHelper.ActiveView.Output(docPrinter.StartPrinting(docPrinterBounds, 0), docPrinter.Resolution, ref deviceRECT, VisibleBounds, null);
//here we call FinishPrinting, which actually flushes the output to the printer.
docPrinter.FinishPrinting();
//now set the output quality back to the previous output quality.
SetOutputQuality(docActiveView, iPrevOutputImageQuality);
}
//release the DC...
ReleaseDC(0, hInfoDC);
}
private void SetOutputQuality(IActiveView docActiveView, long iResampleRatio)
{
/* This function sets OutputImageQuality for the active view. If the active view is a pagelayout, then
* it must also set the output image quality for EACH of the Maps in the pagelayout.
*/
IGraphicsContainer docGraphicsContainer;
IElement docElement;
IOutputRasterSettings docOutputRasterSettings;
IMapFrame docMapFrame;
IActiveView tmpActiveView;
if (docActiveView is IMap)
{
docOutputRasterSettings = docActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
docOutputRasterSettings.ResampleRatio = (int)iResampleRatio;
}
else if (docActiveView is IPageLayout)
{
//assign ResampleRatio for PageLayout
docOutputRasterSettings = docActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
docOutputRasterSettings.ResampleRatio = (int)iResampleRatio;
//and assign ResampleRatio to the Maps in the PageLayout
docGraphicsContainer = docActiveView as IGraphicsContainer;
docGraphicsContainer.Reset();
docElement = docGraphicsContainer.Next();
while (docElement != null)
{
if (docElement is IMapFrame)
{
docMapFrame = docElement as IMapFrame;
tmpActiveView = docMapFrame.Map as IActiveView;
docOutputRasterSettings = tmpActiveView.ScreenDisplay.DisplayTransformation as IOutputRasterSettings;
docOutputRasterSettings.ResampleRatio = (int)iResampleRatio;
}
docElement = docGraphicsContainer.Next();
}
docMapFrame = null;
docGraphicsContainer = null;
tmpActiveView = null;
}
docOutputRasterSettings = null;
}
}
}