阅读:1835回复:1
打印页面视图
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 |
|
1楼#
发布于:2003-11-27 17:32
非常感谢,我有用
|
|