Report Builder Event Handler Registry Table

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 (50)

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

Event Handler

Indicates a handler class for a specific builder event / report object combination.

F

Filter Handler

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

Exit Handler

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

GetExpression Wrapper

Indicates a class that will be invoked in place of the native GETEXPR dialog box in any report builder dialog box.

E

Run-time Extension Editor

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

Multi-select dialog tab

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:

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:

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:

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:

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. Return FALSE 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:

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 Registry
How 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)

Concepts

Understanding Report Builder Events

Other Resources

Extending Reports at Design Time