S P A C E F O L D  
data... any distance... minimal time  
 
Visual FoxPro 9.0 SP2
FRX Cursor Foundation Class
This is an addendum to an existing FFC class topic, covering changes in SP2. The frxCursor reporting system utility class received some general and highly significant enhancements in SP2, which are described in the table below. 

The memberdata-handling enhancements described here were originally proposed in the RTM CHM topic Report XML MemberData Extensions, as methods of an FX class, FXMemberData. They became methods of FRXCursor because this class holds behavior that needs to be available to both design-time and run-time components.

A change that occurred in the SP1 time period, to the screenDPI property, is also included here.

Properties and methods Description

createBandCursor Method (and similar)

Creates a cursor with alias "bands" from the FRX cursor, containing useful info about the bands in the report.

SP1 Syntax: createBandCursor([cFrxAlias])

SP2 Syntax: createBandCursor([tcFrxAlias][,tiSession])

Return Values: logical

Parameters: 

tcFRXAlias provides the alias of the open Report table (frx) from which the "bands" cursor data should be derived. If the argument is omitted, the method assumes an alias of "FRX".

tiSession, new in SP2,  provides the number of the session in which the open Report table exists, and in which the new cursor should be created.. 

Remarks:

The optional second parameter provided in SP2 for this method is also added to many other cursor-handling methods of frxCursor in SP2. This argument  allows runtime objects, which may have been created in any session and may be data-handling in multiple sessions, to give an frxCursor instance proper directions to find the session in which to work.

In some cases, this work is being done outside a report run, and without a reportlistener class present.  Therefore, it may not be possible to request the information from a reference to the listener, or a listener may be present but the FRXDataSession value may be -1 (the default when a report run is not in progress).

cursorToXmlStr Method,
xmlStrToCursor Method

cursorToXmlStr invokes CURSORTOXML on an alias, providing a string result. Always omits DELETED() records regardless of the SET("DELETE"), and omits the XML declaration.

xmlStrToCursor moves a CURSORTOXML-shaped XML document provided as a string into a cursor, following free table rules. It dynamically adds columns up to the limit available in Xbase and expects all attributes to be appropriate to free table column-names in length.

Syntax: cursorToXmlStr([tcMetaAlias]),xmlStrToCursor(tcXml[, tcMetaAlias])

Return Values: string and logical, respectively

Parameters: 

tcMetaAlias provides the alias of the open cursor or table for which you want XML returned. 

Remarks:

Overloading of the "basic" memberdata columns and the minimal set provided by the shipping components is encouraged, to stay within the 255 column limit available in any one cursor row to everyone.

Reference the shipping components for practical examples of use of the Name column in the memberdata cursor to scope your use of columns to the rows that belong to "your" object, while other rows of memberdata for the same layout control might use the columns very differently. You can review the namespaces for all the shipping components #DEFINEd in the FOXPRO_REPORTING.H file.

For example, in the following excerpt from its ApplyFX implementation, gfxRotate finds a row of memberdata that "belongs" to it by checking for its namespace and then gets its instructions from the standard Execute column in that row:

         LOCATE FOR FrxRecno = m.liFRXRecno AND ;
                    Type = FRX_BLDR_MEMBERDATATYPE AND ;
                    Name == FRX_BLDR_NAMESPACE_ROTATE AND ;
                    NOT EMPTY(Execute)  
                    
         IF FOUND() AND NOT EMPTY(INT(VAL(Execute))) 
            m.liAngle = INT(VAL(Execute))
            * ... 
         ENDIF                        
                        

In this example, a component derives completely different meaning from the same standard columns:

	select FRXRECNO, ;
		   EXECWHEN   as ENABLED, ;
		   CLASS      as ALPHA, ;
		   DECLASS    as SOURCE ;
	    from (m.toListener.MemberdataAlias) ;
	    into cursor (THIS.myCursor) ;
	    where TYPE     = 'R' and ;
	          NAME     = "Spacefold.Example.MyRender" and ;
	          EXECWHEN = '1'                        
                        

It is also important to realize that a single component may use multiple rows in the same layout control's memberdata cursor, to represent more complex information.

As a final significant opportunity, you can "pack" nested XML documents, or other complex structures, within a single complex attribute. This is the approach that is used by Advanced Properties (namespace: Microsoft.VFP.Reporting.Builder.AdvancedProperty)  of type XML, such as HTML.Metatag.HTTP-EQUIV.

All cursor columns are created as memofields by xmlStrToCursor, to allow extensions the greatest freedom in interpreting the contents of any value and in overloading the columns for multiple use. If a namespace, such as the Custom Properties namespace, may use a single column for contents of multiple data types, it is advisable to use another column to indicate the datatype in use for a specific row.  For example, the Advanced Properties namespace uses the DECLASS column for this purpose. 

You can see all the datatype values recognized in the Advanced Properties namespace, and stored in the DECLASS column, #DEFINED in the FOXPRO_REPORTING.H file.  They are also listed in Appendix C of the whitepaper Data Visualization in Reports with VFP 9.0 SP2.

Tip note Tip
Note that the two Dynamics implementations add a number of "custom columns" to the memberdata core schema set.

While in the case of Microsoft.VFP.Reporting.Builder.AdjustObjectSize the extra columns might have been avoided, we judged that the added columns (Width and Height) would prove extremely useful for multiple overloads in various custom namespaces.

In the Microsoft.VFP.Reporting.Builder.EvaluateContents namespace, some added columns were unavoidable but, wherever possible, we limited the number being added by creating compound values (FStyle, PenRGB, and FillRGB) rather than "spreading" the information into simple data elements although that might have been more convenient.

