4 votos

¿Qué API debemos utilizar para imprimir un PageLayout?

Estamos construyendo una aplicación independiente de ArcGIS Engine y vamos a añadir soporte para la impresión.

Hay varias APIs para imprimir un PageLayout en ArcObjects, en ArcGIS 10 hay al menos tres formas diferentes de hacerlo:

¿Puede alguien dar recomendaciones sobre qué API deberíamos elegir? ¿Hay algún problema conocido en estas APIs?

Actualización: Encontré una trampa durante mi investigación:

  • Cuando se trabaja con capas de ArcGIS Server, sólo PrintAndExport dibuja los parches/muestras en la leyenda al imprimir el diseño.

18voto

Isaac Solomon Puntos 16554

Este es el resultado de mi propia investigación del método PrintAndExport, Esto parece ser una otra envoltura de IOutput hecha por ESRI para apoyar Páginas basadas en datos .

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    'Customization of this sample
    'http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/Sample_Print_active_view/0001000002ms000000/
    Private Sub PrintActiveViewVB(ByVal iResampleRatio As Integer)

        '  Prints the Active View of the document to selected output format. 

        Dim docActiveView As IActiveView = m_hookHelper.ActiveView
        Dim docPrinter As IPrinter
        Dim PrintAndExport As IPrintAndExport = New PrintAndExport
        Dim docPaper As IPaper
        Dim sNameRoot As String

        Dim iNumPages As Short
        Dim sysPrintDocument As System.Drawing.Printing.PrintDocument

        ' assign the output filename.  
        sNameRoot = "PrintActiveViewVBSample"

        docPrinter = New EmfPrinter()

        'sets default values in print dialog
        Dim PrintDialog1 As PrintDialog = New PrintDialog()

        'Show print dialog
        Dim res As System.Windows.Forms.DialogResult = PrintDialog1.ShowDialog()
        If res = DialogResult.Cancel Then
            Return
        End If

        sysPrintDocument = New System.Drawing.Printing.PrintDocument()
        docPaper = New Paper()
        docPaper.Attach(PrintDialog1.PrinterSettings.GetHdevmode().ToInt32(), PrintDialog1.PrinterSettings.GetHdevnames().ToInt32())

        'make sure the paper orientation is set to the orientation matching the current view.
        docPaper.Orientation = m_hookHelper.PageLayout.Page.Orientation

        'assing docPrinter's paper.  We have to do this in two steps because you cannot change a 
        'printers' paper after it's assigned.  That's why we set docPaper.PrinterName first.
        docPrinter.Paper = docPaper

        'set the spoolfilename (this is the job name that shows up in the print queue)
        docPrinter.SpoolFileName = sNameRoot

        ' Find out how many printer pages the output will cover.  iNumPages will always be 1 
        ' unless the user explicitly sets the tiling options in the file->Print dialog.  
        If TypeOf m_hookHelper.ActiveView Is IPageLayout Then
            m_hookHelper.PageLayout.Page.PrinterPageCount(docPrinter, 0, iNumPages)
        Else
            'it's data view, and so we always just need one page.
            iNumPages = 1
        End If

        Dim lCurrentPageNum As Integer
        For lCurrentPageNum = 1 To iNumPages Step lCurrentPageNum + 1
            Try
                PrintAndExport.Print(docActiveView, docPrinter, m_hookHelper.PageLayout.Page, lCurrentPageNum, iResampleRatio, Nothing)
            Catch ex As Exception
                MessageBox.Show("An error has occurred: " + ex.Message)
            End Try

        Next

    End Sub
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

1voto

Ryan Guest Puntos 2262

PrintAndExport es el método recomendado en ArcGIS 10. Esta clase no fue añadida sólo para el soporte de las páginas de datos. Se añadió como un método envolvente para simplificar la impresión y la exportación para los desarrolladores. Además de envolver muchas llamadas COM, también maneja muchas de las llamadas GDI/Win32 que son necesarias para una correcta impresión y exportación.

0voto

Isaac Solomon Puntos 16554

