OutputPage Method
Provides access to the current page or the full range of pages for a report run, according to the value of the ListenerType property.
oReportListener.OutputPage(;
nPageNo, ;
eDevice, ;
nDeviceType ;
[,nleft, nTop, nWidth, nHeight ;
[,nClipLeft,nClipTop, nClipWidth, nClipHeight]])
Parameters
nPageNo
In page-at-a-time mode (ListenerType values 0 and 2), ReportListener uses this parameter to send you the current page number as it prepares each page for output. You can request that this single page be rendered to an alternate device at this point.In all pages-at-once mode (ListenerType values 1 and 3), you use this parameter to send the ReportListener the page number you wish to render.
For more information about supported ListenerType values, see ListenerType Property.
eDevice
Provides a handle, reference, or filename for the device to which output is rendered.When its ListenerType property value is 0, ReportListener uses this parameter to send you a GDI+ graphics handle to the current printer. When its ListenerType property value is 2, output is not actually going to a printer, so ReportListener sends you the value 0.
In all pages-at-once mode (ListenerType values 1 and 3), you use this parameter to send the ReportListener one of the following:
A GDI handle to a printer.
A GDI+ graphics handle to another output device.
A reference to an object derived from either the Visual FoxPro Shape or Container baseclass.
A filename.
You tell the ReportListener what type of eDevice value you send in this parameter by sending an appropriate value in nDeviceType.
nDeviceType
Represents the type of Device to which output is rendered.Value
Device Type
-1
No device.
The ReportListener sends this value when it triggers OutputPage in ListenerType 2.
0
hDC (GDI handle).
You can send a GDI handle to the ReportListener, to send output to an alternate printer.
1
hGraphics (GDI+ graphics handle).
The ReportListener sends this value when it triggers OutputPage in ListenerType 0. You can send it to the ReportListener, to send output to a different GDI+ context, such as a window.
2
oFoxControl.
Use this value to tell the Report Listener to create a preview display, using a Visual FoxPro Shape or Container control.
100
This value specifies a filename, to be saved as image of EMF type.
101
This value specifies a filename, to be saved as image of TIFF type.
102
This value specifies a filename, to be saved as image of JPEG type.
103
This value specifies a filename, to be saved as image of GIF type.
104
This value specifies a filename, to be saved as image of PNG type.
105
This value specifies a filename, to be saved as image of BMP type.
201
This value specifies a page to be saved additively into a previously-created TIFF, generating a multi-page TIFF file.
Tip
The ReportListener is able to perform some extra optimization of this file format when you use this value before a report run finishes. For a ReportListener with ListenerType 0 or 2, the OutputPage event happens during this time. An example of this usage is shown below. For a ReportListener with ListenerType 1 or 3, you can call OutputPage during the AfterReport Event to take advantage of the optimization.
[nleft, nTop, nWidth, nHeight,[nClipLeft,nClipTop, nClipWidth, nClipHeight]]
These optional parameters are not relevant when nDeviceType is 2 (a Visual FoxPro control surface).The first set of four coordinates (nleft, nTop, nWidth, nHeight) specifies the coordinates, in units of 1/960 inch (960 dpi), of the rectangle on the current device in which this occurrence of the layout element will be rendered. The second set of four coordinates (nClipLeft,nClipTop, nClipWidth, nClipHeight) allows a preview-type output device to indicate that only a portion of the page needs to be refreshed.
Return Value
None.
Remarks
Applies To: ReportListener Object.
The OutputPage method is unusual because, depending on the current ListenerType value, a ReportListener either triggers this method to signal you that a page is ready or expects you to trigger the calls yourself, to request the pages you want.
Understanding OutputPage's Two Processing Modes
In the first processing mode, the ReportListener acts in a style appropriate to printers and other output devices that handle output one page at a time. If necessary, these devices place incoming pages in a spool or queue until they are ready to handle more pages. This type of page-processing is forward-only; you cannot ask for any specific page a single time, after the ReportListener has begun rendering subsequent pages.
In the second processing mode, the ReportListener prepares all pages at once, effectively providing a queue of all pages until the device is ready to request them. You cannot request any pages until all pages are prepared. However, this type of page-processing results in a cached, or scrollable, collection of pages, as required by previewing devices; once the pages are prepared, you can request them in any order, and, you can request them multiple times.
Error-handling for OutputPage Parameters
The parameter list to OutputPage is complex and some parameters have multiple uses. For this reason, it may be difficult to interpret the errors you receive when you use the parameters incorrectly.
The following are the error messages you can expect if you send the ReportListener unexpected or inappropriate values when using this method.
Error message and number
Conditions triggering this error
Must specify additional parameters (Error 94)
Triggered if you do not include all three required parameters (nPageNo, eDevice, nDeviceType).
Function argument value, type, or count is invalid (Error 11)
Triggered if nDeviceType receives an unrecognized value.
DataType property for field 'eDevice' is invalid (Error 1544)
Triggered if the eDevice argument’s data type does not match the requirements for a valid value in nDeviceType.
For example, you might receive this value if nDeviceType is 0 or 1 and eDevice is not a valid handle, or if nDeviceType is one of the filename types but eDevice is not a string representing a valid filename.
Error writing to file 'filename' (Error 1105)
Triggered if nDeviceType is one of the filename types and eDevice appears valid but the file cannot be created. For example, the user might not have permissions to create a file in the specified directory.
Output page 'pageno' is not available (Error 2194)
Triggered if nPageNo is not appropriate to the current rendered pages, or if the ListenerType value is not properly set to one of the values (0, 1, 2, or 3) in which the ReportListener renders pages.
For more information about Visual FoxPro error messages, see Error Messages Listed Numerically. For more information about what to do when errors occur when you process reports, see Handling Errors During Report Runs.
Warning
In addition to the error messages above, which you may see if you invoke OutputPage with incorrect parameters, be aware that OutputPage needs resources available to the report even when you call it after the report run concludes. For example, if image file used in a report is built into your calling application, a call to OutputPage from a PreviewContainer needs access to that image file. Although no error message is generated, your report output will not be complete if you unload the application from which the REPORT FORM or LABEL command was issued.
Examples
Example 1: OutputPage in page-at-a-time mode for image files from output pages
This sample code creates a multipage Tag Image File Format (TIFF) document from a report. It uses the native ReportListener ability to specify the OutputPage nDeviceType parameter as 101, to create a TIFF file, followed by additional calls with an eDeviceType value of 201, to add into this TIFF document for subsequent pages. This ReportListener derived class uses a ListenerType value of 2, so the native code invokes OutputPage as it prepares each page.
Tip
The ReportListener class's native ability to provide images of pages as various file types is limited to some default settings for each image type it supports. In the case of TIFFs, ReportListener provides compressed TIFFs for performance. However, you are not limited to the settings provided in the native implementation. You can give the ReportListener a GDI+ graphics handle and, in the OutputPage method, request that it render a page to this device. You can then save the result to an image file with non-default specifications. Visual FoxPro supplies a class library to help you perform this and other GDI+-related tasks. For more information, see GDI Plus API Wrapper Foundation Classes.
Code
#define OutputNothing -1 #define OutputTIFF 101 #define OutputTIFFAdditive (OutputTIFF+100) LOCAL oReportListener oReportListener = NEWOBJECT("MPTiffListener") oReportListener.Filename = "Multi" WAIT WINDOW "Processing report to TIFF file...." NOWAIT REPORT FORM ? OBJECT oReportListener WAIT CLEAR DEFINE CLASS MPTiffListener AS ReportListener PROCEDURE Init THIS.AddProperty("Filename", "temp") THIS.ListenerType = 2 ENDPROC PROCEDURE BeforeReport ERASE THIS.Filename ENDPROC PROCEDURE OutputPage(nPageNo, eDevice, nDeviceType) IF (nDeviceType == OutputNothing) IF (nPageNo == 1) nDeviceType = OutputTIFF ELSE nDeviceType = OutputTIFFAdditive ENDIF THIS.OutputPage(nPageNo, THIS.Filename, nDeviceType) NODEFAULT ENDIF ENDPROC ENDDEFINE
Example 2: OutputPage in page-at-a-time echoing output to the display
This example provides a replacement for backward-compatible reporting's echoed output to the display, when the keyword NOCONSOLE is not used on the REPORT FORM Command. It uses the OutputPage method's ability to write to a GDI+ Graphics handle. If the REPORT FORM specifies NOCONSOLE, the ReportListener object does not provide display output.
By default, this ReportListener uses a ListenerType value of 2, so it invokes OutputPage as it prepares each output page but has no native output result. It evaluates CommandClauses Property values to check for the NOCONSOLE keyword, and also to evaluate the user's specified output target. If the user chose to generate output to a printer, a file, or preview, this class adjusts its behavior to match previous versions of Visual FoxPro.
Code
#DEFINE OUTPUTDEVICETYPE_GDIPLUS 1 #DEFINE OUTPUTTO_PRINT 1 #DEFINE OUTPUTTO_FILE 2 #DEFINE LISTENER_TYPE_PRN 0 #DEFINE LISTENER_TYPE_PRV 1 #DEFINE LISTENER_TYPE_PAGED 2 LOCAL loRL, loForm loRL = CREATEOBJECT("EchoListener") REPORT FORM ? OBJECT loRL && output to the console REPORT FORM ? OBJECT loRL NEXT 1 TO PRINT && output to console and print _SCREEN.Cls && clear screen REPORT FORM ? OBJECT loRL PREVIEW && to preview only, no console output loForm = CREATEOBJECT("form") loForm.Caption = "My Output Window" loForm.Show() REPORT FORM ? OBJECT loRL TO FILE c:\temp\x.txt && to file and output window REPORT FORM ? OBJECT loRL TO FILE c:\temp\x.txt NOCONSOLE && to file only DEFINE CLASS EchoListener as ReportListener ListenerType = LISTENER_TYPE_PAGED GP = 0 RHeight = 0 RWidth = 0 PROCEDURE LoadReport() IF THIS.CommandClauses.Preview THIS.ListenerType = LISTENER_TYPE_PRV ELSE IF INLIST(THIS.CommandClauses.OutputTo,OUTPUTTO_PRINT,OUTPUTTO_FILE) THIS.ListenerType = LISTENER_TYPE_PRN ENDIF ENDIF ENDPROC PROCEDURE BeforeReport() IF NOT (THIS.CommandClauses.NoConsole OR THIS.CommandClauses.Preview) DECLARE integer GdipCreateFromHWND IN GDIPLUS.DLL ; integer hwnd, integer @ nGraphics LOCAL lH, nG nG = 0 IF TYPE("_SCREEN.ActiveForm") = "O" m.lH = _SCREEN.ActiveForm.HWnd ELSE m.lH = _SCREEN.HWnd ENDIF IF GdipCreateFromHWND( m.lH, @nG ) = 0 THIS.GP = m.nG THIS.RHeight = THIS.GetPageHeight()/10 && convert 960 DPI to 96 DPI THIS.RWidth = THIS.GetPageWidth()/10 ENDIF ENDIF ENDPROC PROCEDURE OutputPage(nPageNo, ; eDevice, ; nDeviceType, ; nleft, nTop, nWidth, nHeight, ; nClipLeft,nClipTop, nClipWidth, nClipHeight) IF THIS.GP # 0 DODEFAULT(nPageNo, THIS.GP,OUTPUTDEVICETYPE_GDIPLUS , ; 0,0,THIS.RWidth, THIS.RHeight, ; 0,0,THIS.RWidth, THIS.RHeight) ENDIF ENDPROC PROCEDURE UnloadReport() * reset: IF NOT THIS.GP = 0 DECLARE integer GdipDeleteGraphics IN GDIPLUS.DLL integer GdipDeleteGraphics( THIS.GP ) THIS.GP = 0 ENDIF THIS.ListenerType = LISTENER_TYPE_PAGED ENDPROC ENDDEFINE
Example 3: OutputPage in all-pages-at-once mode
This example uses a ListenerType value of 3, so the native ReportListener class does not invoke OutputPage as it prepares pages. Instead, this derived class invokes OutputPage after the report run concludes, and displays the output to a simple preview object contained by a form. As this example shows, by varying the dimensions of the preview object, you can vary and control zoom level using any algorithm or restrictions you prefer. By passing a reference to this object in the OutputPage method, you instruct the native code what size you want for the previewed page. The native OutputPage behavior takes care of scaling the preview output appropriately.
Tip
Notice that this class's DoOutputPage wrapper code for the OutputPage method checks to see that the external call to the method has included a valid page number before invoking native OutputPage code, to avoid errors.
Code
#DEFINE BASEPAGEHEIGHT 550 #DEFINE BASEPAGEWIDTH 425 CLEAR ALL oListener = NEWOBJECT("zoomListener") oForm = CREATEOBJECT("form") WITH oForm .ScaleMode = 3 .allowOutput = .F. .top = 0 .left = 0 .height = BASEPAGEHEIGHT .width = BASEPAGEWIDTH .backcolor = RGB(255,255,255) .Show() ENDWITH oListener.PreviewContainer = oForm REPORT FORM ? OBJECT oListener oListener.DoOutputPage(1,1) WAIT window ; "Previewing at 100%... " + ; "press any key for the next preview zoom level" oListener.DoOutputPage(2, .21123 ) WAIT window ; "Previewing at 21.123%... " + ; "press any key for the next preview zoom level" oListener.DoOutputPage(3,2.367) WAIT window ; "Previewing at 236.7%... " DEFINE CLASS zoomListener AS ReportListener ListenerType = 3 PROCEDURE DoOutputPage(tPage, tMultiplier) LOCAL liPage IF VARTYPE(tPage) = "N" AND ; BETWEEN(tPage,; THIS.CommandClauses.RangeFrom, ; IIF(THIS.CommandClauses.RangeTo=-1, ; THIS.PageTotal, ; THIS.CommandClauses.RangeTo)) liPage = INT(tPage) ELSE liPage = THIS.CommandClauses.RangeFrom ENDIF THIS.SetPreview(tMultiplier) THIS.OutputPage(liPage,THIS.PreviewContainer.MyPreview,2) ENDPROC PROCEDURE SetPreview(tMultiplier) LOCAL liHeight, liWidth IF TYPE("THIS.PreviewContainer.MyPreview") # "O" THIS.PreviewContainer.AddObject("MyPreview","shape") ENDIF IF VARTYPE(tMultiplier) = "N" AND ; BETWEEN(tMultiplier,.01, 10) liHeight = BASEPAGEHEIGHT * tMultiplier liWidth = BASEPAGEWIDTH * tMultiplier WAIT WINDOW ; "H:" + TRANSFORM(liHeight)+ ; ", W:" + TRANSFORM(liWidth) TIMEOUT 1 * note that VFP will round the pixels WITH THIS.PreviewContainer .LockScreen = .T. .MyPreview.Height = liHeight .MyPreview.Width = liWidth .Height = liHeight .Width = liWidth .LockScreen = .F. .Cls() ENDWITH ENDIF ENDPROC PROCEDURE Destroy THIS.PreviewContainer = NULL ENDPROC ENDDEFINE
See Also
Concepts
Reference
Other Resources