分享

VFP 高级教程:VFP 开发技巧

 悟静 2009-06-21

本章说明

本章共分十一节。阐述了与VFP工作环境有关的细节问题,其中一至七节为一般描述适用于一般使用者,第八、九两节适用于中、高级开发者,第十节是四个具体的实例,可用于任何应用程序,第十一节是"选项"对话框的说明性表格,是手册性质的资料。

第一节 概述

工作环境规定了 VFP 工作时的某些行为。配置工作环境意味着您可以通过某些方法使 VFP 的行为满足自己的需要 - 必须的或者是某些个人偏好的。

与任何完善的开发工具一样,VFP 也是一个复杂的系统,复杂的一个方面就表现在它具有极大的灵活性 - 同一种工作,由于"环境"的不同,可能会产生不同的效果。

工作环境是个整体的概念,我们使用"环境参数"一词来描述构成工作环境的个体。那么就可以说,工作环境就是由一组环境参数来决定的,配置工作环境就是设置这组环境参数,以满足不同的需求。这显然有两方面的任务,第一、您要知道有那些环境参数,第二、明确怎样配置这些参数。

工作环境涉及到很多方面,例如输入输出、数据处理、开发、调试等等。可以通过分类对所有环境参数进行描述。所有的环境参数都有一个原始的默认值,一般的环境配置工作,事实上只需要修改少量的环境参数即可。

有一个问题需要明确,"VFP 的工作环境"是指 Visual FoxPro 工具的开发环境。另外一种情况,使用 VFP 开发的应用程序,在编译成执行文件后,工作在 VFP 运行时的工作环境下。这两者是有区别的,显而易见的区别是,运行时环境涉及的问题比开发环境少得多,例如开发、调试方面的问题。一般来讲,运行时的环境是开发环境的一个子集,但严格说来这是不对的,二者仍存在一些差别,不仅在环境参数的类别与数量方面,也存在于配置方法上。本文的叙述主要针对开发环境而进行,对二者存在的差别也将被提及。

[dvnews_page=VFP 高级教程:VFP 开发技巧]

第二节 默认的工作环境

VFP 安装完成后,其"内部"保存着对所有环境参数的设置,这些参数可以称做是原始设置。您永远也不能够去修改这些原始设置。但 VFP 提供一种机制允许您每次启动时用自己的设置去覆盖这组原始设置。方法是是使用 Windows 注册表及配置文件。

启动时,VFP 首先会检查 Windows 注册表中的有关设置,然后据此修改环境参数。然后还会查找一个配置文件,该文件默认的名字为 config.fpw,其中也存放着一些环境配置信息。VFP 将读取这些信息,并再次修改环境参数。如果 VFP 在Windows 注册表中没有找到配置信息或者没有找到配置文件,这没有关系,VFP 将以原始配置进行工作。您甚至可以主动让 VFP 在启动时放弃读取注册表及配置文件。

VFP 不会主动把环境参数写进 Windows 注册表中,但它提供了一种方法使您方面地将环境参数写进注册表,写入不仅针对修改过的参数,而是所有参数,您没有去修改的参数值将以原始值写入。配置文件则不同,它只保存您写入的参数,某种意义上,它相当是一份注册表中的环境参数表的勘误。

保存在 Windows 注册表中的环境参数以及配置文件中的设置称做"默认工作环境"

第三节 配置文件

先读取注册表再查找配置文件的方法似乎有点复杂,但有些时候需要这样做,例如工作在运行时环境的应用程序,启动时不去读取注册表,这使得配置文件成为必须。另外,配置文件创建于 FoxPro 的早期版本,兼容性使它必须被保留。VFP6 以前的版本在安装时将自动建立一个这样的文件(在安装目录下),而到了 VFP6,系统不再自动建立该文件,需要时由用户自行建立。该文件是一个文本文件,可以使用任何文本编辑器来建立它。

VFP 启动时将按照下列路径查找该文件: 当前工作目录 安装 Visual FoxPro 的目录 DOS 路径中列出的目录 配置文件有默认的名字(config.fpw),"默认"意味着你可以去改变它。这有利于您同时拥有多个配置文件,以便满足不同的需要。指定另外不同于config.fpw名字的配置文件的方法是在启动 VFP 时增加命令行开关项,例如 VFP6.EXE -Cc:\myprg\myconfig.fpw

配置文件中不仅仅存放环境配置信息,例如可以在配置文件中设置 VFP 启动后立即去执行一个程序文件。这使得您可以在配置环境方面使用一种技巧,即将环境设置命令保存在一个程序文件中,然后让 VFP 启动时去执行它。

启动过程也可以通过使用命令行参数来定制,通过定制启动过程,可以得到不同的环境默认设置,以下是对环境配置有影响的一些情况:

 

开关 描述
-A 忽略默认配置文件以及 Windows 注册表设置
-C 放弃使用配置文件。
-c<文件> 指定默认配置文件 (Config.fpw) 之外的配置文件(必要时包含路径)。

[dvnews_page=VFP 高级教程:VFP 开发技巧]

 

第四节 更改默认设置

VFP 启动完成后,工作环境被设置成默认状态。您可以即时地更改环境参数,这有几种方法,各种方法可能适合于不同的情况。

交互式修改

在命令窗口输入环境设置命令,执行后该修改会立即生效。绝大部分的环境参数是通过 SET 命令设置的,另外还有一些通过系统变量存储以及极少数的函数设置。在早期的XBASE 工具中,例如dBASEII中,仅有 20 几条 SET 命令,而今天,VFP 中已经有 120 多个 SET 命令了。交互式的修改方法是枯燥的,因此只用于临时性的修改,例如调试等。

程序化执行修改

可以将一组环境设置命令组织成一个程序文件,运行该程序,就相当于在命令窗口一一输入执行了这组命令,有些情况下是需要这样做的,例如在开发环境下同时调试多于一个项目的时候。可以将该环境设置程序存为一个过程或直接写在项目的主文件中。事实上,对于应用程序,因为最终要脱离开发环境运行,所以大部分都是这样做的。

用命令方式读取Windows 注册表中的设置

让 Visual FoxPro 再次读取自己的注册表设置,并且使用当前的注册表设置更新自己。 语法为: SYS(3056 [,1]) 说明:包含1选项可以只根据注册表设置进行更新,不包括 SET 命令和文件位置。Visual FoxPro 在 Windows 注册表的选项对话框中保存设置。当Visual FoxPro 启动时,读取这些设置,并利用这些设置进行配置。SYS(3056)可更新包含有文件名和路径的系统变量,而系统变量由SET命令和注册表设置。当您选择设置为默认值时,选项对话框指定的设置写入注册表。其中一些影响Visual FoxPro环境的设置含有SET 命令,例如SET BELL,SET LOCK等。注意 SYS(3056)不更新来自Config.fpw(即 Visual FoxPro 配置文件)的设置。

有关环境设置的命令

有很多环境设置的命令,在本文的附表中,以"选项"对话框中的分类列出了相应的环境设置命令,还有一些命令没有包含在"选项"对话框中,但它们也是关于环境的设置命令,本文仅将它们列出来,具体的意义及语法可参见随机文档。

 

SET ALTERNATE SET ASSERTS SET AUTOSAVE
SET COLOR OF SCHEME ET COLORS SET SET CONSOLE
SET COVERAGE SET CPCOMPILE SET CURSOR
SET DEBUG SET DEBUGOUT SET DEVICE
SET DISPLAY SET EVENTLIST SET EVENTTRACKING
SET FIXED SET FULLPATH SET FUNCTION
SET MACKEY SET MEMOWIDTH SET NULL
SET NULLDISPLAY SET OLEOBJECT SET PRINTER
SET READBORDER SET SPACE SET STATUS
SET SYSMENU SET TEXTMERGE SET TEXTMERGE DELIMITERS
SET TYPEAHEAD    

 

无论是交互式还是程序化执行命令,其修改都是临时的,只对当前工作有效,VFP 系统关闭后,这种修改不能被保存,下一次运行,如果需要同样的设置,您不得不再一次输入该命令或执行该程序。要想使修改成为永久,必须将修改保存在 Windows 注册表中或构建配置文件。

修改注册表

有两种方法:直接修改 Windows 注册表或使用 VFP 开发环境提供的"选项卡"对话框。对于直接修改 Windwos 注册表的方法,没有人会建议您这样做,除非您首先对 Windwos 注册表的结构非常熟悉,其次对 VFP 在 Windows 注册表中的各种参数的意义比较了解,第三有某些特殊需要以至于不能使用常规的方法完成。常规的方法,是使用 VFP 的"选项卡"对话框来完成环境配置。

直接修改注册表

VFP 环境设置信息在 Windows 注册表的目录如下: HKEY_CURRENT_USER\Software\Microsoft\VisualFoxPro\6.0\Options 主键名称在本文附表中有详细介绍。

使用"选项"对话框

使用"选项卡"对话框来进行系统的配置比直接修改 Windows 注册表的方法至少有两个好处,第一,很多配置参数在"选项卡"上是以一种"易于理解的方式"表达的,您只需在某些"问题"前打勾或者在很多答案中选择一个,这就象您填一份表格一样来得轻松。第二,在"选项卡"上进行的配置,一旦完成后,立即生效,而直接修改 Windows 注册表的方法却不是这样,只能是在下一次运行 VFP 时生效。

在开发环境下,执行"工具"菜单中的"选项"菜单项,会出现"选项"对话框。对话框上有12个卡页,分12个方面对环境进行配置。本文附表中详细描述了其中的每一项设置。事实上,真正需要修改的并不多,很多项设置,原始值应该能满足要求。现在的问题是,当你修改完成后,可有两种选择,按"确定"按钮退出对话框,您的修改只会保存在当前环境中,随着系统的关闭而失效;按"设置为默认值"按钮退出对话框,当前的设置将会被写进 Windows 注册表从而成为新的默认值。
[dvnews_page=VFP 高级教程:VFP 开发技巧]

第六节 ON命令

ON ERROR 命令

设计得再好的程序,在运行时也不可避免地会发生错误,这些错误可能是程序自身的错误,也可能是系统环境引起的或是用户错误地操作(如错误地移动/删除文件等)引起的等。

因此,程序员有责任编写出可以捕捉错误的程序并尽可能地处理这些错误。要捕捉程序中发生的错误使用 ON ERROR 命令。你可以在 ON ERROR 命令后跟随一个错误处理程序的名字:ON ERROR DO ERRORHANDLER,或者在 ON ERROR 命令后跟随一条赋值语句:ON ERROR glError = .T.。

注意,在程序中全程使用类似于ON ERROR glError = .T.的命令是极不负责任的和令人憎恶的,这有可能会使用程序陷入死循环而使用用户不得不强行退出系统(强行关断电源等),这样做极有可能破坏用户的数据文件。

ON ESCAPE 命令

指定在程序或命令运行过程中,按下 ESC 键时所执行的命令。

语法为:ON ESCAPE [Command]

ON SHUTDOWN 命令

指定当试图退出 Visual FoxPro 时所要执行的命令。

语法为:ON SHUTDOWN [Command]

第七节 一些重要的设置

以下是几乎每一个应用程序都要进行的设置:

_VFP 系统变量

指向当前运行的Visual FoxPro应用程序对象。

语法
_VFP.PropertyName[=eValue]
-或-
_VFP.Method

参数描述
PropertyName 指定应用程序对象的属性。

eValue 指定属性的值。Method指定应用程序对象的方法。

说明

通过_VFP,您可以访问对象集合(Objects collection)。

可设置的属性有:

 

ActiveForm Application AutoYield
Caption DefaultFilePath Forms
Full NameHeight Left
Name OLERequestPendingTimeout OLEServerBusyRaiseError
OLEServerBusyTimeout Parent StartMode
StatusBar Top Version
Visible Width  

 

SET SAFETY

决定改写已有文件之前是否显示对话框,或者决定当用表设计器或用 ALTER TABLE 命令对表结构进行修改后,是否重新计算表或字段规则、默认值以及错误信息。 语法为:SET SAFETY ON | OFF

SET PROCEDURE TO

设置运行时的命令文件

SET CLASSLIB TO

设置运行时的类库文件

SET MEMOWIDTH TO

指定备注字段和字符表达式的显示宽度。

语法为:SET MEMOWIDTH TO nColumns

SET MULTILOCKS ON

决定能否使用 LOCK ()或 RLOCK () 锁定多个记录。

语法为:SET MULTILOCKS ON | OFF

若要在程序中使用表缓存必须设置SET MULTILOCKS 为 ON。

SET HELP TO

激活或废止 Visual FoxPro 联机帮助或指定的帮助文件。

语法为

SET HELP ON | OFF

- 或者 -

SET HELP TO [FileName]

SET DELETED

指定 Visual FoxPro 是否处理标有删除标记的记录,以及其他命令是否可以操作它们。

语法为:SET DELETED ON | OFF

SET EXCLUSIVE

指定 Visual FoxPro 在网络上以独占方式还是共享方式打开表文件。

语法为:SET EXCLUSIVE ON | OFF

SET NOTIFY

确定是否显示某种系统信息。

语法为:SET NOTIFY ON | OFF

SET BELL

关掉或打开计算机铃声,并设置铃声属性。

语法为:

SET BELL ON | OFF

- 或者 -

SET BELL TO [nFrequency, nDuration | cWAVFileName, nDuration]

SET NEAR

FIND 或 SEEK 查找记录不成功时,确定记录指针停留的位置。

语法为:SET NEAR ON | OFF

SET EXACT

指定比较不同长度两个字符串时,Visual FoxPro 使用的规则。

语法为:SET EXACT ON | OFF

SET CONFIRM

指定是否可以用在文本框中键入最后一个字符的方法退出文本框。

SET ESCAPE

决定是否可以通过按 ESC 键中断程序和命令的运行。

语法为:SET ESCAPE ON | OFF

SET DATE

设置日期格式

语法为:SET DATE [TO] AMERICAN | ANSI | BRITISH | FRENCH | GERMAN | ITALIAN | JAPAN | USA | MDY | DMY | YMD

SET CENTURY

设置是否在日期的年中显示世纪值

语法为:SET CENTURY ON | OFF

ON SHUTDOWN DO

指定当试图退出 Visual FoxPro 时所要执行的命令。