Este es el resultado de mi propia investigación del método PrintPageLayout, es una buena manera de imprimir un pagelayout si no se necesita un control total sobre cómo se realiza la impresión, parece ser una envoltura alrededor de la IOutput para facilitar la impresión del PageLayout:

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        'Customization of this sample
        'http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/ViewCodePages/12940E59-1342-4d53-B619-2B609D298221PrintPageLayout.cs.htm

        Dim control As AxPageLayoutControl = AxPageLayoutControl1
        Dim PrintDialog1 As PrintDialog = New PrintDialog()

        Dim res As System.Windows.Forms.DialogResult = PrintDialog1.ShowDialog()
        If res = DialogResult.Cancel Then
            Return
        End If
        Dim paper As ESRI.ArcGIS.Output.IPaper = New ESRI.ArcGIS.Output.Paper

        paper.Attach(PrintDialog1.PrinterSettings.GetHdevmode().ToInt32(), PrintDialog1.PrinterSettings.GetHdevnames().ToInt32())

        'make sure the paper orientation is set to the orientation matching the current view.
        paper.Orientation = CType(control.Object, IPageLayoutControl3).PageLayout.Page.Orientation

        control.Printer.Paper = paper
        control.PrintPageLayout(1, 1, 0)
        '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

0voto

Isaac Solomon Puntos 16554