We also judged that the various columns being added would benefit multiple extension scenarios. Because they ship with the product, you can overload them, along with the base memberdata schema attributes, for any use that seems appropriate in your own namespace, without having increased the overall column count for standard memberdata cursors.

generateAdjustObjectSizeScript Method

Provides generated AdjustObjectSize code based on specified MemberData record usage.

Syntax: generateAdjustObjectSizeScript(
      [tcFrxAlias][,tcMemberDataAlias][,tiSession])

Return Values: string

Parameters: 

tcFRXAlias provides the alias of the open Report table (frx) from which the "bands" cursor data should be derived. If the argument is omitted, the method assumes an alias of "FRX".

tcMetaAlias provides the alias of the open cursor or table holding memberdata. 

tiSession provides the number of the session in which the work table exist. 

Remarks:

This method is invoked by fxMemberDataScript at run-time to create the script it executes for Dynamic behavior associated with  shape and image layout controls in a report.  At design-time the ReportBuilder dialogs invoke this method to show you a preview of the script on the Dynamics tab of the properties dialog.

generateEvaluateContentsScript Method

Provides generated EvaluateContents code based on specified MemberData record usage.

Syntax: generateEvaluateContentsScript(
      [tcFrxAlias][,tcMemberDataAlias][,tiSession])

Return Values: string

Parameters: 

tcFRXAlias provides the alias of the open Report table (frx) from which the "bands" cursor data should be derived. If the argument is omitted, the method assumes an alias of "FRX".

tcMetaAlias provides the alias of the open cursor or table holding memberdata. 

tiSession provides the number of the session in which the work table exist. 

Remarks:

This method is invoked by fxMemberDataScript at run-time to create the script it executes for Dynamic behavior associated with  textbox layout controls in a report.  At design-time the ReportBuilder dialogs invoke this method to show you a preview of the script on the Dynamics tab of the properties dialog.

getMetadataDomDoc Method

Returns a reference to an MSXml.DomDocument with the metadata xml loaded. Assumes FRX is located on record holding the desired metadata in its Style field.

Syntax: getMetadataDomDoc(tcFRXAlias])

Return Values: MSXml.DomDocument

Parameters: 

tcFRXAlias provides the alias of the open Report table (frx) from which the metdata document  should be derived. If the argument is omitted, the method assumes an alias of "FRX".>

Remarks:

This method is primarily for use at design-time by Builder elements working with Memberdata within the ReportBuilder.App code framework, so no second parameter for datasession is provided.

packupMemberData Method

During a ReportBuilder event, converts rows in the Memberdata cursor into XML and stores them in the Style column of the record under edit, assumed to be the current row in the FRX cursor.

Syntax: packupMemberData([cFrxAlias], [cMetaAlias])

Return Values: logical (success)

screenDPI Property

Dots per inch for the current screen display device, initially set by querying GetDeviceCaps.

Default: 96

Remarks:

In VFP9 -RTM, this value was  hard coded to 96, regardless of the actual display's DPI. For design-time use this was appropriate; the Report Designer always works at 96 DPI.

However, starting in VFP9-SP1, the real (versus Report Designer) screen DPI is interrogated and available for use in FruToPixels() and other calculations in frxCursor that might occur in run-time use.
For some output devices, it is necessary to compare screen resolution with target output device DPI while rendering content. 

When the post-RTM ReportBuilder uses frxCursor, it re-adjusts frxCursor's screenDPI property value to the Report Designer-appropriate value of 96.

quietMode Property

Allows runtime users of frxCursor to specify whether the class displays error messages and other user feedback.

Default: .F.

unpackMemberData and unpackFrxMemberData Methods

Expand the XML contents of the STYLE column into a cursor, either for one record (primarily for design-time use) or for all FRX records (primarily for run-time use). 

Syntax:
unpackMemberData([tcFRXAlias][,tcMetaAlias][,tiDataSession]) and
unpackFRXMemberData([tcFRXAlias][,tcMetaAlias][,tiDataSession][,tlOmitIndex])

Return Values: logical (success)

Parameters: 

tcFRXAlias provides the alias of the open Report table (frx) from which the "bands" cursor data should be derived. If the argument is omitted, the method assumes an alias of "FRX".

tcMetaAlias provides the alias of the open cursor or table holding memberdata. Defaults to "memberdata", the alias used by the ReportBuilder application code framework for design-time use. However, at run-time different objects might conceivably all pull their own memberdata cursors with different generated aliases. (Typically, they share one memberdata cursor and pull more customized versions of "their" records into differently-shaped cursors in the FRXDataSession, but there is nothing stopping them from each having their own memberdata base cursor as well.)

tiSession provides the number of the session in which the work table exist. 

If tlOmitIndex is not passed as .T., the unpackFRXMemberData method indexes the memberdata cursor on the FRXRecNo column with the tag FRXRECNO.

Remarks:

The full-FRX version includes an extra leading column, FRXRecNo, holding the record number of the original row in the FRX from which the memberdata was pulled. The FRX cursor rows can therefore be related to the Memberdata cursor rows in an appropriate one-to-many relationship, providing a rich set of metadata information that may describe many different extensions to a single layout control or other FRX element.

The whitepaper Data Visualization in Reports with VFP 9.0 SP2 and its source code provide examples of custom column use. It also demonstrates how the SP2 Xbase components of the Reporting System use these methods to provide both design-time and run-time memberdata services to all extension participants, so individual  extensions do not have to handle XML directly.

Please review the remarks in the entry for the xmlStrToCursor method, above, for more information on rules applying to these two "unpack" methods.

See AlsoSee Also