语法为:ON SHUTDOWN [Command]
[dvnews_page=VFP 高级教程:VFP 开发技巧]

第八节 进一步订制VFP的向导和生成器

作为最好的数据库管理系统,VFP 给我们提供了高度的可自定义的交互式的开发环境(interactive development environment IDE)。你可以修改菜单,安装新的生成器和向导,实现开发工具条,修改项目管理器的行为,以及很多其它事来使你的IDE 更高效。这些定制甚至比我们所知道的和喜欢的VFP语言更好,连相对不熟炼的VFP 开发者都可以按他们自己的方法定制开发环境。

本节将配合实际程序示例,向你展示如何建立简单的工具增加你和你的开发组的效率。我们将着眼于修改VFP 的向导和生成器来提供额外的或自定义功能,并使用VFP 6中的BuilderD 技术创建你自己的生成器。

修改VFP 的向导和生成器

如果你象我一样,你可能不常用VFP 的生成器和向导,因为它们不完全能满足你的需要。可能它们不具备足够的灵活性或可能你只是不喜欢他们的工作方式。直到VFP 6以前,没有办法改变生成器和向导的行为,因为Microsoft 没有提供源代码。但是,现在我们不但获得了生成器和向导的源代码,也获得了类浏览器,组件管理器的源代码。

生成器和向导的源代码可以在VFP主目录下的TOOLS\XSOURCE目录中的XSOURCE.ZIP 文件中找到。当你解压该文件时,它建立一个VFPSOURCE 目录,其中包含了所有的源代码。向导的源代码 可以在WIZARDS 目录下找到,生成器的在BUILDERS目录下 (虽然一些WIZARDS目录中的公共文件也被生成器使用)。

因此,现在我们有了源代码,我们可个按我们的需要来修改生成器和向导,对吗? 好了,一个较好的办法是建立新的生成器和向导时,使用源代码中的大多数类和程序,但以派生子类并复制和修改PRGs 或建立封装PRGs的方法来忽略他们原有的行为。本文将详细说明如何对各生成器和向导这样做。

一但你建立了你自己的生成器和向导,怎样告诉VFP 使用你的而不是原来的吗? 生成器是注册在BUILDER.DBF 且向导是在WIZARD.DBF中,两个表都在VFP主目录下的WIZARDS 子目录中。这些表具有相同的结构,如下表所示。

 

 

字段 描述
NAME 生成器或向导描述名。
DESCRIPT 生成器或向导的说明。
BITMAP 未使用。
TYPE 生成器或向导是对哪一对象类型的。在BUILDER.DBF情况下,它一般是一个对象的基类(虽然已有以MULTISELECTAUTOFORMATRI 字段)。对于WIZARDS.DBF,它可能是FORMREPORT,和 QUERY
PROGRAM 包含生成器和向导的APP 文件名。
CLASSLIB APP文件中要实例的类。
CLASSNAME APP文件中的主要类的类库。
PARMS 传递到生成器或向导的参数。

 

表 1. BUILDER.DBF 和 WIZARD.DBF的结构

当你调用一个生成器时,VFP 调用_BUILDER 系统变量中指定的程序 (默认是BUILDER.APP)。BUILDER.APP 查看它所在的环境 (例如,生成器是被那一个对象调用),在BUILDER.DBF 表中查找与环境匹配的记录 (例如,在TYPE 字段中查找对象的基类),并调用注册后的生成器。除系统变量_WIZARD外,向导也是以相同的方法处理,_WIZARD是用于指向可在WIZARD.DBF找到的WIZARD.APP。

要告诉VFP 使用一个不同的生成器或向导,插入一条说明如何运行你的生成器或向导的新记录到BUILDER.DBF或 WIZARD.DBF表中。如果你想在运行新的向导或生成器的同时也可以选择运行原有的生成器或向导,在WIZARD.DBF表中保留原有的生成器或向导记录。如果你想替换原有的,简单的修改它的TYPE值为另外的值(我使用一个"X"前缀,如 "XGRID"),而不是删除该记录;

使用该方法,你可以简单的以恢复TYPE 的值来恢复使用原来的生成器或向导。 我们将考查创建一个Grid 生成器的替代物,参照完整性生成器,Upsizing 向导,和WWW 搜索页向导。

创建更有用的Grid 生成器

VFP Grid 生成器提供了一种快速方法来整合grid 的列并建立你所希望的视觉外观。但是,关于该生成器,有我所不喜欢的一些东西:

  • 它不会自动调整列的宽度。必须自己调整列的宽度以适应数据宽度的需要。
  • 在生成器的外观页面中的控件类型组合框只列出了已存在于列中的VFP 基类和类; 没有办法添加你自己的类到该列表中。
  • 它创建的列和列头是VFP 的基类。你也许想用你自己的类替代它(必须是以编程的方式定义的),例如,单击一个列头而按该列排序。

要建立一个VFP Grid 生成器的替代物,首先建立了SFGRIDBLDR 项目(它在你解压该文档所附的示例程序时建立的GRID 子目录中) 并添加以下文件: BUILDER.VCX (在VFP 向导源目录中的BUILDERS\BUILDERS 子目录中),GRIDBLDR.VCX (在 BUILDERS\GRIDBLDR 目录中),THERM.VCX,WIZCTRL.VCX,WIZMOVER.VCX (所有都在WIZARDS\WZCOMMON目录中),DUMMY.PRG,和 WBGRID.PRG (在BUILDERS目录中)。我如何知道要添加那些文件到项目中呢? 这很简单:只需要查看GRIDBLDR 项目的内容。

其次,派生GridBuilder 类到SFGridBuilder (在 SFGRIDBLDR.VCX类库中) 并复盖ResetColumns 方法,该方法用于调整选定列的宽度到适当的大小 (我只实现了该想法,未实现上述列表中的其它两个)。该方法的代码在下面列出。这里要注意两个有趣的东西。首先,我希望写很多复杂的代码,根据字段宽度、字体和字号来计算出列的宽度,等等。有趣的是,它放弃了生成器中已存在的任务的方法 (SetColWidth),而只是传递字段宽度到该方法中,生成器传给它一个不同的值。其它事情是分配到loColumn。Width 的计算宽度被注释了。理由是我还没有调试好,改变列宽后,当生成器关闭时,会造成问题,所以我把列宽设置为,列宽是保存在wbaCols中。(如果你需要,wbaCols 是一个公共数组。我没有创建生成器,因此不要责怪我采用这种方式)

因此,效果是当一个字段添加网格中时,它没有立即获得适当的列宽,但是一但你执行了一些其它操作 (添加另一个字段,转到生成器的另一个页面中,关闭生成器等等。)它就会取得适当的列宽。

 

local lnRows, ;
  lnI, ;
  lcField, ;
  loColumn, ;
  lcHeader, ;
  loHeader
dodefault()
lnRows = alen(wbaCols, 1)
for lnI = 1 to lnRows

  lcField = wbaCols[lnI, 2]
  if not empty(lcField)
    loColumn = evaluate('wbaControl[1].' + ;
      wbaCols[lnI, 7])
    wbaCols[lnI, 1] = This.SetColWidth(fsize(lcField), ;
      loColumn)
    * loColumn.Width = wbaCols[lnI, 1]
  endif not empty(lcField)
next lnI

 

最后我为我的生成器建立了GRIDMAIN.PRG (使用了BUILDERS\GRIDBLDR 中的GRIDMAIN.PRG 的办法) 并使它成为项目的主文件。该程序用SET CLASSLIB命令添加SFGRIDBLDR.VCX 到打开的类库中,这样它可以找到我们的SFGridBuilder 类。GRIDMAIN 也自动注册它自己到VFP BUILDER 表中(如果是直接运行该APP 文件)。

要查看该生成器的行为,建立并运行SFGRIDBLDR.APP 来作为grids生成器注册它。如果你在运行该APP后,观察观查BUILDER.DBF,你会发现它是"未注册的" ,原始的grid 生成器的 TYPE 字段由"GRID" 改成了"XGRID" 并在它后面为它自己添加了一条TYPE 字段为"GRID"的新记录。下一步,新建一个表单,拖动grid 到表单中,并调用生成器。新的生成器看起来与原来的没有任何区别,但是当你添加字段到表格时,你会发现字段宽度自动调整到了适当大小。

创建一个更好的参照完整性生成器

我有一小点关于VFP自身的参照完整性(RI)生成器的问题:

  • 当你单击确认按钮来保存修改后的RI 时,它两次(而不是一次)让你确认。不是我太自信,但是我相信取消按钮的用途是允许我们返回; 我单击确认按钮因为它是确认,因此我不需要一条 "你真的,真的确认你要这样做吗" 的确认对话框。
  • 在你压缩数据库前,你不能运行RI 生成器。
  • 我确实砂需要它备份我的当前的储存过程为一个叫做RISP.OLD的我总是要自己删除它的文件。
  • 生成的代码中至少有一处BUG ,应该用正确的功能来防止它。关于该BUG的细节,参见"VFP中的错误处理一文"。
  • 它生成的代码既多又缺少注释。要试着理解这些代码是做什么的是一个艰苦的过程,而且如果是在一个复杂的数据库中,RI 代码可能超过VFP 编译后的代码的64K 限制。如果你看过Jim Booth 和 Steve Sawyer写的 "Visual FoxPro 6.0应用程序开发的有效技术" 一书,你会有一个较好的快速,简洁的子程序来维护RI。Steve的 NEWRI 子程序是数据驱动的,因此它是在运行时而不是在生成时检查哪些规则需要强制执行。结果是清楚的,紧密而不是VFP RI生成器生成的大实用的代码。
  • 它所支持的规则仅是忽略、级联和限制。你所需要的其它选项又怎样呢,例如无效(设置子表的外部关键字为.NULL.) 或指定一个新值 (设置外部关键字为的默认值)?

修正这些项相对容易些,因为我们有RI 生成器的源代码。我建立了SFRIBUILDR.APP,一个 VFP RIBUILDR.APP的替换物。我没有实现附加的规则 (上面提及的最后一项) 但是我处理了其它的所有项。我首先建立了SFRIBUILDR 项目(它在解压后的程序的主目录下的RI 目录中) 并添加了VFP的RIBUILDR.VCX(在VFP向导源程序所在目录下的BUILDERS\RIBUILDR 目录中)。

接着,我派生VFP RI生成器类到 SFRIBUILDR.VCX 类库中的SFRIBuildr。我忽视(overrode)了Load 方法以便在数据库中有被删除的记录时不会发生错误 (你可以参见我注释的已存在的代码)。我忽视了确认按钮的Click 方法,以便不出现确认对话框和不复制当前的储存过程到RISP.OLD中,并修复了生成的代码中的错误。同时,如果它检查到NEWRI.PRG 存在于你的系统中 (与SFRIBUILR.APP在同一目录),它会把该代码放入数据库的储存代码中而不会生成其它代码。这个修改需要一个新的方法 RIMakeNewTr用一个不同的名字建立触发器(__RI_Handler) 而不是原来的RI 生成器的生成的(__RI_<action>_<table>,如__RI_Delete_Customer)。因为这些方法中有大量的代码,在这里就不写出来了; 但是,如果你查看提供的源代码,你会看见我确实只注释了很少的代码行,并添加了很少的代码。

最后,我从BUILDERS\RIBUILDR目录中复制RIMAIN.PRG 到我的生成器所在的目录,添加它到项目中,并使它面为主程序。我修改了该程序所指向的类库,使它能找到我的VFP RI 生成器类的子类所在的类库 (SFRIBUILDR.VCX) 并自动注册该生成器到VFP BUILDER 表中(如果是直接运行该APP)。

生成并运行SFRIBUILDR.APP 导致该文件作为RI生成器注册取代了通常的RIBUILDR.APP。要看这一点,按以下步骤进行:

  • 移动本文附带的示例文件到WIZARDS\RI 目录。
  • 如果你有Steve的 NEWRI.PRG,将其复制到该目录。
  • 运行COPYDEMO.PRG。该程序将复制VFP TESTDATA 数据库到DATA 目录中,这样我们不会改动原始的数据库。
  • 运行 DELETETEST.PRG。这会演示一个VFP RI 生成器生成代码的流程。第一次浏览显示ALFKI 客户的几个订货,然后试着删除该客户。因为CUSTOMER 到 ORDERS 表间存在着级联删除,且ORDERS 到 ORDITEMS表间的规则为限制,该客户将不能被删除。但是,请注意错误对话框出现了六次(而不是你所希望的一次) ,然后另一个浏览显示该客户已被删除(CUST_ID 是 .NULL.)。
  • 因为我们已经把数据弄乱了,再一次运行COPYDEMO.PRG重新复制TESTDATA 数据库到DATA 目录中。
  • 以独占方式打开DATA\TESTDATA数据库
  • 生成并运行SFRIBUILDR.APP 来注册它为RI 生成器。
  • 打开数据库设计器,选择修改参照完整性,然后在RI 生成器对话框中,单击确认按钮。注意没有出现确认对话框。选择修改储存过程并注意代码的不同(如果你有NEWRI.PRG,该代码会放入储存过程中; 否则,生成的RIDelete 和 RIUpdate 方法代码中的bug 已修正)。如果你有Steve 的 NEWRI.PRG,修改CUSTOMER 表,并注意各触发器方法的名字。同时,你不会看到RISP.OLD 文件了。
  • 再次运行DELETETEST.PRG。这一次,你只会看到一次错误信息且ALFKI 客户没有被删除。

创建一个更好的升迁(Upsizing) 向导