Este es el resultado de mi propia investigación del método IOutput, El IOutput le da una mayor posibilidad de controlar cómo se hace la impresión. Por ejemplo si quieres imprimir varias páginas .

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    'Customization of this sample
    'http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/025b5da7-9b10-4623-a51e-c038c348ce29.htm

    <DllImport("GDI32.dll")> _
       Public Shared Function GetDeviceCaps(ByVal hdc As Integer, ByVal nIndex As Integer) As Integer
    End Function

    <DllImport("GDI32.dll")> _
    Public Shared Function CreateDC(ByVal strDriver As String, ByVal strDevice As String, ByVal strOutput As String, ByVal pData As IntPtr) As Integer
    End Function

    <DllImport("User32.dll")> _
    Public Shared Function ReleaseDC(ByVal hWnd As Integer, ByVal hDC As Integer) As Integer
    End Function

    Public Sub PrintActiveViewParameterized(ByVal iResampleRatio As Long)

        ' Prints the Active View of the document to selected output format. 

        ' 
        Dim docActiveView As IActiveView = m_hookHelper.ActiveView
        Dim docPrinter As IPrinter
        Dim iPrevOutputImageQuality As Long
        Dim docOutputRasterSettings As IOutputRasterSettings
        Dim deviceRECT As ESRI.ArcGIS.esriSystem.tagRECT
        Dim docPaper As IPaper
        ' printdocument is from the .NET assembly system.drawing.printing 

        Dim sysPrintDocumentDocument As System.Drawing.Printing.PrintDocument

        Dim iNumPages As Short
        Dim docPrinterBounds As IEnvelope
        Dim VisibleBounds As IEnvelope

        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 = TryCast(docActiveView.ScreenDisplay.DisplayTransformation, 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()

        'Fyller i defaultvärden i printerdialog
        Dim PrintDialog1 As PrintDialog = New PrintDialog()

        'Visar utskriftsdialog
        Dim res As System.Windows.Forms.DialogResult = PrintDialog1.ShowDialog()
        If res = DialogResult.Cancel Then
            Return
        End If

        sysPrintDocumentDocument = New System.Drawing.Printing.PrintDocument()
        docPaper = New PaperClass()
        docPaper.Attach(PrintDialog1.PrinterSettings.GetHdevmode().ToInt32(), PrintDialog1.PrinterSettings.GetHdevnames().ToInt32())

        '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
        Dim hInfoDC As Integer
        hInfoDC = CreateDC(docPrinter.DriverName, docPrinter.Paper.PrinterName, "", IntPtr.Zero)

        ' Find out how many printer pages the output will cover. 

        If TypeOf m_hookHelper.ActiveView Is IPageLayout Then

            m_hookHelper.PageLayout.Page.PrinterPageCount(docPrinter, 0, iNumPages)
        Else
            iNumPages = 1
        End If

        For lCurrentPageNum As Short = 0 To iNumPages - CType(1, Short)

            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 = CInt((docPrinterBounds.YMax - GetDeviceCaps(hInfoDC, 113)))
            deviceRECT.left = CInt((docPrinterBounds.XMin - GetDeviceCaps(hInfoDC, 112)))
            deviceRECT.right = CInt((docPrinterBounds.XMax - GetDeviceCaps(hInfoDC, 112)))
            deviceRECT.top = CInt((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 TypeOf m_hookHelper.ActiveView Is IPageLayout Then
                '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
                Dim pPage As IPage
                pPage = m_hookHelper.PageLayout.Page

                'get paper object
                docPaper = docPrinter.Paper
                If docPaper Is Nothing Then
                    MessageBox.Show("no paper defined")
                    Exit Sub
                End If

                'create an envelope for the bounds of the printer's page size in device units.
                Dim pDeviceFrame As IEnvelope
                pDeviceFrame = New EnvelopeClass()
                pPage.GetDeviceBounds(docPrinter, 1, 0, docPrinter.Resolution, pDeviceFrame)

                'create and populate an envelope with the bounds of the printer page.
                Dim wksdevice As WKSEnvelope
                pDeviceFrame.QueryWKSCoords(wksdevice)

                'transfer the envelope to the deviceRECT. 
                deviceRECT.left = CInt(Math.Round(wksdevice.XMin))
                deviceRECT.top = CInt(Math.Round(wksdevice.YMin))
                deviceRECT.right = CInt(Math.Round(wksdevice.XMax))
                deviceRECT.bottom = CInt(Math.Round(wksdevice.YMax))

                'since this is a data view, not a pagelayout, we don't need VisibleBounds, so set it to NULL.

                VisibleBounds = Nothing
            End If

            '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 Then
                VisibleBounds = Nothing
            End If
            m_hookHelper.ActiveView.Output(docPrinter.StartPrinting(docPrinterBounds, 0), docPrinter.Resolution, deviceRECT, VisibleBounds, Nothing)

            '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)
        Next
        'release the DC...
        ReleaseDC(0, hInfoDC)
    End Sub
    Private Sub SetOutputQuality(ByVal docActiveView As IActiveView, ByVal iResampleRatio As Long)
        ' 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.
        ' 

        Dim docGraphicsContainer As IGraphicsContainer
        Dim docElement As IElement
        Dim docOutputRasterSettings As IOutputRasterSettings
        Dim docMapFrame As IMapFrame
        Dim tmpActiveView As IActiveView

        If TypeOf docActiveView Is IMap Then
            docOutputRasterSettings = TryCast(docActiveView.ScreenDisplay.DisplayTransformation, IOutputRasterSettings)
            docOutputRasterSettings.ResampleRatio = CInt(iResampleRatio)
        ElseIf TypeOf docActiveView Is IPageLayout Then
            'assign ResampleRatio for PageLayout
            docOutputRasterSettings = TryCast(docActiveView.ScreenDisplay.DisplayTransformation, IOutputRasterSettings)
            docOutputRasterSettings.ResampleRatio = CInt(iResampleRatio)
            'and assign ResampleRatio to the Maps in the PageLayout
            docGraphicsContainer = TryCast(docActiveView, IGraphicsContainer)
            docGraphicsContainer.Reset()

            docElement = docGraphicsContainer.[Next]()
            While docElement IsNot Nothing
                If TypeOf docElement Is IMapFrame Then
                    docMapFrame = TryCast(docElement, IMapFrame)
                    tmpActiveView = TryCast(docMapFrame.Map, IActiveView)
                    docOutputRasterSettings = TryCast(tmpActiveView.ScreenDisplay.DisplayTransformation, IOutputRasterSettings)
                    docOutputRasterSettings.ResampleRatio = CInt(iResampleRatio)
                End If
                docElement = docGraphicsContainer.[Next]()
            End While

            docMapFrame = Nothing
            docGraphicsContainer = Nothing
            tmpActiveView = Nothing
        End If

        docOutputRasterSettings = Nothing
    End Sub

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X