gis
gis
管理员
管理员
  • 注册日期2003-07-16
  • 发帖数15947
  • QQ554730525
  • 铜币25339枚
  • 威望15364点
  • 贡献值0点
  • 银元0个
  • GIS帝国居民
  • 帝国沙发管家
  • GIS帝国明星
  • GIS帝国铁杆
阅读:1835回复:1

打印页面视图

楼主#
更多 发布于:2003-11-17 11:03
Description:

This tip illustrates VBA code to print the current ArcMap page layout to the current printer. This tips code does not raise any dialogs.

A simpler alternative is to call IApplication::PrintDocument, however this will raise dialogs to select various print options and only if the "OK" button is pressed then the layout will be printed.

Make sure ArcMap is in "Layout View" for this code to run. This tip uses ArcMaps printer object to do the output. This can be one of three types of printer, Emf (default windows printer), PostScript or ArcPress. The page in the ArcMaps layout will be mapped onto the printers page depending on the value of the PageToPrinterMapping property on the Page object. This is accessible off the PageLayout object. The page to printer mapping can also be set in the "Print" dialog from ArcMap only if the layout page will not fit onto the printer page. If the PageToPrinterMapping is esriPageMappingCrop or esriPageMappingScale then the output will fit on one printer page either cropped or scaled respectively. However if the PageToPrinterMapping is set to esriPageMappingTile and the page in ArcMap is bigger than the printers page then the output will be printed on multiple printer pages.

Most of this tip is involved in calculating 3 envelopes and one rectangle:
IPage::GetDeviceBounds is used to calculate the envelope of the page that is printable (pDeviceBounds), this may include a small gap around the edge of the page. This envelope is in device co-ordinates (dots across a page).
The device bounds co-ordinates are also held in a RECT structure (rectDeviceBounds) which stores the same co-orindates as the envelope but held as type long. Note there is a special case for EMF printers and here the rectDeviceBounds has to have the top left at 0,0.
IPage::GetPageBounds is used to calculate an envelope holding the area of the layout that is to be printed on the current printer page (pVisBounds), this is in either inches of centimetres.
IPrinter::QueryPaperSize is use to calculate the size of the current printer page (devFrameEnvelope), this is in device co-ordinates.

The output is then initiated with StartPrinting and a standard windows device context is returned. The page layouts implementation of the Output method (on the ActiveView interface) is called to draw the contents of the page layout into the supplied device context. When FinishPrinting is called, the output will be ready to print.

The above process is then repeated for each page.

How to use:
Add a new UIButtonControl to any toolbar.
Paste the code into the UIButtonControl's click event.
Mind the name of the control, the tip assumes it is UIButtonControl1.
Make sure ArcMap is in Layout View.
Run the Macro or click on the UIButtonControl.
' Print Page Layout Sample
'
Private Sub UIButtonControl1_Click()

  Dim pMxDoc As IMxDocument
  Set pMxDoc = ThisDocument
  
  '
  ' Make sure we're in layout view
  '
  If Not TypeOf pMxDoc.ActiveView Is IPageLayout Then
    MsgBox "Must be in Page Layout mode for this print example to work"
    Exit Sub
  End If
  
  '
  ' Get the PageLayout by a QI with the active view,
  ' and then get the Page object representing the on screen page
  '
  Dim pPageLayout As IPageLayout
  Set pPageLayout = pMxDoc.ActiveView
  Dim pPage As IPage
  Set pPage = pPageLayout.Page
 
  ' Optionally override the current PageToPrinterMapping, options for example:
  ' To tile the page layout over many pages if its bigger than the printer page
  '  pPage.PageToPrinterMapping = esriPageMappingTile
   '
  ' Get ArcMaps current Printer object
  '
  Dim pPrinter As IPrinter
  Dim pMxApp As IMxApplication
  Set pMxApp = ThisDocument.Parent
  Set pPrinter = pMxApp.Printer
  
  Dim lNumPages As Integer
  
  '
  ' Find out how many printer pages the output will cover, lNumPages is calculated by PrinterPageCount.
  ' If lNumPages greater than 1 then we're going to tile the pagelayout onto multiple pages
  ' This will only be the case if pPage.PageToPrinterMapping = esriPageMappingTile
  '
  pPage.PrinterPageCount pPrinter, 0, lNumPages
  
  '
  ' Note if you want to force ArcMap to use a postscript printer rather
  ' than ArcMaps current printer then uncomment the two lines below:
  'Set pPrinter = New PsPrinter
  'Set pPrinter.Paper = pMxApp.Paper
  '
  
  Dim lCurrentPageNum As Long
  For lCurrentPageNum = 1 To lNumPages
  
    ' Get dots per inch from printer
    Dim printerDpi As Long
    printerDpi = pPrinter.Resolution
    
    ' Get device bounds - this is in printer device coordinates (number of dots across page to a page)
    ' Note there is often a margin around the edge that is unprintable
    '
    Dim pDeviceBounds As IEnvelope
    Set pDeviceBounds = New Envelope
    pPage.GetDeviceBounds pPrinter, lCurrentPageNum, 0, printerDpi, pDeviceBounds
      
    ' Get values (as doubles) out of the envelope and put them into a rectangle (as Longs)
    '
    Dim rectDeviceBounds As tagRECT
    rectDeviceBounds.Left = pDeviceBounds.XMin
    rectDeviceBounds.Top = pDeviceBounds.YMin
    rectDeviceBounds.Right = pDeviceBounds.XMax
    rectDeviceBounds.bottom = pDeviceBounds.YMax
  
    If TypeOf pPrinter Is IEmfPrinter Then
      ' For emf printers we have to remove the top and left unprintable area
      ' from device coordinates so its origin is 0,0.
      '
      rectDeviceBounds.Right = rectDeviceBounds.Right - rectDeviceBounds.Left
      rectDeviceBounds.bottom = rectDeviceBounds.bottom - rectDeviceBounds.Top
      rectDeviceBounds.Left = 0
      rectDeviceBounds.Top = 0
      
    End If
  
    ' Compute the area of the page layout to send to the printer,
    ' this is in page layout units (inches or cm)
    Dim pVisBounds As IEnvelope
    Set pVisBounds = New Envelope
    pPage.GetPageBounds pPrinter, lCurrentPageNum, 0, pVisBounds
      
    ' Build envelope in device coordinates - this must be the whole paper
    Dim paperWidthInch As Double
    Dim paperHeightInch As Double
    pPrinter.QueryPaperSize paperWidthInch, paperHeightInch
    
    Dim devFrameEnvelope As IEnvelope
    Set devFrameEnvelope = New Envelope
    devFrameEnvelope.PutCoords 0, 0, paperWidthInch * printerDpi, paperHeightInch * printerDpi
    
    ' StartPrinting takes a device frame (whole page) and returns a handle to a device context (hDC)
    ' - we direct further output to the hDC
    Dim hDC As Long
    hDC = pPrinter.StartPrinting(devFrameEnvelope, 0)
    
    ' This draws the visible bounds (pVisBounds) area of the
    ' active view to the printer
    pMxDoc.ActiveView.Output hDC, printerDpi, rectDeviceBounds, pVisBounds, Nothing
    
    ' Flush output to the printer
    pPrinter.FinishPrinting
  
  Next
  

End Sub

喜欢0 评分0
trsoft
路人甲
路人甲
  • 注册日期2003-11-26
  • 发帖数56
  • QQ
  • 铜币253枚
  • 威望0点
  • 贡献值0点
  • 银元0个
1楼#
发布于:2003-11-27 17:32
非常感谢,我有用
举报 回复(0) 喜欢(0)     评分
游客

返回顶部