Jim Falino 在使用升迁向导时失败了,因此他创建了一个具有他所希望的行为的版本。

  • 向导在每一个具有至少一个数值,浮点,通用 或备注字段的表中,建立一个timestamp 字段。Jim 不希望向导自动建立任何timestamp 字段,因此他移去了该功能。
  • 向导为具有主关键字段的表自动建立一组索引。这在有时是令人满意的,Jim 决定在默认情况下不建立组索引,因此在建立主关键字时,他加入了NONCLUSTERED 子句。
  • 由于数据库对象名字在SQL Server 中必须唯一,对于具有非唯一名的东西不能升迁。例如,如果你为多个表的主关键字段建立了相同索引名的索引则你不能升迁关键字索引 (如使用"ID" 为每一个表的主关键字段)。Jim 的方案是重命名主关键字索引为UQ_<table name>,因为名字在在 SQL Server中是不重要的。
  • 可用的表的列表框滑有排序; 表出现的顺序是它们在DBC中的顺序。在一个拥有上百个表的DBC中,要找到一个特定的表是件痛苦的事。Jim 设置了SuperMover 对象的SortLeft 属性(用于指明左边的列表框是否需要排序) 为 .T.
  • 向导可以为DBC中的每一个表,用相同和定义建立一个远程视图。但是,但是它命名视图与原表同名,并重命名表为一个唯一名。由于有些人喜欢对视图使用命名约定(例如,在原表名前加上一个"V"),Jim 修改了向导中的这一点。
  • Jim 修复了一个问题:向导有时会重新排列字段复合索引的顺序。
  • VFP 数值型字段类型升迁为浮点型,即使 SQL Server 中有数值型数据类型也一样。这致使VFP中多于两位小数的数值型字段被截短,并且 VFP 数值字段没有小数点的会升迁为两位小数。

Jim 的修改是让用户指定他们的要求; 你可以使用它们如果你的需要与之相同,或将他们作为模板使用以便你自己修改。

创建一个更好用的WWW 搜索页向导

在 "Visual FoxPro 6 企业开发" (Prima Tech,ISBN 0-7615-1381-7)一书中,Rod Paddock 和 John Petersen 描述了如何修改WWW 搜索页向导来取消只能输出5个字段到一个网页的局限。胜于修改向导,你会希望派生它们。要这样做,用我派生生成器类的相似的方法。WWW 搜索页向导的代码在VFP 向导源目录下的WIZARDS\WZINTNET 目录中。
[dvnews_page=VFP 高级教程:VFP 开发技巧]

第九节 创建你自己的向导

Rod Paddock 和John Petersen 也在他们的书中也提供了一些使用VFP 向导类来建立你自己的向导的细节。这样做的优点是,有人已经建立了所有的"引擎"来管理向导处理,且你的向导将与其它的VFP向导具有相同的感观。

用BuilderD 创建生成器

在查看VFP6中的FoxPro基本类时(FFC),我注意到一件事是它们都具有叫做Builder和BuilderX的自定义属性,并且各个类的BuilderX 是设置为= HOME() + "Wizards\BuilderD,BuilderDForm"。我知道这些属性的作用(他们告诉VFP,这个类的生成器名),但为什么每一个类都要指定相同的生成器呢?更有趣的是,各个类以不同的选项调用类似的生成器表单(图1显示_HyperLinkLabel 类的生成器)。当使用相同的类时将会发生什么情况呢?


图 1. _HyperLinkLabel 类的生成器

首先介绍一点背境。可能正象你可能意识到的,VFP 生成器可能以多种方式调用,但最常见的是可能是在对象上右击鼠标并从出现的菜单上选择生成器。这会使BUILDER.APP 被执行。BUILDER.APP 检查是否选定的对象(我们称为"目标对象") 具有 BuilderX 属性,如果有,运行该属性指定的程序或实例化该该属性指定的类(如果生成器是一个类,将指定一个类库,逗号及类名)。如果它没有 BuilderX 属性但有一个 Builder 属性,生成器运行该属性指定的程序或实例化该该属性指定的类(我们将看到为什么会同时用两个属性指定生成器)。如果两个属性都不存在,将使用该对象基类的默认生成器。 你可以在你的类中建立自定义的 Builder 和 BuilderX 属性(甚至在你的基类中) 然后为每一个类填写适当的生成器名字。要使用两个属性的理由是 BuilderX 为该类指定一个自定义生成器 而Builder为一组公共的类(如comboboxe 或 grid)指定一个所需的生成器。正如我们稍后会看到的一样,我们可以在 BuilderX 属性中指定的生成器中,单击一个按钮来调出在 Builder 属性中指定的生成器。 因此,我们可以很容易地在 Builder 和 BuilderX 属性中指定生成器。而不是花很多时间来建立你自己的生成器,特别对于不常使用的类。

BuilderD

你可能意识到了 BuilderB 技术 用来建立生成器是容易的和快速的。BuilderB 是一组你可以派生来建立你自己的生成器的类。你可以为你想用生成器维护的目标对象的各属性添加一个控件到生成器子类。虽然BuilderB 使得建立生成器更容易,但你必须为每一个你想用生成器管理的类建立一个新的生成器子类。对于我们这样的懒人来说,幸运的是,Ken 以数据驱动的方式增强了BuilderB。这种新技术叫做BuilderD ,"D" 的意思是"动态" (Dynamic),可以在Ken 的网站(www.classx.com)找到,也包含在VFP 6 中(在VFP 主目录下的WIZARDS 目录中的BUILDERD.VCX)。 BuilderD 由一系列的类组成,但主要的一个是BuilderDForm; 这是一个数据驱动生成器表单 (注意这是VFP6.0的基本类中指定的BuilderX类)。正如你在图2中看到,该表单中的文本框用于输入目标类的名字和类名,按钮提供的功能可以调出类浏览器和显示帮助,一个页框、两个页面,但没有用于管理属性值的控件。


图 2. BuilderDForm

以下是该表单在实例化时,如何组合适当的控件:

  • Init 方法调用SetObject 方法,它调用AddObjects 方法(该代码事实上是在BuilderDForm 的父类BuilderBaseForm中)。

  • AddObjects 方法调用来自BuilderDB类的表单上的oBuilderDB 对象的AddObjects 方法。

  • BuilderDB.AddObjects 是一个复杂的方法,但其基本操作是打开生成器定义表(默认情况下是在VFP 主目录下的WIZARDS 目录中的BUILDERD.DBF,但可以修改cBuilderTable 属性来指定另一个表),查找目标对象类的记录,查找所有相似的记录,并使用该记录中的信息在页框中的一个或多个页上建立控件。这些控件是基于BUILDERD.VCX中的类的,诸如BuilderCheckBox 和 BuilderTextBox,它们知道如何绑定属性到目标对象。

这些步骤的结果是,一个生成器可以管理目标对象的一个或更多的属性。一个指定的生成器可以事实上做得比这些还要多,例如放置代码到目标对象的方法或对象的容器中,介是目前我们只使用最简单的方法。

BuilderD 表

让我们进一步了解生成器定义表BUILDERD.DBF,因为理解它的结构是建立你自己的生成器的关键。表2 显示了BUILDERD.DBF表的结构; 在该表中,"property control" 意思是生成器中的、维护一个目标对象的指定属性的控件。

 

字段 用途
TYPE 定义记录类型。它包含了两个内容:如果这是一个类记录它是CLASS,如果这是一个属性记录则它是PROPERTY
ID 记录识别符,通常是类的名字。
LINKS 连接到该记录的其它记录的ID 值列表(以回车符分隔)。该字段的更多细节在下面描述。
TEXT 如果这是一个CLASS记录,则为生成器表单的标题提示。

如果这是一个PROPERTY记录,则为属性控件的标题提示。

DESC 属性控件的状态条文本。
CLASSNAME 对于CLASS记录,是类的名字。BuilderDB 搜索该字段中指定的、一个包含目标对象类的记录。

对于PROPERTY记录,是要为属性控件实例的类的名字。若该字段为空,将使用BUILDERD.VCX 中的默认的类 (逻辑属性是BuilderCheckBox其它属性是 BuilderTextBox)。你指定的任何其它类都必须是BuilderD 类的子类,因为这些类具有被BuilderDForm使用的特殊的属性和方法。

CLASSLIB 包含有CLASSNAME 中指定的类的类库。该属性可以包含一个表达式 (例如HOME() + WIZARDS\BUILDERD.VCX)或一个常量; 在这种情况下,在表达式事放上方括号。对于PROPERTY记录,如果该字段为空且指定了CLASSNAME,则假定为BUILDERD.VCX。对于CLASS记录,BuilderDB 搜索一个包含有与该字段内容值相同的记录(如果必要的话,在求值后) 作为目标对象的ClassLibrary 属性,保留该值为空可建立一个类的生成器而不必担心它是在哪一类库中。
MEMBER 对于CLASS记录,其值为空。对于PROPERTY记录。如果为空,ID 必须包含属性名。
HELPFILE 包括有该类的帮助内容的CHM 文件名。如果为空,就使用当前帮助文件。
HELPID 帮助主题ID
TOP 属性控件的Top 设置。如果为0BuilderDForm 将该控件放在先前一个控件的下面(页面上的第一个控件放置在BuilderDB.nTop 属性中指定的位置)
LEFT 属性控件的Left 设置。如果为0BuilderDForm 将该控件放在先前一个控件的左边(BuilderDB.nLeft中指定)
HEIGHT 属性控件的Height 设置。如果为0,就使用该控件的默认Height值。
WIDTH 属性控件的Width 设置。如果为0,就使用该控件的默认Width 值。
ROWSRCTYPE 如果类使用的属性控件(CLASSNAME中指定) 是一个combobox,该combobox RowSourceType 设置。
ROWSOURCE 如果属性控件是一个combobox,该comboboxRowSource 设置。例如,如果 ROWSRCTYPE 1 ()ROWSOURCE 将包含一个用于combobox的、以逗号分隔的值的列表。
STYLE 如果属性控件是一个 combobox,该 combobox Style 设置。
VALIDEXPR 一个用于验证属性值的表达式。
READONLY 如果属性控件中只读的则为.T.
UPDONCHNG 如果属性控件的值写到目标对象的属性后被修改,则为.T. (就是说,交互式方式)
UPDATED 决定记录最后修改 (未被 BuilderD使用,仅是一个信息)
COMMENT 关于记录的注释(未被 BuilderD使用)
USER 用户信息记录(未被 BuilderD使用)

 

表 1. BUILDERD.DBF的结构

表2 和 3 显示了两个生成器的记录,VFP6.0的基本类_HyperLinkBase 和_HyperLinkLabel 类。我没有显示BUILDERD.DBF 表中的所有字段,出于空间的考虑; 仅列出与讨论有关的字段。

 

TYPE ID LINKS CLASSNAME CLASSLIB
CLASS _HyperLinkBase Ctarget
cFrame
lNewWindow
_HyperLinkBase (HOME()+"FFC\_Hyperlink.vcx")
CLASS _HyperLinkLabel Caption
_HyperLinkBase
_HyperLinkLabel (HOME()+"FFC\_Hyperlink.vcx")

 

表 2. _HyperLinkBase 和 _HyperLinkLabel 类的生成器记录

 

TYPE ID TEXT CLASSNAME ROWSRCTYPE ROWSOURCE
PROPERTY cTarget Target URL BuilderComboBox 1 www.microsoft.com/vfoxpro
PROPERTY cFrame Frame      
PROPERTY lNewWindow Open new browser window      
PROPERTY Caption Caption      

 

表 3. _HyperLinkBase 和 _HyperLinkLabel 生成器管理的属性定义记录

在表2 中的 _HyperLinkBase记录中,我们看见CLASSNAME 和 CLASSLIB 指定了该生成器使用的类(注意CLASSLIB 包含了一个在运行时求值的表达式而不是一个硬编码值),在LINKS 中列了出该生成器可管理的类的属性。显示在表3中的cTarget PROPERTY 记录指明该属性将被BuilderComboBox 控件管理,且该BuilderComboBox的RowSource 包含一个 Microsoft VFP 网站的URL (目前是msdn.microsoft.com/vfoxpro)。cFrame 将被 BuilderTextBox 对象管理(因为它是一个字符串属性且该类没有定义),lNewWindow 将有一个BuilderCheckBox 对象(因为它是一个逻辑属性)。

看起来是如此简单,对吧? 好了,LINKS 字段事实上可以更加复杂。首先,假如在LINKS字段中指定的类记录的ID 没有匹配记录,该ID 就被假设为属性名。

这样,你可以简单的在CLASS记录的LINKS字段中指定它管理的属性来实际建立一个生成器。当然,你必须保持属性的 captions 和属性的名字相同,没有状态条文本、默认的类和属性大小,但这些对于一个快速的和dirty 生成器来说都不算太坏。

第二个复杂之处是,CLASS记录的LINKS字段中指定的ID 可以指向另一个CLASS 记录而不是一个PROPERTY 记录。在这种情况下,该类 "继承"所有指定类的连接。你可以在表2中的_HyperLinkLabel 记录中看到这一点; 它的一个连接是_HyperLinkBase,因此它不仅用该类的生成器来管理Caption 属性(specifically 在它的 LINKS 字段中列出),同时也管理cTarget、cFrame和lNewWindow 属性,因为这些在_HyperLinkBase 的LINKS 字段中指定。

第三,PROPERTY 记录可以连接到另一个PROPERTY 记录。在这种情况下,记录"继承"连接记录的所有非空字段。最后,如果你用@<caption> 格式指定它,LINKS 可以包含生成器中的页框的标题 (例如,@Properties 使用"Properties" 作为页的标题)。

创建一个生成器

让我们在TEST.VCX类库中创建一个名为TestCheck的 VFP CheckBox 的子类作为开始。在该类中添加一个叫做BuilderX 的自定义属性并设置它的值为= HOME() + "Wizards\BuilderD,BuilderDForm"。然后在该类上右击鼠标并从快捷菜单中选择生成器。我们得到一条"没有注册该类型的生成器"的错误。这也说得通,因为我们还没有定义它 (尽管这令人不愉快,在稍后它将自动为我们建立一个)。按以下步骤做:

  • 在命令窗口中打入USE HOME() + "WIZARDS\BUILDERD",然后打入BROWSE。
  • 从表菜单中选择"添加新记录"。
  • 在TYPE字段中输入"CLASS",ID 字段中输入"TestCheck",LINKS 字段中输入"Enabled","AutoSize"和"Caption" (在输入各字段后按回车键),TEXT 字段中输入"My Test Builder",CLASSNAME 字段中输入"TestCheck",CLASSLIB 字段中输入 "TEST.VCX"。
  • 关闭浏览窗口并在命令窗口中打入USE 来关闭该表。
  • 在TestCheck 上右击鼠标并选择生成器。

酷不酷,嗯? 完全是你自己的生成器,仅在一分钟左右就建立了! 去掉Enabled 的选择并输入一个不同的Caption,并可看到这些属性已被修改。

注意不要被为属性建立记录所迷惑; Enabled 和 Caption 记录已存在于 BUILDERD.DBF表中,因此我们只需重用它们,而且由于不存在 AutoSize 记录,BuilderD 只假设我们想管理那个属性。

