订购:http://www.huachu.com.cn/itbook/itbookinfo.asp?lbbh=10054628
http://www.china-pub.com/computers/common/info.asp?id=34809
在本书即将完成之际,微软公司发布了Visual FoxPro 9.0的SP2版本。在SP2中又引入了对报表的许多增强,这些增强中最引人注目的是现在可以通过xBase代码扩展报表设计器和报表输出引擎。
报表设计器现在允许自定义设计器的Properties对话框,在SP2之前,开发者不能扩展现有Properties对话框,但是可以通过事件处理器注册表(Event Handler Registry)来替换它们。不过创建一个自定义Properties对话框并不是一件容易的事情,SP2的增强受欢迎之处是为所有用户在报表设计器中提供了一个接口,作为对所创建自定义报表绘制对象的补充。
SP2也使得报表输出处理更加容易。包含在SP2中的REPORTOUTPUT.APP,提供了一种使用自定义类挂钩报表输出的方法。这个新增类叫做Handlers,它由FX和GFX两部分构成。FX Handlers提供了报表运行的扩展功能,但是它并不处理任何报表绘制功能。GFX Handlers执行实际的报表绘制功能,并提供扩展当前绘制或替换所有绘制的功能。
在 12.10.5 节使用EvaluateContents事件实现了对域控件对象绘制的调整,要实现对形状或图片类型的布局元素的调整,则应当在控件的AdjustObjectSize事件中进行。Visual FoxPro为形状或图片的每个布局元素在绘制之前调用一次AdjustObjectSize,但是当具备下列某个条件时除外:
l 如果在运行时刻派生的ReportListener的AdjustObjectSize事件中没有代码;
l 如果元素在带区中没有标记为可扩展;
在SP2中新增了CallAdjustObjectSize属性,用于指定是否要求ReportListener为所有相应的形状或图片类型控件调用AdjustObjectSize事件。该属性的可用值在如表12-50所示。
表12-50 CallAdjustObjectSize属性的可用值
值 |
说明 |
0(默认值) |
如果在AdjustObjectSize事件具有代码的话,则对所有布局对象运行此代码 |
1 |
不发生AdjustObjectSize事件,即使其中具有代码 |
2 |
AdjustObjectSize事件总是发生,不管事件中是否具有代码。该值主要的目的是用于调用BINDEVENT( ),而不是执行方法中的代码 |
如果报表输出不需要动态对象大小,可以关闭该功能,以实现更好的性能。假设在表单上有一个复选框被选定,下列代码示例使用CallAdjustObjectSize关闭AdjustObjectSize事件,进行最佳化报表输出。
oReport = CREATEOBJECT("myReportlistener")
IF THISFORM.chkNoAdjustSize.Value = .T.
oReport.CallAdjustObjectSize = 1
ENDIF
REPORT FORM (myreportfile) OBJECT oReport PREVIEW
与CallAdjustObjectSize属性类似,CallEvaluateContents属性用于指定是否要求ReportListener对报表上的所有的域控件调用EvaluateContents事件。通过 12.10.5 节的介绍可以知道,在EvaluateContents事件中可以改变域控件的文本、颜色、字体和Alpha值。该属性的可用值如表12-51所示。
表12-51 CallEvaluateContents属性的可用值
值 |
说明 |
0(默认值) |
如果在EvaluateContents事件具有代码的话,则对所有布局对象运行此代码 |
1 |
不发生EvaluateContents事件,即使其中具有代码 |
2 |
EvaluateContents事件总是发生,不管事件中是否具有代码。该值主要的目的是用于调用BINDEVENT( ),而不是执行方法中的代码 |
现有一个报表,可以在运行时刻通过ReportListener的EvaluateContents事件修改域控件的画笔颜色,如果使用了一个非彩色打印机,则可能希望关闭EvaluateContents事件。下面的代码根据复选框的值来决定是否关闭EvaluateContents事件的处理。
oReport = CREATEOBJECT("myReportlistener")
IF THISFORM.chkColorPrinter.Value = .F.
oReport.CallEvaluateContents = 1
ENDIF
REPORT FORM (myreportfile) OBJECT oReport PREVIEW
在SP2之前,在将报表输出到预览窗口后,如果希望打印缓冲区中的报表,只能在关闭预览窗口的情况下执行ReportListener的OnPreviewClose(.T.)方法(参考 12.13.2 节的示例代码)。在SP2中提供了PrintCachedPages方法,如果在预览窗口打开的情况下调用该方法,执行结果OnPreviewClose(.T.)相同。
由于ReportPreview应用程序中已经包含了PrintCachedPages方法,所以可以控制报表预览工具栏中打印按钮的行为。例如,如果希望在用户单击打印后打印预览窗口保持为打开状态,可以在REPORT FORM命令中包含NOWAIT子句。
REPORT FORM (filename) OBJECT oReportListener PREVIEW NOWAIT
从SP2开始,可以在LoadReport方法中读写CommandClauses.File属性,从而提供了在装载报表时修改要打印报表文件的能力。
SP2包含新增的FX和GFX Handlers,以及添加到Properties对话框的新增选项卡,用来配合这些Handlers。这实际上是为用户提供了一个这些Handlers的设计时刻接口。
SP2添加了一个叫做Document Properties的选项卡到Report Properties对话框中,其中显示了一个自定义属性列表,可以从中存储有关文档的附加信息或控制报表的绘制,如图12-100所示。
图12-100 Document Properties选项卡
列表中以HTML开始的属性名称特定于HTML输出,并且当前仅被HTMLListener(包含在_ReportListener.vcx类库中)支持。而所有能够生成文档的ReportListener可以使用其他的属性名称。
例如,如果设置如图12-100中所示的自定义文档属性,则在使用HTML Report Listener绘制报表的情况下,下面的文本将包含在生成的HTML文件中。
<title>My Report</title>
< META name="description" content="My description text">
< META name="author" content="Hong Ju">
尽管这些数据并不显示Web页上,但是在为搜索引擎创建文档索引时这却是有用的信息。在SP2之前,没有一种更有效的方法可以在HTML报表文档中包含这些信息。表12-52列出了对这些扩展属性的简要说明。
可以添加自定义属性到属性列表中,但是它们不能被标准的ReportListener识别,任何新增的自定义属性应当由新的ReportListener或自定义FX、GFX Handler进行处理。
表12-52 内置在新报表设计器中的报表属性
属性 |
说明 |
Document.Title |
为报表文档指定一个标题。对于HTML输出,这会作为一个TITLE标签在所绘制的文档中出现 |
Document.Author |
为报表文档指定作者信息。对于HTML输出,这将以一个META标签出现 |
Document.Description |
为报表文档指定一个说明。对于HTML输出,这将以一个META标签出现 |
Document.Keywords |
指定包含在报表文档中的关键词。对于HTML输出,这将以一个META标签出现 |
Document.Copyright |
为报表文档指定版本信息。对于HTML输出,这将以一个META标签出现 |
Document.Date |
为报表文档指定一个日期 |
HTML.CSSFile |
仅用于HTML输出。为生成的文档指定要使用的外部CSS文件名称 |
HTML.Metatag.HTTP-EQUIV |
仅用于HTML输出。指定一个包含在HTML输出中的HTTP-EQUIV标签 |
HTML.TextAreasOff |
仅用于HTML输出。对溢出伸展字段取消使用TEXTAREA标签 |
SP2向每个控件属性对话框(包括标签、字段、矩形、线条和图片)添加了一个新增的Advanced选项卡,该选项卡提供了一个属性列表,开发者可以自定义报表上的每个对象。如图12-101所示。
图12-101 Advanced选项卡
注意列表中以HTML作为前缀的属性名称在默认情况下仅用于HTMLListener。Advanced选项卡也包含一个Object Rotation控件,使用该控件可以为当前对象指定一个旋转角度。旋转仅在绘制期间发生,因此在报表设计器中并不可见。需要注意的是,HTMLListener不支持旋转,在输出为HTML时,旋转角度会被忽略。
通常情况下,在Advanced选项卡中列出的是与报表控件相关的默认属性。此外,也可以为报表控件设置、新增或删除自定义属性。表12-53列出了对这些默认属性的简要说明。
表12-53 Advanced选项卡中报表控件的默认属性
属性 |
说明 |
HTML.Link |
当以HTML输出运行报表时,该表达式作为控件超级链接的HREF属性 |
HTML.Anchor |
当以HTML输出运行报表时,该表达式作为控件超级链接的name属性 |
HTML.Alt-Title |
当以HTML输出运行报表时,该表达式作为控件<div>元素中的title属性 |
HTML.CSSClass.OverrideFRX |
当以HTML输出运行报表时,ReportOutput应用程序为每个报表元素创建具有格式定义的CSS类。如果在Document Properties选项卡中设置了HTML.CSSFile报表属性,在Report Builder Properties对话框的Report Properties对话框(Report Builder)指定了一个CSS文件,则可以使用HTML.CSSClass.OverrideFRX属性在文件中指定一个CSS类,这会替换由Report Builder创建的格式 |
HTML.CSSClass.ExtendFRX |
如果设置了HTML.CSSFile报表属性到一个CSS文件,则可以使用该属性指定一个类来添加格式特征到由Report Builder创建的格式中 |
HTML.PrintablePageLink |
在HTML报表中,系统为每页创建一个位图文件。对于实际页面,打印位图比HTML更加紧凑。如果将控件的该属性设置为“真”,则该控件则会转换为到该图像的一个超级链接 |
ListenerRef.NoRenderWhen |
当表达式计算为“真”时,所打印页面中将不包含指定对象。ListenerRef是在报表运行时对Report Listener的引用 |
ListenerRef.Preprocess.NoRenderWhen |
当表达式计算为“真”时,在一个多次运行的报表的第一次运行时,所打印页面中将不包含指定对象 |
现有一个如图12-102所示的报表,其中第二列的标题(This is a long column title)超长,为了使其显示的更加完整,可以对该标签控件旋转一定的角度。双击该标签控件,打开其Properties对话框,可以在Advanced选项卡的Object Rotation中单击鼠标左键指定角度,也可以通过下方的Angle微调按钮进行调整。单击OK按钮关闭对话框,并执行下面的命令在预览窗口中打开报表。可以看到第二列的标题发生了旋转,如图12-104所示。
SET REPORTBEHAVIOR 90
REPORT FORM report1.frx PREVIEW NOWAIT
图12-102 示例报表
图12-103 指定标签的旋转角度
图12-104 报表预览效果
但是,在输出到HTML时控件无法进行旋转,第二列的标题仍旧会显示不完整,如图12-105所示。在这种情况下,可以设置在输出到HTML时不输出该标题,而是为下方的域控件添加提示信息,当鼠标指针移动域控件上方时,显示提示信息。
图12-105 将报表输出到HTML时的效果
双击报表中的This is a long column title标签,打开其Properties对话框。选择Advanced选项卡并编辑ListenerRef.NoRenderWhen属性的值为“This.Listener.OutputType= 5 ” ,指定在输出HTML时不输出该控件,如图12-106所示。
双击报表中的contact域控件,打开其Properties对话框。选择Advanced选项卡并编辑HTML.Alt-Title属性的值为“"This column is contact name of customer."”,指定当鼠标指针移动到该控件上时将显示该提示信息,如图12-107所示。
设置完成后,选择File菜单中的Save As HTML菜单项或执行下面的命令输出报表到HTML,执行结果如图12-108所示。
SET REPORTBEHAVIOR 90
oListener = CREATEOBJECT('ReportListener')
oListener.ListenerType = 5
REPORT FORM report1.frx TO FILE report1.htm OBJECT oListener
RUN report1.htm
图12-106 设置This is a long column title标签不输出到HTML
图12-107 设置控件输出到HTML时的提示信息
图12-108 在输出到HTML时未输出第二列的标题,并且为第二列中的控件添加了提示
如果为报表中的某个控件设置了HTML.PrintablePageLink属性,则将报表输出到HTML的同时会为每页生成一个GIF文件,并且每页上的该控件会链接到相应的GIF文件。例如,在上面所设计报表的基础上添加一个标签控件,并双击该控件打开其Properties对话框,在Advanced选项卡中双击HTML.PrintablePageLink属性,将属性值改变为Yes,如图12-109所示。
设置完成后,按照前面介绍的方法将报表输出到HTML中,可以看到所添加的标签变成了一个指向当前页面GIF文件的超级链接,如图12-110所示。
图12-109 将控件设置为到GIF图像文件的链接
图12-110 可以链接到GIF文件的报表
SP2向Field、Rectangle和Picture控件的Properties对话框添加了一个Dynamics选项卡,该选项卡为在报表运行期间动态改变报表对象的属性提供了一个Conditions(条件)列表。仍旧以前面建立的report1.frx报表为例,我们将使用该功能动态改变控件的背景,以实现报表中的奇偶行使用不同颜色显示。
双击报表中的company域控件,打开其Properties对话框。单击Dynamics选项卡中的Add按钮,在打开的对话框输入新条件的名称并单击OK按钮,将打开Configure Dynamic Properties对话框,可以从中设置一个条件表达式和一系列控制属性。对于域控件,可以改变字段的文本、字体、颜色、背景类型和透明层级,但是注意这些属性可以被ReportListener中的EvaluateContents事件覆盖。对于形状和图片控件,Dynamics选项卡允许覆盖控件的宽度和高度,但是注意这些属性会被ReportListener中的AdjustObjectSize事件覆盖。
该示例的详细设置步骤如图12-111所示。
图12-111 Field对象的Dynamics选项卡和Configure Dynamic Properties对话框
预览报表,效果如图12-112所示。
图12-112报表中的奇偶行使用不同背景颜色显示
ReportListener不断地计算动态条件并处理所设置的条件,实际上是在执行一个CASE语句。单击Dynamics Properties选项卡的Script按钮,可以看到这个CASE语句。下面就是该示例的代码,我们为条件指定的名称RedBar被放在了注释中。
LPARAMETERS m.toListener, m.tP1, m.tP2
* generated user-dynamic code
* for EvaluateContents method
* FRXRECNO: 6, EXPR: CUSTOMER.company
* the following code translates from the standard
* fxMemberDataScript.ApplyFx parameters, which are used
* so you can cut and paste the CASEs below into
* Memberdata standard script later if you want to
LOCAL m.nFRXRecno, m.oProps
m.nFRXRecno = m.tP1
m.oProps = m.tP2
m.oProps.Reload = .T.
TRY
SET DATASESSION TO (m.toListener.CurrentDataSession)
* Conditions are evaluated in the Current (Report) datasession.
DO CASE
CASE RECNO()%2 = 1 && user condition: RedBar
* Additional items use literal values.
m.oProps.FillRed = 255
m.oProps.FillGreen = 128
m.oProps.FillBlue = 128
m.oProps.PenAlpha = 255
m.oProps.FillAlpha = 255
m.oProps.FontName = "Arial"
m.oProps.FontStyle = 0
m.oProps.FontSize = 9
OTHERWISE && default result from FRX definition
m.oProps.Reload = .F.
ENDCASE
CATCH WHEN .T.
m.oProps.Reload = .F.
FINALLY
SET DATASESSION TO (m.toListener.FRXDataSession)
ENDTRY
我们知道,在使用CASE语句的情况下,在遇到计算为“真”的第一个条件时,就会执行其下的语句,因此条件的顺序十分重要。Dynamics选项卡中的Conditions列表框提供了移动块来允许调整条件的顺序。
这些新增选项卡用于为每个对象在FRX中存储附加属性,如果一个对象需要的属性在FRX中没有相应的字段,则应当在对象的MemberData中存储这些附加属性。
MemberData是一个存储在FRX的style列中的XML字符串,在Visual FoxPro 9.0中包含MemberData,是为保持FRX的向后兼容性而提供的一种扩展方法。
在设计时刻可以通过控件的Properties对话框的上下文菜单来查看或编辑MemberData,在对话框上单击鼠标右键,在显示的上下文菜单中选择Object MemberData的Browse或Edit XML子菜单,如图12-113所示。
图12-113 在控件的Properties对话框允许查看对象的MemberData
下面是在前面所设置的company域控件的XML MemberData,用于以红色背景报表中的奇数行。
<VFPData>
<reportdata
name="Microsoft.VFP.Reporting.Builder.EvaluateContents"
type="R"
script=""
execute="RedBar"
execwhen="RECNO()%2 = 1"
class=""
classlib=""
declass=""
declasslib=""
penrgb="-1"
fillrgb="8421631"
pena="255"
filla="255"
fname="Arial"
fsize="9"
fstyle="0"/>
</VFPData>
Visual FoxPro 9.0帮助文件中的Report XML MemberData Extensions主题详细描述了MemberData应用于报表时的信息。
FX和GFX Handler类位于_REPORTLISTENER.VCX(位于Visual FoxPro 9.0的FFC目录中)中,包含隐藏在上述新增选项卡后面的所有绘制功能。类名称以FX或GFX开头。
Visual FoxPro 9.0为报表引擎引入了Handler注册数据表,SP2扩展了该数据表的功能,可以允许向控件的Properties对话框添加自定义选项卡。
自定义Properties选项卡创建起来相对容易一些,它基于Visual FoxPro的Page类,并且应当至少要包含一个Container对象。这个Container对象应当至少包含两个方法:LoadFromFRX和SaveToFRX,Visual FoxPro在打开和关闭自定义Properties对话框时相应地调用这些方法。然后Visual FoxPro使用这些方法来插入代码,读取和更新下面被编辑报表对象的frx记录。下面的代码(该类存储在MyRptClass.prg)演示了创建自定义选项卡的方法。
DEFINE CLASS myCustomTab AS Page
Caption="我的自定义选项卡"
ADD OBJECT oContainer AS myContainer WITH ;
Top=10, ;
Left=10
FUNCTION RightClick()
*!* 添加对上下文菜单的支持
This.Parent.RightClick()
ENDFUNC
ENDDEFINE
DEFINE CLASS myContainer AS Container
Width=400
Height=400
ADD OBJECT txtUser AS EditBox WITH ;
Top=10,;
Left=10, ;
Width=380,;
Height=380
PROCEDURE LoadFromFRX
*!* 从user字段装载编辑框的值
This.txtUser.Value=frx.user
ENDPROC
PROCEDURE SaveToFRX
*!* 如果改变了值,则更新user字段
IF NOT frx.user==This.txtUser.Value
REPLACE user WITH This.txtUser.Value IN frx
ENDIF
ENDPROC
ENDDEFINE
在上面的LoadFromFRX和SaveToFRX方法中,可以见到一个对frx的引用。从前面章节的介绍中我们知道,frx是一个报表的副本,以表的形式在独占环境中打开。任何对frx的更新可以在SaveToFRX方法中进行保存。
要添加自定义选项卡到控件的Properties对话框,应当在所需的注册数据表中添加一个词条,这可以通过打开Report Builder Options对话框进行编辑。要显示该对话框,应当执行如下的命令:
DO (_REPORTBUILDER)
在对话框打开后(如图12-114所示),应当注意当前访问的注册数据表不能是内部版本(该版本编译在REPORTBUILDER.APP)中。选择Use alternative lookup table选项并单击Create Copy按钮创建一个新表,然后单击“…”按钮并定位到新表。在默认情况下,外部注册表位于与REPORTBUILDER.APP相同的目录中(一般是VFP9.EXE的起始目录)。
图12-114 使用Report Builder Options对话框指定Handler Registry表
一旦选择了外部表,可以单击Registry Explorer来显示Event Registry Handler对话框。该对话框包含一个为报表引擎作为自定义Handler注册的类的列表。要添加一个新增记录,单击Add New按钮。要注册在上面myCustomTab类中定义的选项卡,可以在高亮度记录处输入下列值,最终结果如图12-115所示。
Type: T(选项卡)
Class: myCustomTab
Library: MyRptClass.prg
Event: -1(所有事件)
Objtype: -1(所有对象)
Objcode: -1(所有对象变量)
图12-115 myCustomTab的Event Handler设置
要了解表中每列的更多信息,可以单击列标头,将出现一个快速参考对话框,描述了该列每个值所代表的类型,如图12-116所示。
一旦设置了注册词条,关闭报表生成器对话框。然后在报表设计器中打开任意报表,在报表中打开任意对象或带区的控件Properties对话框,则对话框将具有一个名为“我的自定义选项卡”的新选项卡,如图12-117所示。自定义选项卡中的编辑框将显示并更新当前所选择控件或带区的frx的user列。
图12-116 Objtype列注册值的快速参考对话框
图12-117 “我的自定义选项卡”显示在Report Properties对话框中