The default report builder application, ReportBuilder.App, contains an internal lookup table that assigns specific behavior to builder events. The table defines whether certain object-event combinations are ignored or directed to specific classes for handling.
For more information on the event handling classes, see the source code to reportbuilder.app contained in the XSource Folder under the Visual FoxPro HOME() directory.
Because it is built-in to the application, this lookup table cannot be modified directly. ReportBuilder.App has a mechanism that allows you to copy the table out to disk so that you can adjust the default settings and even add your own handler classes to augment or replace the default ones.
See How to: Configure the Report Builder's Event Handling for more information.
In this topic:
-
The Event Handler Registry Table Structure
-
Handler Class Types
-
How the Report Builder processes events
Table Structure
ReportBuilder.App uses an internal lookup table to determine which handler class to instantiate for a given combination of EventType and report object (as specified by the currently selected record in the FRX cursor, which could be a report control, a report band, or the report header record itself). The structure of this table is shown below:
Field Name | Type (size) | Description |
---|---|---|
REC_TYPE |
C (1) |
Specifies the type of handler class the record defines. |
HNDL_CLASS |
C (35) |
Specifies the class name. The class will be instantiated using a NEWOBJECT() call that assumes the class library will be found in the Visual FoxPro SET CLASSLIB or SET PATH. |
HNDL_LIB |
C (50) |
Specifies the class library. This can be a visual (.vcx) or non-visual (.prg) class library. |
EVENTTYPE |
I |
Specifies the event type. Use a value of -1 for a "wild card" match. See Understanding Report Builder Events for a list of possible event types. |
OBJTYPE, OBJCODE |
I, I |
Specifies the report control type. These fields are equivalent to the OBJTYPE and OBJCODE fields in the report layout source (.frx) tables. Use a value of -1 for a "wild card" match. See Table Structures of Table Files (.dbc, .frx, .lbx, .mnx, .pjx, .scx, .vcx) for links to where the structure of report layout source (.frx) files are documented. |
NATIVE |
L |
Indicates "native behavior override". For this record's event type/report object combination, the native Designer behavior should be allowed to take place. |
DEBUG |
L |
Indicates "debug handler override". For this record's event type/report object combination, a special "debug" user interface will be displayed instead of the handler class specified by HNDL_CLASS. |
FLTR_ORDR |
C (1) |
Defines the order in which Filter handlers are processed. For records of REC_TYPE="F" only. |
NOTES |
C (35) |
This field is not used by ReportBuilder.App, but it is displayed in the report builder's event handler registry table browser. (For more information, see Event Handler Registry Dialog Box (Report Builder).) |
Any additional fields in this table are ignored by the report builder.
Handler Class Types
Classes defined in the registry table can be one of several types:
Value | Type | Description |
---|---|---|
H |
Indicates a handler class for a specific builder event / report object combination. |
|
F |
Indicates a handler class that will be invoked for every report builder event, and can prevent the event from being handled by the report builder. |
|
X |
Indicates a handler class that will be invoked after the event processing, but before the report builder returns control to the Designer, as a "clean up" process. |
|
G |
Indicates a class that will be invoked in place of the native GETEXPR dialog box in any report builder dialog box. |
|
E |
Indicates a class that will be invoked when the Edit settings command button is selected from the Other tab of the Report Control Properties Dialog. |
|
M |
Indicates a Page Object class that will be automatically added to the pageframe in the Multiple Selection Dialog Box (Report Builder). |
Event Handler API
Event Handler classes can be of any Visual FoxPro base class but must implement the Event Handler API. The Event Handler API has the following attributes:
-
A method named Execute that accepts a single object reference parameter.
What the class actually does in the Execute( oEvent ) method is not specified, although for Event Handler classes they probably will need to set the return flags:
В | Copy Code |
---|---|
DEFINE CLASS MyHandler AS Custom PROCEDURE Execute( oEvent ) * You can alter oEvent.returnFlags to suit oEvent.SetHandledByBuilder(.T. | .F. ) oEvent.SetReloadChanges( .T. | .F. ) ENDPROC ENDDEFINE |
This method is passed a reference to an object representing the event that occurred. The handler should assign the appropriate ReturnFlags value to indicate what action the designer should take next when the builder terminates and returns control.
Event Handlers:
-
Are identified by a
REC_TYPE
value of "H".
-
Are generally only instantiated for a specific designer builder event type and report object type combination.
For more information on the properties and methods of the object reference passed to the handler class in the Execute()
method, see The Report Builder Event Class.
Filter Handler API
Filter classes can be of any Visual FoxPro base class but must implement the Event Handler API (see above) plus one additional public property, allowToContinue:
В | Copy Code |
---|---|
DEFINE CLASS MyFilter AS Custom allowToContinue = .T. PROCEDURE Execute( oEvent ) * decide whether or not to process the event THIS.allowToContinue = .T. * You can optionally alter oEvent.returnFlags to suit oEvent.SetHandledByBuilder(.T. | .F. ) oEvent.SetReloadChanges( .T. | .F. ) ENDPROC ENDDEFINE |
Filter Handler classes:
-
Are identified by a
REC_TYPE
value of "F".
-
Are instantiated for every report builder event.
-
Are processed in the order indicated by the FLTR_ORDR field.
-
Can prevent further processing of the event by setting their AllowToContinue property to false (
.F.
)
-
Can apply pre-processing to the FRX cursor prior to the event being processed by an Event Handler class.
Exit Handlers
Exit Handler classes must support the Event Handler API.
Exit Handler classes:
-
Are identified by a
REC_TYPE
value of "X".
-
In general are a way of getting some code to run at clean-up time.
-
Are only processed if an Event Handler class was previously located and executed. If a Filter handler prevented further processing, then Exit handlers will not be processed.
-
Like all handler classes, they have the opportunity to alter the
oEvent.ReturnFlags
value but it is very bad practice to do so.
GetExpression Wrapper API
You can replace the implementation of the GETEXPR dialog box used in the report builder by registering a class of REC_TYPE="G" in the handler registry. The class must support the GetExpression() method as shown in this example:
В | Copy Code |
---|---|
DEFINE CLASS MyGetExpr AS Custom PROCEDURE GetExpression( cDefExpr, cDataType, cCalledFrom, oEvent ) LOCAL cExpression GETEXPR TO cExpression DEFAULT cDefExpr RETURN cExpression ENDPROC ENDDEFINE |
Only one class may be registered as the default GetExpressionWrapper. If there are more than one record of REC_TYPE
="G," only the first one located will be used by the report builder.
The cCalledFrom parameter
The report builder passes the GetExpressionWrapper class a parameter indicating what type of expression is being edited. Possible values are:
-
"PrintWhenExpression"
-
"FieldExpression"
-
"OleBoundField"
-
"OleBoundExpression"
-
"BandGroupOnExpression"
-
"VariableValueToStore"
-
"VariableInitialValue"
Run-time Extension Editor API
You can replace the implementation of the dialog box that appears when you click the Edit settings command button in the Run-time extensions group on the Other tab of the Report Builder by registering a class in the handler registry with a REC_TYPE
of "E". The class must support the Event Handler API. If implementing a form class, then the form must be issued as a MODAL window.
A run-time extension editor classes should do the following in the Execute() method:
-
Read the metadata XML from the STYLE field.
-
Present a user interface to allow the user to edit the metadata.
-
Save a valid XML fragment back into the STYLE field.
-
Unlike the other handler types shown above, it should not attempt to set the return flags.
Only one class may be registered as the default RuntimeExtensionEditor. If there is more than one "E" record in the handler registry table, the first one found will be used.
Adding tabs to the Multiple-selection dialog box
You can add pages to the pageframe in the Multiple Selection Dialog Box (Report Builder) by registering a class in the handler registry with a REC_TYPE
of "M".
The class must be derived from the Page Object. If the page contains a Container Object that implements .LoadFromFrx()
and .SaveToFrx()
, then these methods will be called automatically by the multiple-selection dialog at appropriate points:
В | Copy Code |
---|---|
DEFINE CLASS pagAlign AS page Caption = "Alignment" Name = "pagAlign" ADD OBJECT Panel1 AS panelAlign ENDDEFINE DEFINE CLASS panelAlign as Container BorderWidth = 0 Width = 300 Height = 300 Event = null frxCursor = null ADD OBJECT Check1 AS Checkbox WITH ; Caption = "Align to leftmost object", ; Top = 100, Left = 50, Width = 150, Value=.F. PROCEDURE LoadFromFrx() * No initialization required RETURN .T. ENDPROC PROCEDURE SaveToFrx() IF THIS.Check1.Value LOCAL curSel curSel = SELECT() SELECT MIN(hpos) AS hpos FROM frx ; WHERE curpos AND objcode<>53 ; INTO CURSOR query newHpos = query.hpos USE IN query SELECT frx SCAN FOR curpos AND RECNO()>1 REPLACE hpos WITH m.newHpos ENDSCAN SELECT (m.curSel) ENDIF RETURN .T. ENDPROC ENDDEFINE |
This example adds a tab to the multiple-selection dialog with a single checkbox that, if checked, will set the horizontal position all selected objects to that of the left-most positioned object in the selection.
The container object may implement any of the following PEMs:
-
The
LoadFromFrx()
method is called during the initialization of the form, and is a good place to read values from the frx cursor in order to initialize values of the controls in the container.
-
The
SaveToFrx()
method is called when the user clicks OK. ReturnFALSE
if you wish to prevent the dialog from closing.
-
If defined, the
Event
property will be assigned a reference to the report builder's Event object. (See The Report Builder Event Class for more information.)
-
If defined, the
frxCursor
property will be assigned a reference to the Event object's frxCursor member object, for convenience. (See FRX Cursor Foundation Class for more information.)
There can be more than one record in the handler registry defined with REC_TYPE
="M,". Each page class will be loaded into the dialog box as a separate tab.
How the report builder processes events
When the report builder is invoked, the Report Designer passes it an event type ID, with a copy of the FRX file open in a private data session. The report object that the event applies to is usually identified by the location of the record pointer in the FRX cursor. The report builder takes note of the OBJTYPE and OBJCODE values on the selected record, and then refers to the handler registry table.
1. All Filter Handlers are processed
The builder selects all records from the handler registry table with REC_TYPE
="F", sorted by FLTR_ORDR
, and instantiates each filter class in turn, invoking the Execute() method.
If the value of its allowToContinue property is true (.T.
), then the next filter handler class is instantiated.
If the value of its allowToContinue property is false (.F.
), then no further processing takes place - ReportBuilder.App sets Bit 0 on the ReturnFlags parameter to indicate to the designer that the builder event had been handled successfully.
Important:
-
The value specified in the
FLTR_ORDR
field is important, because a filter with a lower value (higher priority) can prevent futher processing, both by the next filter in line and also by an appropriate Event Handler class.
-
Each Filter Handler gets an opportunity to set the event's return flags, but these will only be respected if the Filter sets its allowToContinue to false (
.F.
), because if processing continues, the successive Event Handler will assume it can set these flags as it wishes, possibly overriding any setting made by the Filter Handler.
2. An appropriate Event Handler class is instantiated
The report builder next looks for a specific Event Handler class to instantiate and handle the event.
The Registry table allows for "wild card" matches, so that not every unique combination of builder event + report object needs to have a separate record. The builder uses selectively more general searches in the handler registry table for non-deleted records.
The builder will progressively generalize the searches, applying wild-card values until it finds a match:
Sequence | REC_TYPE | EVENTTYPE | OBJTYPE | OBJCODE |
---|---|---|---|---|
1 |
"H" |
(Exact) |
(Exact) |
(Exact) |
2 |
"H" |
(Exact) |
(Exact) |
-1 |
3 |
"H" |
(Exact) |
-1 |
-1 |
4 |
"H" |
-1 |
-1 |
-1 |
If still no matching record is found, then the builder event will be ignored (both bits of the ReturnFlags parameter will be cleared) and control returned to the designer for the native Visual FoxPro behavior.
If a match is found, the class is instantiated and its Execute() method invoked.
3. All Exit Handlers are processed
Once the matching Event Handler has been executed, the report builder selects all records from the lookup table with REC_TYPE
="X," sorted by FLTR_ORDR
, and instantiates each class in turn, invoking the Execute() method.
Concerning multiple selected objects
The default event handler registry table includes a record for a MultiSelectHandler registered to an OBJTYPE
of 99. See Multiple Selection Dialog Box (Report Builder) for an example of a handler of multiple selections.
The builder detects when multiple report controls are selected in the layout and treats this case as a unique OBJTYPE
:
В | Copy Code |
---|---|
COUNT FOR curpos AND RECNO() > 1 TO oEvent.SelectedObjectCount IF oEvent.SelectedObjectCount > 1 oEvent.OBJTYPE = 99 oEvent.OBJCODE = 0 ELSE oEvent.OBJTYPE = frx.OBJTYPE oEvent.OBJCODE = frx.OBJCODE ENDIF |
In this way, a specific Event Handler class can be registered to handle multiple-selections.
See Also
Tasks
How to: Add Your Own Handler to the Report Builder's RegistryHow to: Configure the Report Builder's Event Handling
Reference
Event Handler Registry Dialog Box (Report Builder)Report Band Properties Dialog Box (Report Builder)
Report Control Properties Dialog Box (Report Builder)