让我们再建立一个并看看以多小的输入可以得到一个可工作的生成器。在TEST.VCX类库中创建一个名为TestText的 VFP TextBox 的子类,向它添加一个属性 BuilderX 并设置它的值为 = HOME() + "Wizards\BuilderD,BuilderDForm"。在BUILDERD.DBF 中添加一条记录并只指定 TYPE ("CLASS"),ID ("TestText"),LINKS ("ReadOnly")和 CLASSNAME ("TestText";我们可以跳过 CLASSLIB 但 CLASSNAME 是必须的)。关闭该表,然后调出该类的生成器。

这也是一个可以工作的生成器。单击生成器中的生成器按钮; 它调出另一个生成器(如果Builder属性存在并非空,在Builder属性中指定的生成器,否则就是该类的基类的默认生成器,在此例中是 VFP TextBox 生成器)。这样,即使我们可以为一个类指定生成器,只要愿意,我们仍然可以访问更多的普通生成器。

预置-内建的生成器

我最近用BuilderD 建立了两个生成器,一个为我的SFGrid 类另一个为SFPageFrame。SFGrid 生成器维护DeleteMark 和RecordMark 属性(你可以很容易地添加其它你可能经常修改的属性) 但由于它们容易在属性窗口中修改,所以这不是我要建立该生成器的真正的理由。真正的理由是因为我喜欢使用grid 的columns 中的SFGridTextBox 对象(SFTextBox 的一个子类,具有一小部分不同的属性设置,以提供它们在 grid中出现的外观),并尽量用SFGridTextBox对象替换一般的TextBox 对象。

因此我建立了一个按钮(SFBUILDERS.VCX类库中的SFGridTextBoxButton类) 来自动进行该工作。以下是该按钮的 Click 方法代码:

 

local loColumn, ;
            loControl, ;
            lcName
            for each loColumn in Thisform.oObject.Columns
            for each loControl in loColumn.Controls
            if upper(loControl.Class) = 'TEXTBOX'
            lcName = loControl.Name
            loColumn.RemoveObject(lcName)
            loColumn.NewObject(lcName, 'SFGridTextBox', ;
            'SFCtrls.vcx')
            endif upper(loControl.Class) = 'TEXTBOX'
            next loControl
            next loColumn
            wait window 'SFGridTextBox added to each column' ;
            timeout 2

 

BuilderDForm 有一个引用到目标对象保存在它的 oObject 属性,因此生成器表单上的许多控件可以引用或修改目标对象的东西。在这些代码中,Thisform.oObject.Columns 引用grid 的Columns 集合被生成器影响。

这里有一个副作用:我怎样才能在我的生成器表单中得到该按钮? 我可以为我的生成器在BUILDERD表中建立一个记录,但那会添加按钮到页框中的一个页上,而我确希望该按钮象其它的生成器按钮一样出现。

因此我建立了一个 "button loader" 类 (SFBUILDERS.VCX类库中的SFBuilderButtonLoader类),该类添加一个按钮到生成器表单然后返回 .F. 这样,它实际上没有实例化。SFBuilderButtonLoader 在BUILDERD表的当前记录的备注字段 USER 中查找(使用类实例化的记录) 要添加到表单的按钮的类名和类库(注意下面代码中的 BUILDERD 是以 "BUILDER"别名打开的)。对于SFGridTextBoxButton,例如,我在BUILDERD表中建立一条记录,以 "SFGridTextBoxButton" 作为它的 ID 但 "SFBuilderButtonLoader" 是一个类,并在USER字段中输入 "SFBuilders, SFGridTextBoxButton"。这告诉 SFBuilderButtonLoader 添加一个 SFGridTextBoxButton 到表单中。以下是SFBuilderButtonLoader的 Init 方法代码:

 

local lcClass, ;
lnPos, ;
lcLibrary, ;
lnTop, ;
lnLeft, ;
loControl

* 如果 BUILDERD 表已经打开且定位在要载入的按钮记录上
* 我们将从USER字段中读取类和类库名并添加该按钮
* 到表单。

if used('BUILDER') and ;
            lower(BUILDER.CLASSNAME) = lower(This.Class)
            with Thisform
            lcClass = BUILDER.USER
            lnPos   = at(',', lcClass)
            if lnPos > 0
            lcLibrary = left(lcClass, lnPos - 1)
            lcClass   = substr(lcClass, lnPos + 1)
            else
            lcLibrary = ''
            endif
            * 添加按钮。如果我们成功了,在表单的按钮区找第一个打开"裂缝"
            .NewObject(lcClass, lcClass, lcLibrary)
            if type('.' + lcClass + '.Name') = 'C'
            lnTop  = .cmdClassBrowser.Top + ;
            .cmdClassBrowser.Height + 5
            lnLeft = .cmdClassBrowser.Left
            for each loControl in .Controls
            if loControl.Left = lnLeft and ;
            loControl.Top = lnTop
            lnLeft = lnLeft + ;
            .cmdClassBrowser.Width + 6
            if lnLeft + .cmdClassBrowser.Width > .Width
            lnLeft = .cmdClassBrowser.Left
            lnTop  = lnTop + .cmdClassBrowser.Height + 5
            endif lnLeft + .cmdClassBrowser.Width > .Width
            endif loControl.Left = lnLeft ...
            next loControl
            * 设置按钮位置到"裂缝"位置,并使其可访问。
            with .&lcClass
            .Top     = lnTop
            .Left    = lnLeft
            .Visible = .T.
            endwith
            endif type('.' + lcClass + '.Name') = 'C'
            endwith
            endif used('BUILDER') ...
            return .F.

 

在BUILDERD表中 SFGrid 记录的LINKS字段中有 DeleteMark、RecordMark 和 SFGridTextBox,因此该生成器获得这些控件。

现在我可以为我的SFGrid对象调出我的BuilderD 生成器,使用 VFP Grid 生成器(单击BuilderD表单上的生成器按钮) 来快速建立 grid中的列,然后单击我的添加SFGridTextBox按钮来让这些列使用 SFGridTextBox 对象。

对于 SFPageFrame,我也希望相似的功能:一个添加代码到页框中各页的RightClick方法的按钮; 这允许在页面上右击鼠标明时为页框或整个表单提供快捷菜单。象SFGrid 生成器一样,我在BuilderD表中建立了一个记录来实例化一个 SFBuilderButtonLoader 对象,然后添加一个 SFCodePageButton 对象到生成器表单。以下是添加代码到各页的SFCodePageButton的Click方法:

 

local lcCode, ;
            loPage, ;
            lcCurrentCode
            lcCode = 'This.Parent.ShowMenu()' + chr(13)
            for each loPage in Thisform.oObject.Pages
            lcCurrentCode = loPage.ReadMethod('RightClick')
            if not lcCode $ lcCurrentCode
            loPage.WriteMethod('RightClick', lcCurrentCode + ;
            iif(empty(lcCurrentCode), '', chr(13)) + lcCode)
            endif not lcCode $ lcCurrentCode
            next loPage
            wait window 'Code added to each page' timeout 2

 

要添加这些新的生成器到你的系统中,复制 SFBUILDERS.VCX 和 VCT (在本文档的源代码文件中可以找到) 到一个目录,然后打开示例文件提供的NEWBUILDERS 表,并修改 CLASSLIB 字段到包含路径的 SFBUILDERS.VCX文件名。打开 BUILDERD 表,然后 APPEND FROM NEWBUILDERS 表,添加Builder 和BuilderX 属性到你的类中,并在BuilderX中输入 = HOME() + "Wizards\BuilderD,BuilderDForm"。

其它生成器类

我早些时候注意到,SFBUILDERS.VCX 中的BuilderCheckBox 和 BuilderTextBox 类都是派生自同一个BuilderD 类。在附加的右击鼠标行为中,这两个类具有nTop 和 nLeft 属性,当这些属性改变时,用assign 方法设置它们的自定义的lMoved 属性为.T.。这允许我们查觉到什么时候一个属性控件被移动了(在属性控件生成器中的Left 和Top 是绑定至 nLeft 和 nTop 而不是直接绑定到 Left 和 Top)。只有当一个属性控件移动时,我们保存它的its Left 和 Top 值到 BUILDERD 表。 SFBUILDERS.VCX 中的加一个类是 SFPropertyCaption。该控件用于管理属性控件的 caption。

为什么用一个特别的类来做这件事? 为什么不用一个普通的BuilderTextBox 对象?

理由是如果属性控件是一个BuilderCheckBox,它有一个 Caption 属性,因此控件管理该属性。但是,如果属性控件是一个 BuilderTextBox,它没有 Caption 属性但确有一个组合的 label 对象,因此控件必须管理对象的对象的 Caption 属性。由于 BuilderD 类只管理单个对象的属性,SFPropertyCaption 不得不超越(override)少量方法来允许它处理这种情况。

SFBuilderPropertyComboBox 类是BuilderComboBox的一个子类。它提供一个目标对象的所有可写属性的一个列表(用 AMEMBERS() 得到所有属性的列表然后检查各自的PEMSTATUS()来排除只读的)。虽然它的主要目的是修改属性控件的 cProperty 属性(用于检查要管理的属性),它有两个有趣的行为。

首先,如果属性控件是一个BuilderTextBox 但你只修改了它管理的逻辑属性(如 Enabled),它移去BuilderTextBox 及组合的label 对象,并放一个 BuilderCheckBox 在这个地方。如果你改变了一个逻辑属性为另一个类型它会做相反的事。

第二,如果你输入了一个不存在的属性名,你会被提示建立该属性。如果你同意,生成器使用AddProperty 来添加新属性到目标对象。我的确不推荐在一个拖放到表单中的对象上这样做,因为这等于实例化编程; 如果你真的需要一个新属性,你可以考虑用子类来代替。

总之,这是一个经一个步骤在类中建立新属性并用生成器管理它的快速方法。 SFBuilderAddButton 是一个为了属性控件使用 SFBuilderButtonLoader 类而添加到生成器表单的按钮类 (派生自BuilderCommandButton)。SFBuilderAddButton 的Click方简单地调用属性控件所在的生成器表单的 AddPropertyControl 方法来建立一个新的属性控件,然后转换当前生成器表单来管理新属性控件。

这意味着你可以单击添加属性按钮添加一个新属性到生成器,并在生成器中管理它。这是一种添加多个属性控件的快速方法。

试一试

让我们看一看SFBuilderBuilderForm; 它实际上比对它的描述更易于使用。在TEST.VCX中建立一个叫做 MyTestText 的VFP TextBox 类的子类。添加一个 BuilderX 属性并设置它的值为 "SFBuilders,SFBuilderBuilderForm",然后调出该类的生成器。

注意尽管我们没有在BUILDERD 表中建立任何记录,我们仍然得到了一个生成器表单(当然,表单上没有控件,但我们马上会改变这一切)。

这是因为 SFBuilderBuilderForm 在不能找到该类的记录时,自动地为该类在BUILDERD表中建立了一个 CLASS 记录。

单击添加属性控件按钮。你会注意到一个文本框和标签出现在生成器表单上,但随后另一个生成器表单出现在该生成器表单的面上。这个新的表单是我们刚添加的属性控件的生成器。在属性 combobox中,选择 "Tooltiptext" 并修改 Caption 为 "Tool Tip Text" 和 Width 到250。移动该生成器表单在一旁并注意原表单上的属性控件也同样修改了。

单击第二个生成器表单上的添加另一属性按钮并注意另一个属性控件已添加到原生成器表单中,并且该生成器表单现在可以管理它了。为属性选择"Statusbartext" 并修改Caption 为"Status Bar Text" 和Width 到250。添加另一个属性控件,并为该属性选择 "Readonly" 并修改Caption 到"Read-Only"; 这时,注意原生成器属性控制改变了checkbox。关闭新的生成器表单。图3 显示了我们建立的生成器,图4 显示了属性控件生成器。


图 3. 我们为MyTestText 对象建立的BuilderD 生成器


图 4. 属性控件生成器

要修改控件的属性,在控件上右击鼠标并从快捷菜单中选择修改属性修改控件; 你以前看到过的相同的属性控件生成器会出现。要移去属性控件,从菜单中选择移去属性控件。要重置目标对象的该属性的值为默认值,选择重置为默认值

让我们修改生成器表单的标题为更为合适的东西。单击修改生成器标题按钮并在随后出现的SFBuilderBuilder生成器表单中输入 "我的测试文本框类生成器" 。关闭第二个生成器。

如果你在关闭生成器时没有保存,下一次你再调用 MyTestText 对象的生成器时,你的设置不会起作用。若要保存生成器的定义到 BUILDERD 表中,单击保存生成器按钮。如果你想导出生成器定义到另一个表中,单击导出生成器按钮并在出现的对话框中输入文件名。然后你可以发送该表给一些人,他们可以将其导入他们的 BUILDERD 表并访问你建立的生成器。

说明

因为VFP的开放式IDE,任何人都可以很容易地定制它们的开发环境,因此他们和他们的开发组可以极大地提高编程效率。
[dvnews_page=VFP 高级教程:VFP 开发技巧]

第十节 示例

例1:在程序开始时设置系统环境

*-- 设置工作目录
cCurrentProcedure = SYS(16,1)
nPathStart = AT(":",cCurrentProcedure) - 1
nLenOfPath = RAT("\", cCurrentProcedure,2) - (nPathStart)
SET DEFAULT TO (SUBSTR(cCurrentProcedure, nPathStart, nLenOfPath))
SET PATH TO PROGS,LIBS,MENUS,HELP,INCLUDE,FORMS,BITMAPS
*-- 修改程序标题并将屏幕放到最大,在编译成.EXE的文件运行时,这是必须的
MODIFY WINDOW SCREEN TITLE "测试" NOCLOSE
ZOOM WINDOW SCREEN MAX
*-- 屏蔽系统菜单
SET SYSMENU OFF
*--定义用于保存系统设置的全局变量
PUBLIC ;
GcOldTalk,;
gcOldPath,;
gcOldDir,;
gcOldClassLib,;
gcOldEscape,;
gcOldSafety,;
gcOldProc,;
gcOldStatus,;
gnOldMemo,;
gcOldMultiLocks,;
gcOldHelp,;
gcOldDeleted,;
gcOldExclusive,;
gcOldNotify,;
gcOldBell,;
gcOldNear,;
gcOldExact,;
gcOldIntensity,;
gcOldConfirm,;
gcOldOnShutDown,;
gcOldCompatible
*--保存原始的系统状态,以便在退出时恢复
GcOldTalk		= SET("TALK")
gcOldPath		= SET("PATH")
gcOldDir		= FULLPATH(CURDIR())
gcOldClassLib		= SET("CLASSLIB")
gcOldEscape		= SET("ESCAPE")
gcOldSafety		= SET('SAFETY')
gcOldProc		= SET('PROCEDURE')
gcOldStatus		= SET('STATUS BAR')
gnOldMemo		= SET('MEMOWIDTH')
gcOldMultiLocks	= SET('MULTILOCKS')
gcOldHelp		= SET('HELP', 1)
gcOldDeleted		= SET('DELETED')
gcOldExclusive		= SET('EXCLUSIVE')
gcOldNotify		= SET('NOTIFY')
gcOldBell		= SET('BELL')
gcOldNear		= SET('NEAR')
gcOldExact		= SET('EXACT')
gcOldIntensity		= SET('INTENSITY')
gcOldConfirm		= SET('CONFIRM')
gcOldOnShutDown	= ON('SHUTDOWN')
gcOldCompatible	= SET("COMPATIBLE")
gcOldDate		= SET("DATE")
gcOldCentury		= SET("CENTURY")
*-- 设置SET 和ON 命令
SET SAFETY OFF
SET PROCEDURE TO UTILITY.PRG
SET CLASSLIB TO MAIN
SET MEMOWIDTH TO 120
SET MULTILOCKS ON
SET HELP TO HELP\MAIN.CHM
SET DELETED ON
SET EXCLUSIVE OFF
SET NOTIFY OFF
SET BELL OFF
SET NEAR OFF
SET EXACT OFF
SET INTENSITY OFF
SET CONFIRM ON
SET COMPATIBLE OFF
SET DATE ANSI
SET CENTURY ON
SET ESCAPE OFF
ON SHUTDOWN DO OnShutDown
注意:运行上述代码时程序文件UTILITY.PRG,OnShutDown,类库文件MAIN及帮助文件MAIN.CHM必须存在。

例2:在程序结束时恢复系统环境

LOCAL luTemp
SET PATH TO      (gcOldPath)
luTemp = gcOldClassLib
SET CLASSLIB TO  &luTemp
luTemp = gcOldProc
SET PROCEDURE TO &luTemp
SET MEMOWIDTH TO gnOldMemo
luTemp = gcOldMultiLocks
SET MULTILOCKS &luTemp
luTemp = gcOldSafety
SET SAFETY &luTemp
luTemp = gcOldStatus
SET STATUS BAR &luTemp
CD (gcOldDir)
luTemp = gcOldDeleted
SET DELETED &luTemp
luTemp = gcOldExclusive
SET EXCLUSIVE &luTemp
IF FILE(gcOldHelp)
SET HELP TO (gcOldHelp)
ENDIF
luTemp = gcOldNotify
SET NOTIFY &luTemp
luTemp = gcOldBell
SET BELL &luTemp
luTemp = gcOldNear
SET NEAR &luTemp
luTemp = gcOldExact
SET EXACT &luTemp
luTemp = gcOldIntensity
SET INTENSITY &luTemp
luTemp = gcOldConfirm
SET CONFIRM &luTemp
luTemp = gcOldOnShutdown
ON SHUTDOWN &luTemp
luTemp = gcOldEscape
SET ESCAPE &luTemp
luTemp = gcOldCompatible
SET COMPATIBLE &luTemp
luTemp = gcOldTalk
SET TALK &luTemp
luTemp = gcOldDate
SET DATE &luTemp
luTemp = gcOldCentury
SET CENTURY &luTemp
CLOSE ALL
CLEAR DLLS
RELEASE ALL EXTENDED
CLEAR ALL

例3:程序崩溃时恢复系统环境

在程序设计期间,有时会因程序错误而使系统崩溃。当系统崩溃时,可能会有打开的表没有关闭,数据工作期不能释放,表单在屏幕上不能清除,菜单没有释放等一系列令人心烦的事。当你要手工地恢复系统到初使状态真还要费不少事,但是你可以自己编写一个过程文件来自动完成这些工作。这样,当系统崩溃时,你只需在命令窗口打入 DO XXX 即可。

*:******************************************************************************
*:
*: 过程文件C:\HIGHMIS\HF.PRG
*:
*:******************************************************************************
ON ERROR
SET PROCEDURE TO
POP KEY ALL
SET COLOR TO
SET SYSMENU TO DEFA
CLOSE ALL
RELEAS ALL EXTE
CLEAR DLLS
CLEAR EVENTS
CLEAR FIELDS
CLEAR GETS
CLEAR MACROS
CLEAR MEMORY
CLEAR MENUS
CLEAR POPUPS
CLEAR PROGRAM
CLEAR PROMPT
CLEAR READ ALL
CLEAR TYPEAHEAD
CLEAR WINDOWS
SET DEVICE TO SCREEN
CLEAR
SET EXCL ON
SET TALK ON
SET MESSAGE ON
RELEASE WINDOW 常用
SET HELP TO
SET HELP ON
CANCEL
例4:查看系统设置
*:******************************************************************************
*:
*: 过程文件C:\HIGHMIS\PROGS\SYSTEST.PRG
*:
*       用途:查看当前系统信息
**************************************************************************
PROCEDURE SYSTEST
PARAMETERS T__Method, T__File
RELEASE ALL EXCEPT T__*
PRIVATE ALL LIKE T__*
CREATE VIEW it
SET TALK OFF
CLOSE ALL
SET SAFETY OFF
SET ALTERNATE TO (IIF(EMPTY(T__File), "SysTest.TXT", T__File))
SET ALTERNATE ON
SET SAFETY ON
SET EXACT OFF
T__IsVisual = .T.
T__OutputFile = SET("ALTERNATE", 1)
DEFINE WINDOW T__win FROM 0,0 TO SROWS(),SCOLS() TITLE T__OutputFile CLOSE SYSTEM ZOOM
ACTIVATE WINDOW T__win
??"*** SysTest Version 2.00","日期",DATE(),"时间",TIME(),"***"
T__IsError = .F.
IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="SET")
WAIT WINDOW NOWAIT "*** SET() ***"
?
? "*** SET()  ***"
?PADR("SET(ALTERNATE)",30) + " == ", SET("ALTERNATE")
?PADR("SET(ANSI)",30) + " == ", SET("ANSI")
?PADR("SET(AUTOSAVE)",30) + " == ", SET("AUTOSAVE")
?PADR("SET(BELL)",30) + " == ", SET("BELL")
?PADR("SET(BLINK)",30) + " == ", SET("BLINK")
?PADR("SET(BLOCKSIZE)",30) + " == ", SET("BLOCKSIZE")
?PADR("SET(BRSTATUS)",30) + " == ", SET("BRSTATUS")
?PADR("SET(CARRY)",30) + " == ", SET("CARRY")
?PADR("SET(CENTURY)",30) + " == ", SET("CENTURY")
?PADR("SET(CLASSLIB)",30) + " == ", SET("CLASSLIB")
?PADR("SET(CLEAR)",30) + " == ", SET("CLEAR")
?PADR("SET(CLOCK)",30) + " == ", SET("CLOCK")
?PADR("SET(COLOR)",30) + " == ", SET("COLOR")
?PADR("SET(COMPATIBLE)",30) + " == ", SET("COMPATIBLE")
?PADR("SET(CONFIRM)",30) + " == ", SET("CONFIRM")
?PADR("SET(CONSOLE)",30) + " == ", SET("CONSOLE")
?PADR("SET(CURRENCY)",30) + " == ", SET("CURRENCY")
?PADR("SET(CURSOR)",30) + " == ", SET("CURSOR")
?PADR("SET(DATE)",30) + " == ", SET("DATE")
?PADR("SET(DEBUG)",30) + " == ", SET("DEBUG")
?PADR("SET(DECIMALS)",30) + " == ", SET("DECIMALS")
?PADR("SET(DEFAULT)",30) + " == ", SET("DEFAULT")
?PADR("SET(DELETED)",30) + " == ", SET("DELETED")
?PADR("SET(DELIMITERS)",30) + " == ", SET("DELIMITERS")
?PADR("SET(DEVELOPMENT)",30) + " == ", SET("DEVELOPMENT")
?PADR("SET(DEVICE)",30) + " == ", SET("DEVICE")
?PADR("SET(DISPLAY)",30) + " == ", SET("DISPLAY")
?PADR("SET(DOHISTORY)",30) + " == ", SET("DOHISTORY")
?PADR("SET(ECHO)",30) + " == ", SET("ECHO")
?PADR("SET(ESCAPE)",30) + " == ", SET("ESCAPE")
?PADR("SET(EXACT)",30) + " == ", SET("EXACT")
?PADR("SET(EXCLUSIVE)",30) + " == ", SET("EXCLUSIVE")
?PADR("SET(FIELDS)",30) + " == ", SET("FIELDS")
?PADR("SET(FILTER)",30) + " == ", SET("FILTER")
?PADR("SET(FIXED)",30) + " == ", SET("FIXED")
?PADR("SET(FULLPATH)",30) + " == ", SET("FULLPATH")
?PADR("SET(HEADING)",30) + " == ", SET("HEADING")
?PADR("SET(HELP)",30) + " == ", SET("HELP")
?PADR("SET(HISTORY)",30) + " == ", SET("HISTORY")
?PADR("SET(HOURS)",30) + " == ", SET("HOURS")
?PADR("SET(INTENSITY)",30) + " == ", SET("INTENSITY")
?PADR("SET(KEYCOMP)",30) + " == ", SET("KEYCOMP")
?PADR("SET(LIBRARY)",30) + " == ", SET("LIBRARY")
?PADR("SET(LOCK)",30) + " == ", SET("LOCK")
?PADR("SET(LOGERRORS)",30) + " == ", SET("LOGERRORS")
?PADR("SET(MACKEY)",30) + " == ", SET("MACKEY")
?PADR("SET(MARGIN)",30) + " == ", SET("MARGIN")
?PADR("SET(MARK)",30) + " == ", SET("MARK")
?PADR("SET(MEMOWIDTH)",30) + " == ", SET("MEMOWIDTH")
?PADR("SET(MENU)",30) + " == ", SET("MENU")
?PADR("SET(MESSAGE)",30) + " == ", SET("MESSAGE")
?PADR("SET(MOUSE)",30) + " == ", SET("MOUSE")
?PADR("SET(MULTILOCKS)",30) + " == ", SET("MULTILOCKS")
?PADR("SET(NEAR)",30) + " == ", SET("NEAR")
?PADR("SET(NOTIFY)",30) + " == ", SET("NOTIFY")
?PADR("SET(ODOMETER)",30) + " == ", SET("ODOMETER")
?PADR("SET(OPTIMIZE)",30) + " == ", SET("OPTIMIZE")
?PADR("SET(ORDER)",30) + " == ", SET("ORDER")
?PADR("SET(PALETTE)",30) + " == ", SET("PALETTE")
?PADR("SET(PATH)",30) + " == ", SET("PATH")
?PADR("SET(PDSETUP)",30) + " == ", SET("PDSETUP")
?PADR("SET(POINT)",30) + " == ", SET("POINT")
?PADR("SET(PRINTER)",30) + " == ", SET("PRINTER")
?PADR("SET(PROCEDURE)",30) + " == ", SET("PROCEDURE")
?PADR("SET(REFRESH)",30) + " == ", SET("REFRESH")
?PADR("SET(REPROCESS)",30) + " == ", SET("REPROCESS")
?PADR("SET(RESOURCE)",30) + " == ", SET("RESOURCE")
?PADR("SET(SAFETY)",30) + " == ", SET("SAFETY")
?PADR("SET(SCOREBOARD)",30) + " == ", SET("SCOREBOARD")
?PADR("SET(SEPARATOR)",30) + " == ", SET("SEPARATOR")
?PADR("SET(SHADOWS)",30) + " == ", SET("SHADOWS")
?PADR("SET(SPACE)",30) + " == ", SET("SPACE")
?PADR("SET(STATUS)",30) + " == ", SET("STATUS")
?PADR("SET(STATUS BAR)",30) + " == ", SET("STATUS BAR")
?PADR("SET(STEP)",30) + " == ", SET("STEP")
?PADR("SET(STICKY)",30) + " == ", SET("STICKY")
?PADR("SET(SYSMENU)",30) + " == ", SET("SYSMENU")
?PADR("SET(TALK)",30) + " == ", SET("TALK")
?PADR("SET(TEXTMERGE)",30) + " == ", SET("TEXTMERGE")
?PADR("SET(TOPIC)",30) + " == ", SET("TOPIC")
?PADR("SET(TYPEAHEAD)",30) + " == ", SET("TYPEAHEAD")
?PADR("SET(UDFPARMS)",30) + " == ", SET("UDFPARMS")
?PADR("SET(UNIQUE)",30) + " == ", SET("UNIQUE")
?PADR("SET(ALTERNATE,1)",30) + " == ", SET("ALTERNATE",1)
?PADR("SET(CLOCK,1)",30) + " == ", SET("CLOCK",1)
?PADR("SET(CURRENCY,1)",30) + " == ", SET("CURRENCY",1)
?PADR("SET(DELIMITERS,1)",30) + " == ", SET("DELIMITERS",1)
?PADR("SET(FIELDS,1)",30) + " == ", SET("FIELDS",1)
?PADR("SET(HELP,1)",30) + " == ", SET("HELP",1)
?PADR("SET(MESSAGE,1)",30) + " == ", SET("MESSAGE",1)
?PADR("SET(PRINTER,1)",30) + " == ", SET("PRINTER",1)
?PADR("SET(RESOURCE,1)",30) + " == ", SET("RESOURCE",1)
?PADR("SET(TALK,1)",30) + " == ", SET("TALK",1)
?PADR("SET(TEXTMERGE,1)",30) + " == ", SET("TEXTMERGE",1)
ENDIF
T__IsError = .F.
IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="ON")
WAIT WINDOW NOWAIT "*** ON() ***"
?
? "*** ON() ***"
?PADR("ON(ERROR)",30) + " == ", ON("ERROR")
?PADR("ON(ESCAPE)",30) + " == ", ON("ESCAPE")
?PADR("ON(KEY)",30) + " == ", ON("KEY")
?PADR("ON(KEY LABEL)",30) + " == ", ON("KEY LABEL")
?PADR("ON(PAGE)",30) + " == ", ON("PAGE")
?PADR("ON(READERROR)",30) + " == ", ON("READERROR")
?PADR("ON(SHUTDOWN)",30) + " == ", ON("SHUTDOWN")
ENDIF
T__IsError = .F.
IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="MIS")
WAIT WINDOW NOWAIT "其他设置"
?
? "其他设置"
?PADR("CAPSLOCK()",30) + " == ", EVALUATE("CAPSLOCK()")
?PADR("CPCURRENT()",30) + " == ", EVALUATE("CPCURRENT()")
?PADR("CPCURRENT(1)",30) + " == ", EVALUATE("CPCURRENT(1)")
?PADR("CPCURRENT(2)",30) + " == ", EVALUATE("CPCURRENT(2)")
?PADR("DISKSPACE()",30) + " == ", EVALUATE("DISKSPACE()")
?PADR("FULLPATH('')",30) + " == ", EVALUATE("FULLPATH('')")
?PADR("GETENV('COMSPEC')",30) + " == ", EVALUATE("GETENV('COMSPEC')")
?PADR("GETENV('FOXPROCFG')",30) + " == ", EVALUATE("GETENV('FOXPROCFG')")
?PADR("GETENV('FOXPROSWX')",30) + " == ", EVALUATE("GETENV('FOXPROSWX')")
?PADR("GETENV('FOXPROX')",30) + " == ", EVALUATE("GETENV('FOXPROX')")
?PADR("GETENV('PATH')",30) + " == ", EVALUATE("GETENV('PATH')")
?PADR("GETENV('TEMP')",30) + " == ", EVALUATE("GETENV('TEMP')")
?PADR("INSMODE()",30) + " == ", EVALUATE("INSMODE()")
?PADR("ISCOLOR()",30) + " == ", EVALUATE("ISCOLOR()")
?PADR("MEMORY()",30) + " == ", EVALUATE("MEMORY()")
?PADR("NUMLOCK()",30) + " == ", EVALUATE("NUMLOCK()")
?PADR("OS()",30) + " == ", EVALUATE("OS()")
?PADR("OS(1)",30) + " == ", EVALUATE("OS(1)")
?PADR("PRINTSTATUS()",30) + " == ", EVALUATE("PRINTSTATUS()")
?PADR("VERSION(1)",30) + " == ", EVALUATE("VERSION(1)")
?PADR("VERSION(2)",30) + " == ", EVALUATE("VERSION(2)")
?PADR("VERSION(3)",30) + " == ", EVALUATE("VERSION(3)")
ENDIF
T__IsError = .F.
IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="VAR")
WAIT WINDOW NOWAIT "系统内存变量"
?
? "系统内存变量"
?PADR("_ASCIICOLS",30) + " == ", EVALUATE("_ASCIICOLS")
?PADR("_ASCIIROWS",30) + " == ", EVALUATE("_ASCIIROWS")
?PADR("_BROWSER",30) + " == ", EVALUATE("_BROWSER")
?PADR("_BUILDER",30) + " == ", EVALUATE("_BUILDER")
?PADR("_CONVERTER",30) + " == ", EVALUATE("_CONVERTER")
?PADR("_DBLCLICK",30) + " == ", EVALUATE("_DBLCLICK")
?PADR("_GENGRAPH",30) + " == ", EVALUATE("_GENGRAPH")
?PADR("_GENMENU",30) + " == ", EVALUATE("_GENMENU")
?PADR("_GENPD",30) + " == ", EVALUATE("_GENPD")
?PADR("_GENSCRN",30) + " == ", EVALUATE("_GENSCRN")
?PADR("_GENXTAB",30) + " == ", EVALUATE("_GENXTAB")
?PADR("_PDRIVER",30) + " == ", EVALUATE("_PDRIVER")
?PADR("_PDSETUP",30) + " == ", EVALUATE("_PDSETUP")
?PADR("_SHELL",30) + " == ", EVALUATE("_SHELL")
?PADR("_SPELLCHK",30) + " == ", EVALUATE("_SPELLCHK")
?PADR("_STARTUP",30) + " == ", EVALUATE("_STARTUP")
?PADR("_TRANSPORT",30) + " == ", EVALUATE("_TRANSPORT")
?PADR("_WIZARD",30) + " == ", EVALUATE("_WIZARD")
ENDIF
T__IsError = .F.
IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="FONT")
WAIT WINDOW NOWAIT "可用字体"
?
? "可用字体"
=AFONT(T__fonts)
FOR T__i = 1 TO ALEN(T__fonts)
T__string = T__fonts[m.T__i] + ": "
IF AFONT(T__sizes, T__fonts[m.T__i])
FOR T__j = 1 TO ALEN(T__sizes)
T__string = m.T__string+IIF(m.T__j==1, "", ", ")+;
IIF(T__sizes[m.T__j]==-1,"scalable", LTRIM(STR(T__sizes[m.T__j])))
ENDFOR
ENDIF
? m.T__string
ENDFOR
RELEASE T__i, T__j, T__fonts, T__sizes, T__string
ENDIF
T__IsError = .F.
IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="CONFIG")
FOR T__i = 1 TO 3
DO CASE
CASE m.T__i==1
T__File = SYS(2019)
IF EMPTY(m.T__File)
T__File = SYS(2004)+"CONFIG.FPW"
ENDIF
CASE m.T__i==2
T__File = "C:\CONFIG.SYS"
CASE m.T__i==3
T__File = "C:\AUTOEXEC.BAT"
ENDCASE
WAIT WINDOW NOWAIT "配置文件"
?
DO CASE
CASE m.T__i==1
T__File = SYS(2019)
IF EMPTY(m.T__File)
T__File = SYS(2004)+"CONFIG.FPW"
? "*** " + "配置文件" + SYS(2004) + " CONFIG.FPW ***"
ELSE
? "*** " + "配置文件" + SYS(2019) + " CONFIG.FPW ***"
ENDIF
CASE m.T__i==2
T__File = "C:\CONFIG.SYS"
? "*** " + "配置文件" + "C:\CONFIG.SYS ***"
CASE m.T__i==3
T__File = "C:\AUTOEXEC.BAT"
? "*** " + "配置文件" + "C:\AUTOEXEC.BAT ***"
ENDCASE
IF FILE(m.T__File)
T__handle = FOPEN(m.T__File)
IF m.T__handle>-1
DO WHILE NOT FEOF(m.T__handle)
? FGETS(m.T__handle)
ENDDO
=FCLOSE(m.T__handle)
ELSE
? "不能打开文件."
ENDIF
ELSE
? "不能找到文件."
ENDIF
ENDFOR
RELEASE T__File, T__handle, T__i
ENDIF
SET CONSOLE OFF
? "完成"
SET CONSOLE ON
CLOSE ALL
T__handle = FOPEN(T__OutputFile, 2)
IF NOT m.T__handle==-1
=FSEEK(m.T__handle, -1, 2)
IF FREAD(m.T__handle,1)==CHR(26)
=FCHSIZE(m.T__handle, FSEEK(m.T__handle, -1, 2))
ENDIF
=FCLOSE(m.T__handle)
ENDIF
ACTIVATE SCREEN
SET TALK OFF
SET MESSAGE TO "检查完成,结果已写至" + T__OutputFile
WAIT CLEAR
ZOOM WINDOW T__win MAX
MODIFY COMMAND (T__OutputFile) NOEDIT WINDOW T__win NOMENU
RELEASE WINDOW T__win
SET VIEW TO it.vue
DELETE FILE it.vue
SET MESSAGE TO " "
RETURN
[dvnews_page=VFP 高级教程:VFP 开发技巧]

第十一节 附表:"选项"对话框的说明

显示:

包含控制 Visual FoxPro 显示界面的选项。

 

选项 说明 注册表主键名 命令、函数、系统变量
状态栏 指定 Visual FoxPro 是否在主窗口底部显示状态栏。 StatusBar SET STATUS BAR
时钟 指定 Visual FoxPro 是否在状态栏中显示系统时钟。必须选中状态栏选项,此选项有效。对应于 命令。 CLOCK SET CLOCK STATUS
命令结果 指定 Visual FoxPro 主窗口、系统信息窗口、图形状态栏或一个用户定义窗口中,显示命令(包括 APPEND FROMAVERAGECALCULATECOUNTINDEXSUM TOTAL)的结果。 TALK SET TALK
系统信息 指定在 Visual FoxPro 的状态栏显示系统信息。 NOTIFY SET NOTIFY
最近用过的项目列表 指定 1234 命令出现在文件菜单中。允许直接打开最近使用过的四个项目。如果未选定文件位置选项卡中的资源文件,或者 SET RESOURCE 被设置为 OFF,该选项不可用。 RecentlyUsedFiles  
在启动时打开上一个项目 指定启动时 Visual FoxPro 打开最近一次使用的项目。如果未选定文件位置选项卡中的资源文件,或者 SET RESOURCE 被设置为 OFF,该选项不可用。 LastProject  

 

返回顶部

常规

包含了有关 Visual FoxPro 中声音、程序设计、数据输入的选项以及其它选项。

 

选项 说明 注册表主键名 命令、函数、系统变量
警告声音 关闭:关闭报告错误的声音;默认:把报告错误的声音设置为系统的默认值。播放:把报告错误的声音设置为一个 .wav 文件。可以在框中键入文件名,也可以单击三点按钮选择一个已存在的 .wav 文件。 BELL SET BELL
ESC 键取消程序运行 通过按 ESC 键取消一个正在运行的程序 ESCAPE SET ESCAPE
记录编辑错误 在一个与项目文件同名的 .err 文件中记录 Visual FoxPro 的编译错误。 LOGERRORS SET LOGERRORS
SET DEVELOPMENT 如果对象的代码比源代码旧,Visual FoxPro 将在运行前重新进行编译。 DEVELOPMENT SET DEVELOPMENT
严格的日期级别 指定是否不明确的日期和日期时间常量会产生错误。 STRICTDATE SET STRICTDATE
dBASE 兼容 指定与 FoxBASE+dBASE 以及其它 Xbase 语言的兼容性。 COMPATIBLE SET COMPATIBLE
使用 VFP 调色板 对所有位图或 OLE 对象指定使用默认的 Visual FoxPro 调色板。在同时显示几个图片时可以防止切换调色板。 PALETTE SET PALETTE
文件替换时加以确认 指定用新文件改写已存在文件时,Visual FoxPro 要求确认。 SAFETY SET SAFETY
浏览表时启动 IME 控件 当您在浏览窗口中定位一个文本框时,Visual FoxPro 将显示一个输入法编辑器。如果不是在 DBCS 环境中工作,该设置无效。对应于函数。 BROWSEIMECONTROL SET BROWSEIME
定位键 指定是否为任务(例如,在表单中的控件之间移动)使用与 Windows MS_DOS 兼容的定位键。对应于 命令。 KEYCOMP SET KEYCOMP
用当前值填充新记录 指定 Visual FoxPro 自动将当前记录的值复制到插入或添加的新记录中。 CARRY SET CARRY
使用 TAB Enter 键退出字段 指定只有按 ENTER TAB 键来退出编辑文本框。否则,键入的字符超过文本框最后一个字符时也可退出该文本框。对应于命令。 CONFIRM SET CONFIRM

 

返回顶部

数据

包含控制表中数据的选项。

 

选项 说明 注册表主键名 命令、函数、系统变量
以独占方式打开 指定 Visual FoxPro 是否以独占方式打开表及数据库,这样当您使用它们工作时,其他人不能够查看或修改它们。以独占方式打开文件可以带来更好的性能。在其他用户不需要访问数据(比如在晚上)的环境下,当处理大量记录时,可以使用该选项。 EXCLUSIVE SET EXCLUSIVE
显示字段名 指定在 AVERAGECALCULATEDISPLAYLIST SUM 命令的输出中,是否在每个字段的开始位置放一个字段名作为列标头。 HEADINGS SET HEADINGS
提示代码页 在打开没有指定代码页的表时,Visual FoxPro 提示是否指定一个代码页。 CPDIALOG SET CPDIALOG
忽略已删除记录 当执行带有作用域子句的命令时,指定 Visual FoxPro 是否忽略带有删除标记的记录;如果清除了这个选项,Visual FoxPro 命令将使用这些带有删除标记的记录。 DELETED SET DELETED
Rashmore 优化 当执行带有 FOR 子句的命令时,指定 Visual FoxPro 是否使用 Rushmore 优化。该选项对应于 命令。 OPTIMIZE SET OPTIMIZE
在索引中不出现重复记录 指定 Visual FoxPro 是否允许在索引文件中包含具有相同索引关键字值的记录。如果选定了该选项,只有第一个包含原始索引关键字的记录被索引。 UNIQUE SET UNIQUE
排序系列 指定字符字段在索引和排序操作中的排序顺序。 COLLATE SET COLLATE
记录计数器间隔 在诸如 COPY TO 等命令的执行过程中,指定 Visual FoxPro 更新状态栏中显示的记录计数器之前,应该处理多少条记录(范围从 1 32,767 条记录)。指定的数目越高,更新之间的延迟就越长,但命令可以执行的更快。必须选定视图选项卡中的状态栏选项,该选项才有效。 ODOMETER SET ODOMETER
备注块大小 指定给备注字段分配的磁盘空间大小。您输入的值指定了一个备注字段所需的最小磁盘空间,以及当数据添加到备注字段中时备注字段增加的大小。如果您指定了一个介于 1 32 之间的值,Visual FoxPro 512 乘以您的值,然后按那个大小的块分配磁盘空间。如果您指定了一个大于 32 的值,Visual FoxPro 只分配该大小的块,因此指定大于 32 的数目可以节省磁盘空间。 BLOCKSIZE SET BLOCKSIZE
浏览窗口刷新时间间隔 指定 Visual FoxPro 更新一个活动浏览窗口中记录的显示的频率,在多用户环境中它十分有用(可能的值从 0 3600)。把该值设置为 0 可以防止更新。设置该值为一个大的数目,可以不太频繁的更新浏览窗口,从而可以提高性能。 BrowseRefresh SET REFRESH
表刷新时间间隔 指定 Visual FoxPro 更新一个活动表的显示的频率(可能的值从 0 3600)。把该值设置为 0 可以防止更新。设置该值为一个大的数目,可以不太频繁的更新浏览窗口,从而可以提供性能。在多用户环境中它十分有用。 TableRefresh SET REFRESH
SET NEAR on 指定如果 FIND SEEK 命令失败,则 Visual FoxPro 将记录指针定位在匹配程度最大的记录上。 NEAR SET NEAR
SET EXACT on 指定在使用等号 (=) 时,Visual FoxPro 使用两个字符串的全部长度(除了后缀的空格)。如果清除了该选项,当到达等号 (=) 右侧表达式的末尾时,Visual FoxPro 即停止比较两个字符串。注释 该设置对 = 操作符的结果不起作用。 EXACT SET EXACT
SET ANSI on SQL = 操作符比较字符串时,指定 Visual FoxPro 是否填充字符串。SQL = 操作符逐字符比较,直至短字符串结束为止。如果您选择了该选项,Visual FoxPro 用空格填充短的字符串,因此一个 SQL 比较可能失败(Tommy不等于Tom)。如果您清除了该选项,将不填充短字符串,因此不等长的字符串也可能相等(Tommy等于Tom)。 ANSI SET ANSI
文件自动锁定 指定 Visual FoxPro 对某些不更改数据的命令(包括 AVERAGECOPY TOINDEXREPORTSORT 以及 TOTAL)自动锁定文件。如果您清除了该选项,在这些命令执行期间文件不锁定,其他用户可以在您的命令执行期间更改记录。 LOCK SET LOCK
多个记录锁定 指定是否能够同时锁定多条记录。如果您清除了该选项,Visual FoxPro 清除当前所有的锁定,并且一次只允许您锁定一条记录。当您锁定下一条记录时,当前记录即解除锁定。 MULTILOCKS SET MULTILOCKS
缓冲 在多用户环境中,指定是否在本地进行缓冲更改记录。缓冲分开放式缓冲或保守式缓冲。缓冲可以提高性能并能提供更强的并行控制。要使该选项生效,您必须选定多个记录锁定选项。 CrsBuffering CURSORSETPROP( )
重新处理 对已被其他用户锁定的表或记录再进行多少次或多长时间锁定尝试。 REPROCESS SET REPROCESS

 

返回顶部

远程数据

包含了有关远程 (ODBC) 视图和连接默认值的选项。

 

选项 说明 注册表主键名 命令、函数、系统变量
远程视图默认值 远程视图默认值框中的设置代表了 Visual FoxPro 当前工作期中临时表的设置。    
共享连接 指定 Visual FoxPro 使用当前连接处理新的视图。在数据源一次只支持一个连接时,它很有用。 CRSShareConnection CURSORSETPROP( ) CURSORGETPROP( )
取备注字段 指定只有在视图输出中激活一个备注或通用字段后才从数据源取备注或通用字段。清除该选项可以减少初始从远程表中下载的数据量,这将提高性能。 CrsFetchMemo
SQL 更新条件 指定当您试图更新数据前,Visual FoxPro 检查远程服务器上的字段来决定是否改变数据。如果选择条件所指定远程字段中的数据已经更改,则更新失败。 CrsWhereClause
SQL 方法程序 指定 Visual FoxPro 是使用 SQL UPDATE 还是使用 SQL DELETE,然后用 INSERT 来更新远程服务器上的信息。 CrsMethodUsed
每次取的记录数 指定 Visual FoxPro 从远程数据源中一次返回多少条记录。选定全部可以指定在第一次取操作中即返回所有的记录。该设置受要取的最大记录数中指定值的限制。 CrsFetchSize
要取的最大记录数 指定一个视图返回的记录总数。如果您错误地建立了一个查询,它可以防止返回过多的数据。选择全部可以指定返回所有的记录。 CrsMaxRows
使用备注字段的长度 指定长字符型字段中数据的最大长度。指定在视图输出中,如果字符数据超出指定长度时,将长字符字段转换成备注字段。默认值是 255 ,等于 Visual FoxPro 中字符型字段的最大长度。 CrsUseMemoSize
成批更新的记录数 指定视图一次发送的更新语句数目。调整这个值可以明显地提高更新性能。默认值是 1 CrsNumBatch
连接默认值 连接默认值框中的设置代表 Visual FoxPro 连接的全局默认设置。    
异步执行 指定把控制权返回给您的应用程序之后,Visual FoxPro 在后台执行 SQL pass-through 命令(使用 SQLEXEC( )SQLMORERESULTS( )SQLTABLES( ) SQLCOLUMNS( ))。如果您选定了该选项,您的应用程序可以显示过程信息,并且允许用户使用 ESC 键中断一个命令(如果 SET ESCAPE 已经设置为)。您可以决定一个异步执行的 SQL 命令的状态,方法是重复地调用其中一个 SQL pass-through 函数,直至它报告命令已经完成为止。这个选项的默认值是废止(同步执行),它指定 Visual FoxPro 在把控制权返回您的应用程序之前一直等待,直至 pass-through SQL 命令完成为止。 SQLAsynchronous SQLSETPROP( ) SQLGETPROP( )
显示警告信息 允许显示警告信息。 SQLDispWarnings
批处理 在使用 SQLEXEC( ) 发送多个 SQL pass-through 语句时,指定 Visual FoxPro 并不返回任何结果,直到所有结果集合都检索到为止。对应于在 SQLSETPROP( ) 函数中设置 BatchMode。如果废止了该选项,您必须调用 SQLMORERESULTS( ) 来确定数据是否可用。 SQLBatchMode
自动事物处理 指定由远程表上的连接自动处理事务。如果清除了该选项,您必须使用 SQLCOMMIT( ) SQLROLLBACK( ) 人工处理事务过程。 SQLTransactions
显示登陆信息 当一个连接激活时,指定是否显示登录提示(如果该连接需要用户进行登录)。例如,只在必要时指出,只有在连接或视图定义中未指定登录信息的情况下,才出现登录提示。 SQLDispLogin
连接超时设定 指定与远程服务器建立一个连接所需等待的秒数(0 600 之间)。如果在指定时间内不能建立这个连接,则 Visual FoxPro 显示错误。指定 0 为无限制地等待一个连接。 SQLConnectTimeOut
空闲超时设定 指定连接不活动前允许空闲时间的分钟数。如果在指定时间内没有请求使用服务器,则 Visual FoxPro 终止该连接。但是,连接超时后如果对服务器又有请求,则 Visual FoxPro 将试图自动恢复这个连接。 SQLIdleTimeOut
查询超时设定 指定等待服务器响应一个请求的秒数(0 600 之间)。如果服务器在指定秒数的时间内还不处理查询,则 Visual FoxPro 显示错误。指定 0 可以无限制地等待查询结果。 SQLQueryTimeOut
等待时间 指定 Visual FoxPro 检查 SQL 语句是否执行结束之前经过的毫秒数。 SQLWaitTime

 

返回顶部

文件位置

包含了 Visual FoxPro 使用文件的目录位置和名字。可以直接在每个框中键入路径和文件名,也可以单击对话框按钮激活对话框设置相应的选项。

 

选项 说明 注册表主键名 命令、函数、系统变量
ActiveDoc 启动程序 当从工具菜单选择运行 Active Document时,指定所调用的应用程序的文件名称。默认值为 Runactd.prg _RUNACTIVEDOC _RUNACTIVEDOC
生成器 当在表单设计中的快捷菜单中选择生成器时,指定调用的应用程序名称。一个生成器包含一个或多个对话框,帮您设置特定控件的属性,或者组合一些子句来创建特定的表达式。如果您在表单选项卡中选定了生成器锁定选项,可以自动显示生成器。 _BUILDER _BUILDER
类浏览器 当从工具菜单选择类浏览器时,指定所调用的应用程序的文件名称。默认值为 Browser.app _BROWSER _BROWSER
组件管理库 当从工具菜单选择组件管理器时,指定所调用的应用程序的文件名称。默认值为 Gallery.app _GALLERY _GALLERY
转换器 指定转换器应用程序的文件名,当打开由较早版本的 FoxPro Visual FoxPro 创建的表单、报表、或其他应用程序时,调用转换程序。 _CONVERTER _CONVERTER
代码范围分析器 在创建调试代码范围和分析输出时,指定其应用程序的名称。默认值为 Coverage.app _COVERAGE _COVERAGE
默认目录 指定默认的 Visual FoxPro 目录。如果选定该框并且选择设置为默认值按钮,则显示的目录将注册为当前和所有将来工作期的默认目录;如果未选定该框并且选择设置为默认值,则将从注册中删除显示的目录;如果选定该框并且选择确定,则只更改本工作期的默认目录。最后,如果清除选定该框,则不能够更改当前工作期的默认目录。 SetDefault SET DEFAULT
默认包含文件 指定预定义编译时刻常量的默认头文件,该文件被自动包含在用户自定义类、表单或表单集中。该选项默认为空。 _INCLUDE _INCLUDE
文档向导 当从工具菜单选择修饰时,指定所调用的应用程序的文件名称。当在编辑窗口打开某个程序或文本文件时,在工具菜单中显示修饰命令。默认值 Beautify.app _BEAUTIFY _BEAUTIFY
表达式生成器 当发出 GETEXPR 命令或从 Visual FoxPro 内部调用表达式生成器时,指定所执行的应用程序名称。该选项默认值为空。 _GETEXPR _GETEXPR
HTML 生成器 当从文件菜单选择另存为 HTML命令时,指定所调用的应用程序名称。默认值为 Genhtml.prg _GENHTML _GENHTML
帮助文件 指定 Visual FoxPro 是否显示帮助,使用哪个文件作为帮助内容。复选框的设置对应帮助的打开和关闭。如果文件名的扩展名是 .hlp,使用图形帮助。如果文件名扩展名是 .dbf,那么将使用 .dbf 样式的帮助。如果未指定扩展名,则默认为图形帮助 HelpOn

HelpTo

SET HELP
菜单生成器 指定菜单生成程序的文件名。 _GENMENU _GENMENU
资源文件 指定 Visual FoxPro 是否把当前的状态(宏、窗口的大小及位置等等)存储在一个资源文件中。如果存储,指定使用哪一个文件。如果未选定该选项,每次启动时,Visual FoxPro 都把系统状态重置为默认值。并且选项对话框中的一些选项将被废止。 ResourceOn

ResourceTo

SET RESOURCE
示例目录 指定包含 Visual FoxPro 示例文件的目录。 _SAMPLES _SAMPLES
搜索路径 指定一些目录,当 Visual FoxPro 在默认目录中找不到文件时,便在这个框中指定的目录中继续搜索文件。框中的目录之间必须用逗号或分号隔开。如果使用对话按钮指定多个目录,则自动在目录之间插入分号。 PATH SET PATH
拼写检查器 指定拼写检查器应用程序的文件名。 _SPELLCHK _SPELLCHK
启动程序 指定启动 Visual FoxPro 时所调用的应用程序名称。默认值为 Vfp6strt.app _STARTUP _STARTUP
临时文件 指定 Visual FoxPro 保存临时文件的目录。例如,在排序或索引时。因为临时文件可能变得很大,所以要指定一个具有足够自由空间的目录。要获得最好的性能,还应该指定一个最快的驱动器;例如在多用户环境中,您可能需要指定一个本地驱动器。 TMPFILES  
向导 指定运行向导时调用的应用程序的文件名。 _WIZARD _WIZARD

 

返回顶部

表单

包含表单设计的选项。

 

选项 说明 注册表主键名 命令、函数、系统变量
网格线 指定在表单设计中显示网格线,以帮助调整控件。注释 此设置仅应用于新表单,对现有表单的设置将保存在表单的资源文件中。 GridShow  
对齐格式 在画新控件时,指定它们的边缘与最近的表格线对齐。注释 此设置仅应用于新表单,对现有表单的设置将保存在表单的资源文件中。 GridSnap  
水平间距 指定水平网格线之间的间隔宽度。该宽度基于选项卡上的度量单位选项。注释 此设置仅应用于新表单,对现有表单的设置将保存在表单的资源文件中。 GridHorz  
垂直间距 指定垂直网格线之间的间隔高度。该高度基于选项卡上的度量单位选项。注释 此设置仅应用于新表单,对现有表单的设置将保存在表单的资源文件中。 GridVert  
显示位置 指定是否在状态栏上显示对象的位置和尺寸。 GridShowPos  
TAB 键次序 指定如何设置表单中的 Tab 键次序。选择交互,可以单击控件确定它们的顺序。选择按列表,可以使用Tab 键次序对话框。 TabOrdering  
度量单位 表单设计器类设计器设置默认度量单位。可指定为像素或者Foxel ScaleUnits  
最大设计区 指定设计时表单的最大尺寸。Visual FoxPro 不允许把表单调整到大于指定的尺寸。指定用户可能希望的最小尺寸很有好处,可以让所有用户都能看到它。如果不选择任何东西,Visual FoxPro 将不实施任何尺寸限制。 ResWidth

ResHeight

 
表单集 显示表单集模板,从中可以选择一个表单集模板。 FormSetLib

FormSetClass

 
表单 显示表单模板对话框对话框,从中可以选择一个表单模板。 FormsLib

FormsClass

 
生成器锁定 当您创建的控件有一个注册的生成器时,指定在表单设计中自动显示生成器。 BuilderLock  
提示在运行表单之前前保存修改 指定当您从表单设计器中运行一个表单时,Visual FoxPro 将提示您保存您自上次保存以来所做的更改。如果清除了该选项,在运行表单之前,表单设计器自动保存更改。 PromptBeforeRun  

 

返回顶部

项目

包含了有关项目管理器的选项。

 

选项 说明 注册表主键名 命令、函数、系统变量
项目双击操作 指定在项目管理器中双击一个文件时,Visual FoxPro 是否运行或修改该文件。 ProjectClick  
向导提示 如果选中,指示 Visual FoxPro 提示您使用向导。当从项目菜单选择新建文件或在项目管理器中选择新建按钮时,出现这些提示。 WizardPrompt  
显示用户自定义的图标 指定 Visual FoxPro 项目管理器中显示用户自定义的容器图标。 UseContainerIcons  
激活源代码管理器 指定要使用的源代码管理应用程序名称。您在这里指定的名称将应用到新项目中。当您创建一个新项目时,这里起作用的源代码管理程序名称将与项目存储在一起,这样,每次打开该项目,Visual FoxPro 都可以知道要使用的源代码管理程序。若要废止源代码管理,请选择 SCCProvider  
自动加入新的项目到源代码管理器 指定当创建一个项目时,Visual FoxPro 将提示您把该项目置于源代码管理器之中。如果清除了该选项,新项目不会自动置于源代码管理器之中,您必须人工地添加它们。注释 如果用户在命令窗口中使用命令(比如 MODIFY)修改项目文件,他们必须首先签出文件。 SCCUseSCCOnPjxCreate  
通过修改签出文件 指定当用户从项目管理器中修改文件时,自动把它们签出给用户。如果文件已经签出,Visual FoxPro 显示错误信息。如果清除了该选项,试图修改文件(没有从项目管理器签出的文件)的用户可以查看文件,但不能修改它们。 SCCCheckOutOnModify  
通过添加往源代码管理器上加入文件 指定添加进项目的文件自动置于该项目的源代码管理器之中。如果清除了该选项,您添加的文件变成项目的一部分(.pjx 文件),但没有置于源代码管理器之中。

注释 在添入项目时,数据库 (.dbc)、表 (.dbf)API 库以及应用程序 (.app) 文件不能自动添到源代码管理器。但您可以人工地把这些文件添加进源代码管理器。

SCCAddFileOnAdd  
通过移去从源代码管理器中删除文件 当您从项目中移出一个文件时,指定文件也从源代码管理器中移出。如果清除了该选项,当您从项目中移出一个文件时,该文件的源代码管理信息仍保留在源代码管理数据库中。这样做可以维持这个文件的归档信息,并且如果该文件未从磁盘上删除,您可以通过源代码管理器在 Visual FoxPro 之外访问它。 SCCRemoveFileOnRemove  
显示快捷菜单命令的对话框 当您从项目快捷菜单中选择一个源代码管理命令时,指定 Visual FoxPro 允许您选择多个文件来执行选定的命令。如果清除了该选项,所选命令只能用于项目中的选定文件,但是,按 SHIFT+单击鼠标右键然后选择命令可以忽略这个设置。 SCCContextDialogsOn  
文本生成 在每次签入文件时,指定用来创建二进制文件(表单、标签、菜单、报表或类库)的文本表示的应用程序名称。结果文本文件与表的源文件一起签入,可以用来创建报表以记录同一文件的不同版本之间的区别。 _SCCTEXT  
项目类 显示项目参考对话框,可以从中指定一个默认的 ProjectHook 类作为新项目的模板。 ProjectHookLib

ProjectHookClass

 

 

返回顶部

控件

包含了为指定选项对话框中表单选项卡上的模板类而登记可视类库的选项。这些选项也指定表单控件工具栏上查看类按钮中可以选择的内容,这可以简化向表单中添加用户自定义控件的工作。

 

选项 说明 注册表主键名 命令、函数、系统变量
可视类库\ActiveX 控件 指定类库(.vcx 文件)在选定列表框中显示。 ShowVCXs  
  指定显示在选定列表中的 ActiveX 控件。    
选定 列出可以添加或移出您的 Visual FoxPro 环境的文件。如果您选择了可视类库,该列表显示您已经添加的 .vcx 文件,同时指定当您单击表单控件工具栏上的查看类按钮时,哪些库出现在快捷菜单上。如果您选择了ActiveX 控件,该列表显示系统中可用的对象及控件类。您添加的 ActiveX 对象和控件已经选定,当您单击表单控件工具栏上的查看类按钮时,它们将出现在快捷菜单上。    
标签 当选定可视类库选项时显示标签。指定类库的名称。默认情况下,Visual FoxPro 使用不带 .vcx 扩展名的文件名。    
当选定可视类库选项时显示。对当前选定类库的 .vcx 文件,显示它的路径及文件名。    
可插入对象 当选定ActiveX时出现。可以指定出现在选定列表中的 ActiveX 对象类型。指定选定列表显示对象的类,它们作为 ActiveX 对象插入到 Visual FoxPro 应用程序中。 ShowOLEInsertable  
控件 当选定ActiveX时出现。可以指定出现在选定列表中的 ActiveX 对象类型。

指定选定列表显示 ActiveX 控件。

ShowOLEControls  
添加 选择按钮显示打开对话框,从而可以向选定列表中添加库(.vcx文件)或者 ActiveX 控件。添加一个控件同时也注册它,从而使它在插入对象对话框以及其他应用程序中可用。    
移去 当选定可视类库选项时出现,选择此按钮,从选定框中移去选定的库。    

 

返回顶部

区域

 

选项 说明 注册表主键名 命令、函数、系统变量
使用系统设置 选定该选项时,本选项卡上全部选项均从系统读取(设置是控制面板中建立的设置)。在这种方式下,绝大部分选项是只读的。

如果清除该选项,则可以指定选项设置,Visual FoxPro 使用这些设置,而不使用系统设置。

SYSFORMATS SET SYSFORMATS
日期格式 指定一个日期格式(年、月、日的顺序)。选择可以移去日期中前面的零。选择可以完全地显示日期。 DATE SET DATE
日期分隔符 指定日期各部分之间的字符。清除该选项将使用默认的分隔符。 MARK SET MARK TO
年份 选定时,指定显示关于世纪的信息(例如,1998)。清除选项时,指定用 2 位显示年份(例如,98)。 CENTURY SET CENTURY
小时 把时间设置为显示AMPM 12 小时或24 小时格式。 HOURS SET HOURS
计秒 时间显示中包括秒。 SECONDS SET SECONDS
货币格式 指定货币符号的位置。 CurrLeft SET CURRENCY
符号格式 指定货币符号字符或字符串。 CurrSymbol SET CURRENCY
千位分隔符 指定小数点左方每三位插入的一个字符。 SEPARATOR SET SEPARATOR
小数分隔符 指定一个用以指示小数点位置的字符。 POINT SET POINT
小数位数 指定小数分隔符后的小数位数。 DECIMALS SET DECIMALS
星期开始于 指定哪一天是一个星期的开始。 FDOW SET FDOW
一年的第一周 指定哪一个星期是一个年日历的开始。 FWEEK SET FWEEK

 

返回顶部

调试

通过设置选项来定制 Visual FoxPro 调试器窗口。

 

选项 说明 注册表主键名 命令、函数、系统变量
环境 指定调试环境:

Debug Frame 所有调试器的窗口出现在一个大页框中。这个页框在 Visual FoxPro 主窗口之外,有自己的菜单和工具栏。这样,可以使调试器更少地介入应用程序的运行环境。如果选择了该选项,您可以通过选择"工具"菜单上的"调试器"来打开调试器。

FoxPro Frame 调试器窗口出现在 Visual FoxPro 主窗口中。如果您只需要单个的窗口打开(如"监视"窗口),FoxPro 环境最有用。如果选择了该选项,Visual FoxPro 用打开单个窗口的命令代替"工具"菜单上的"调试器"命令,同时单个调试窗口的工具栏也贴在 Visual FoxPro 主窗口中。

注释 调试器打开时您不能更改该选项。

DebugEnvironment  
显示计时器事件 在达到间隔值时,如果您希望 Timer 控件的 Timer 事件显示在跟踪窗口中,选定该选项。如果您清除了这个选项,Timer 事件仍然发生,但不显示;就好象您已经为那个事件指定了跳出一样对待。 DebugTimerEvents  
指定窗口 选定一个选项,指定为哪一个调试器窗口设置选项。    
调用堆栈 显示堆栈调用顺序:在"调用堆栈"窗口列出的每一个程序旁边显示一个编号,最大的编号指示当前执行的程序。 CallstackOrder  
显示当前行的指示器:指示当前行指示符→是否显示在调用堆栈窗口中 CallstackCurrentLine  
显示堆栈调用指示器:在"调用堆栈"窗口中,是否显示一个箭头→ 来指示在"跟踪"窗口中显示的过程。如果当前行与调用堆栈过程相同,Visual FoxPro 只显示当前行指示符。 CallstackStackPos  
输出:显示记录调试输出区域 记录调试输出 把写入"调试输出"窗口中的值复制到文本文件中。如果选择记录输出值,您需要指定一个日志文件,日志文件的默认扩展名是 .log。只有当"调试输出"窗口显示时,Visual FoxPro 才会把输出记录到一个文件中。您可以在程序中使用 DEBUGOUT SET PRINTER TO DEBUG 命令显示"调试输出"窗口中的信息(并把它发送到日志文件中)。

当退出 Visual FoxPro 时,该选项被清除。这样下次启动 Visual FoxPro 时,您就不会无意中改写日志文件。

DebugOutputFileName  
追加 指定在现有文件当前内容的后面写入调试输出,保留初始的内容。 DebugOutputAppend  
改写 指定调试输出改写指定文件的内容。 DebugOutputAppend  
监视 该窗口没有可用的附加选项。    
局部 该窗口没有可用的附加选项。    
跟踪 显示行号 "跟踪"窗口中的代码行左侧显示行号。 TraceLineNumbers  
跟踪断点之间的部分 以调节速度执行断点之间的代码。调节速度意味着在每行程序的执行之间有数秒的停顿。如果您清除了该选项,则以正常速度执行断点之间的代码。 TRBETWEEN SET TRBETWEEN
运行每行时暂停 指定执行每行代码之间停顿的秒数。该选项允许您减慢程序的执行,这样您可以看到每行代码,而不需要单独找每一行。 _THROTTLE  
所有窗口 字体:为指定的调试器窗口选择一个字体和样式。例如,若要设置调试器跟踪窗口的字体,在指定窗口下选择跟踪,然后选定字体来选择字体、大小及字体样式。 TraceFontName

WatchFontName

LocalsFontName

OutputFontName

CallstackFontName

TraceFontSize

WatchFontSize

LocalsFontSize

OutputFontSize

CallstackFontSize

TraceFontStyle

WatchFontStyle

LocalsFontStyle

OutputFontStyle

CallstackFontStyle

 
区域:选择您准备为其指定颜色的文本元素。例如,若要指定更改的值所用文本的颜色,选定已改变的值区域列表中的选择取决于指定窗口下指定的窗口。 TraceNormalColor

TraceExecutingColor

TraceCallstackColor

TraceBreakpointColor

TraceSelectedColor

WatchNormalColor

WatchSelectedColor

WatchChangedColor

LocalsNormalColor

LocalsSelectedColor

OutputNormalColor

OutputSelectedColor

CallstackNormalColor

CallstackSelectedColor

 
前景:为选定范围的文本选择颜色。要使用 Windows 控制面板中建立的默认颜色,选择自动  
背景:为选定范围选择一个背景颜色。例如,如果要用蓝底黄字显示注释,可以在前景框中选择黄色,然后在背景框中选择蓝色。要使用 Windows 控制面板中建立的默认颜色,选择自动  

 

返回顶部

语法着色

包含的选项可以指定颜色及字体,用来区分 Visual FoxPro 的程序元素,比如关键字和注释。这些程序元素在命令窗口或所有编辑窗口(除用 MODIFY FILE MODIFY MEMO 命令打开的编辑窗口之外)中使用。

 

选项 说明 注册表主键名 命令、函数、系统变量
区域 选择要设置字体及颜色的程序元素类型。当选择时,其他控件将被更新到选定范围值。    
字体 为指定的区域选择一个字体样式。例如,在您的程序中,要用斜体显示所有注释,在区域框中选择注释,然后在字体框中选择斜体 EditorCommentColor

EditorKeywordColor

EditorConstantColor

EditorNormalColor

EditorOperatorColor

EditorStringColor

EditorVariableColor

EditorCommentStyle

EditorKeywordStyle

EditorConstantStyle

EditorNormalStyle

EditorOperatorStyle

EditorStringStyle

EditorVariableStyle

 

 

 

 

 

 

 

 

 

 

 

 

 

前景 为选定范围的文本选择颜色。要使用 Windows 控制面板中建立的默认颜色,选择自动
背景 为选定区域选择一个背景颜色。例如,如果要用蓝底黄字显示注释,可以在区域框中选择注释,在前景框中选择黄色,然后在背景框中选择蓝色。要使用 Windows 控制面板中建立的默认颜色,选择自动
示例 该区域显示您的设置效果。    
全部重置 选定该选项可以把语法着色设置为 Visual FoxPro 默认值。    

 

返回顶部

字段映象

 

选项 说明 注册表主键名 命令、函数、系统变量
将字段类型映象到类中 显示字段类型与类(控件)之间当前的映象关系。列表包括:

类型 数据库支持的所有数据类型。当您一次把整个表或多个字段拖到表单上时,""字段类型用来指定将要创建的类。"Label"字段类型指定为字段标题创建的类。

类库 一个类库,该类库包含映象到一个字段类型的类定义。如果该列为空,该字段类型将映象到一个 Visual FoxPro 基类上。

类名 一个字段类型将要映象的类,它指定了将要创建的控件类型。

   
修改 选择该按钮可以显示字段类型映象对话框,从中可为选定的字段类型指定一个不同的映象。

若要修改字段映象

选项对话框的字段映象选项卡中,选择修改

字段类型映象对话框内,从字段类型列表中选择一个字段类型。

若要设置类(该类在拖动一个表或多个记录时即可创建),选择多用途型

要选择类库(.vcx 文件),该类库包含您希望与选定字段类型联系在一起的控件,选择浏览

文件名列表中选择一个类的名称。每当把选定类型的字段拖到表单上时,都会创建您在这里指定的类。

选择确定应用来接受映象。

   
拖放字段标题 如果希望 Visual FoxPro 使用字段的标题作为即将创建类的标题,选定该选项。如果您清除该选项,Visual FoxPro 将不会创建字段标题。    
复制字段备注 选定该选项可以使 Visual FoxPro 在创建类时,把字段的注释(如果有的话)复制到新类的 Comment 属性中。    
复制字段输入掩码 选定该选项可以使 Visual FoxPro 在创建类时,把字段的输入掩码(如果有的话)复制到新类的 InputMask 属性中。    
复制字段格式 选定该选项可以使 Visual FoxPro 在创建类时,把字段的格式设置(如果有的话)复制到新类的 Format 属性中。    

 


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多