PFC编程基础(学习实战)

PFC编程基础

 
  概要: 
  这一章阐述了 PFC 编程的基本技巧,同时也告诉了你如何开始运用 PFC 编写应用程序。 
  设置应用程序管理器 
  首先建立一个PFC应用程序的第一步就是配置应用程序以及建立应用程序管理器- -n_cst_appmanager。应用程序管理器将替代原来的应用程序对象。原来在应用程序对象中编写的脚本将全部改写在应用程序管理器中。应用程序管理器中同时还通过实例变量、函数来维护应用程序的属性。其中有框架窗口、应用程序与用户的INI文件或注册键以及帮助文件等。 
  注意: 
  使用分开的物理文件 
  每个独立的应用程序都必须拥有自己独立的一套文件。你不可以共享父类文件,也就是那些以PFC开头的文件。这是由PFC的内部继承关系而决定的。 
  例如,假设应用程序1与应用程序2都拥有它们自己的一套扩展的PFC库文件,但是它们共享父类文件(PFC库文件)。这时应用程序1在自己的PFE(PFC扩展库)的w_master中增加了一个函数名为of_SetData。这样这个函数将在w_master的所有子类中都有效,这些子类是pfc_w_main,pfc_w_frame,pfc_w_sheet 等。而这些对象恰恰在这两个应用程序共享的父类文件(PFC库文件)中。这样当应用程序2重新生成应用程序时(regenerate)由于应用程序2的PFE文件中没有of_SetData函数。这样w_master的所有子类中的关于of_SetData函数的指针都将被删除。这样当应用程序1运行时将会导致运行时错误与编译错误。 
  具体步骤 
  1. 打开应用程序画笔。 
  2. 定义库文件列表。 
PFCAPSRV.PBL 
PFCDWSRV.PBL 
PFCMAIN.PBL 
PFCUTIL.PBL 
PFCWNSRV.PBL 
PFEAPSRV.PBL 
PFEDWSRV.PBL 
PFEMAIN.PBL 
PFEUTIL.PBL 
PFEWNSRC.PBL 
PFCOLD.PBL(如果你的应用程序是使用老版本的PFC库那么请增加该文件到库列表 中)  
  3. 在应用程序画笔中打开脚本画笔,定义n_cst_appmanager类型的全局变量gnv _app。 
  n_cst_appmanger gnv_app 这个变量名必须是gnv_app,因为PFC的对象、函数、事件都需要这个n_cst_appm anager或它的子类的全局变量-gnv_app。 
  4. 增加如下代码到应用程序对象的OPEN事件中。它的用途是创建n_cst_appmanager、调用pfc_Open事件。 
gnv_app = Create n_cst_appmanager 
gnv_app.Event pfc_Open(commandline)  
  5. 增加如下代码到应用程序对象的CLOSE事件中。 
gnv_app.Event pfc_Close() 
Destroy gnv_app  
  6. 增加如下代码到应用程序对象的SystemError事件中。调用pfc_SystemError事 件。 
gnv_app.Event pfc_SystemError() 
  7. 关闭应用程序画笔,保存所作的修改。 
  8. 打开用户自定义对象画笔。在PFEAPSRV.PBL中找到n_cst_appmanager并打开,或者是它的子类。 
  9. 在n_cst_appmanager的构造事件(Constructor Event)中调用它的函数来初始化关于软件版本号、公司、和INI文件的实例变量。 
  10. 在 n_cst_appmanager的pfc_Open事件中打开你所想要的应用程序Service 。 
  你所想打开的Service 调用函数Application preference of_SetAppPreference DataWindow caching of_SetDWCache Error of_SetError Most recently used object of_SetMRU Transaction registration of_SetSecurity Debug of_SetDebug 
  11. 在pfc_Open事件中增加打开你的初始窗口的代码,例如框架窗口(Frame Window)或者调用显示快闪窗口的of_Splash()函数。 
  12. (可选)增加代码到pfc_PreAbout,pfc_PreLogonDlg,pfc_PreSplash事件中,用于定制关于对话框(About box)、登录对话框(Logon box)、快闪窗口(splash screen)。 
  13. (可选)增加代码到pfc_idle,pfc_ConnectionBegin,pfc_ConnectionEnd事件中。 
  l_ 在应用程序对象的idle事件中调用pfc_idle事件。 
  l_ 在应用程序对象的ConnectionBegin事件中调用pfc_ConnectionBegin事件。
  l_ 在应用程序对象的 ConnectionEnd事件中调用pfc_ConnectionEnd事件。 
  14. 保存n_cst_appmanager 
  如何显示快闪窗口 
  非常简单,只需在pfc_Open事件中,在打开第一个窗口的代码之前写上如下代码 : 
  this.of_Splash(1) 
  Open(w_tut_frame)(根据不同的应用程序有不同的变化!) 
  如何显示登录窗口 
  1. 在框架窗口的Open事件中调用of_LogonDlg函数: 
Integer li_return 
li_return = gnv_app.of_LogonDlg( ) 
IF li_return = 1 THEN 
this.SetMicroHelp("Logon successful") 
ELSE 
MessageBox("Logon", "Logon failed") 
Close(this) 
End If  
  Of_LogonDlg函数将显示w_logon对话框,同时还会提示输入用户名、密码,当用 户点击OK按钮时还会触发n_cst_appmanager的pfc_Logon事件。 
  同样,你也可以在n_cst_appmanager的pfc_Open事件中的打开框架窗口之后立即 调用Of_LogonDlg函数。但是绝对不要在Of_Splash之后立即调用Of_LogonDlg 。 
  2. 在n_cst_appmanager的pfc_logon事件中编写登录到数据库的代码。这个例子 假设有一个INI文件,它包含了所有的需要登录到数据库的信息,除了用户名、密码以外。同时还假设你已将SQLCA的默认类型改为n_tr(PFC制定的书屋对象类型 )。 
Integer li_returnString ls_inifile, ls_userid, ls_password 
ls_inifile = gnv_app.of_GetAppIniFile() 
IF SQLCA.of_Init(ls_inifile,"Database") = -1 THEN 
Return -1 
END IF 
// as_userid and as_password are arguments 
// to the pfc_Logon event 
SQLCA.of_SetUser(as_userid, as_password) 
IF SQLCA.of_Connect() = -1 THEN 
Return -1 
ELSE 
gnv_app.of_SetUserID(as_userid) 
Return 1 
End If 
建立应用程序 
  建立一个MDI应用程序 
  使用w_frame,w_sheet窗口作为你的框架窗口与表单窗口的父类。在w_sheet窗口 中增加你的应用程序中所有表单窗口需要的事件、实例变量、函数。 
  你必须为每一个表单窗口定义菜单。 
  具体步骤: 
  1. 为应用程序在w_frame窗口中作特定的修改。最好是建立一个w_frame窗口的子类,然后再修改这子类。 
  2. (可选)在w_sheet中增加实例变量、函数、用户自定义事件。 
  3. 建立继承w_sheet的表单窗口。 
  4. 建立一个框架窗口(frame window)用的菜单,通常是选用w_frame 。 
  5. 为框架窗口指定相应的框架窗口菜单。 
  6. 建立表单窗口的菜单 
  7. 为表单窗口(sheet window)指定相应的表单菜单。 
  8. 在n_cst_appmanager的pfc_Open事件中加入打开框架窗口的代码。 
  9. (可选)在必要时候,开启框架窗口Service 。 
  l_ 调用w_frame的of_SetStatusBar函数开启状态条Service 。 
  l_ 调用w_frame的of_SetSheetManager函数开启表单管理Service 。 
  在MDI应用程序中打开表单窗口: 
  1. 在菜单项的Clicked事件中编写有关打开表单窗口的脚本。你需要将表单窗口的名称以字符串的形式传递给Message.StringParm,然后以pfc_Open为参数调用of_SendMessage函数: 
n_cst_menu lnv_menu 
Message.StringParm = "w_products" 
lnv_menu.of_SendMessage(this,”pfc_Open”)  
  2. 在w_frame的pfc_Open事件中访问Message.StringParm,打开指定的表单窗口。 
String ls_sheet 
w_sheet lw_sheet 
ls_sheet = Message.StringParm 
OpenSheet(lw_sheet, ls_sheet, this, 0, Layered!)  
  建立一个SDI应用程序 
  在使用PFC建立SDI应用程序中,你将使用w_main窗口作为你的所有main类型窗口的父类。为了使得你的事件、函数、实例变量能够在所有的窗口中都有效,只需将它们加到w_main中。 
  如果你的窗口需要菜单,那么你必须为每一个窗口定义菜单。 
  具体步骤 
  1. 继承w_main窗口,建立一个main类型窗口,最为主窗口。最好是直接修改w_main窗口。 
  2. 建立一个主菜单。 
  3. 根据需要建立其他的菜单与窗口。 
  4. 在n_cst_appmanager的pfc_Open事件中编写打开主窗口的脚本。 
  PFC编程过程中的函数使用方法 
  几乎所有的PFC函数都是对象级函数。这就意味着你必须定义POWERBUILDER对象后才可以使用函数。经过PB封装后的函数使你很轻易的看到哪个函数属于哪个对象。 
  PFC使用Set/Get/Is 命名规则来控制实例变量。 
  l_ of_Set函数允许你为实例变量赋值 
  l_ of_Get函数允许你获得一个非布尔类型的变量的值 
  l_ of_Is函数允许你确定一个布尔类型变量的真与假 
  其他类型实例变量的访问规则 
  PFC定义变量时同时指定为公共类型(public),那么你将可以随意直接访问。 
  另外,有些变量由于只是在内部使用,因此不能通过函数进行访问。 
  除了Set/Get/Is命名规则以外,PFC在为某一Service定义入口参数时使用Regist er/UnRegister规则。例如,你可以调用u_calculator对象的of_Register函数来定义Datawindow的那个列使用下拉日历。 
Object qualificationPFC uses access levels (public, private, protected 
) to control your access to functions designed for 内部自动调用 use. 
When you call these functions from outside the object, use dot notatio 
n to qualify the function name. Qualify the function name with the ref 
erence variable used to create the object (in some cases you qualify t 
he function name with the actual object name).  
调用PFC对象函数 
  1. 确认对象是已否被创建 
  PowerBuilder在当窗口打开的时候会建立窗口、菜单和可视的用户对象。你要使用函数of_Setservicename来建立大部分的不可视的用户对象。例如,下面u _dw的对象函数创建了排序Service(n_cst_dwsrv_sort user object),并且在u_dw’s中的实例变量inv_sort中保留它的引用。通常这些代码都在Datawindow的 构造事件中: 
  this.of_SetSort(True) 
  自动实例化对象 
  某些PFC对象利用了Powerbuilder提供的自动实例化功能。这些对象没有Set函数 。PowerBuilder会在它们声明的时候自动实例化它们。 
  2. 在应用程序中调用适当的对象函数 
  这个例子展示了排序Service将利用DataWindow的列名、排序已显示值、 实现当用户点击后排序。同时可以在菜单栏上显示下拉对话框。 
this.inv_sort.of_SetColumnNameSource(this.inv_sort.HEADER) this.inv_s 
ort.of_SetUseDisplay(TRUE) this.inv_sort.of_SetColumnHeader(TRUE) 
this.inv_sort.of_SetStyle(this.inv_sort.DRAGDROP)  
  函数重载PFC使用函数重载提供了一个丰富的、富有弹性的编程接口。它通过两种方法实现函数重载。 
  l_ 多种语法 多个函数具有不同的参数类型、不同的参数顺序。这使得PFC的函数可以处理多种数据类型的参数。 
  l_ 随意的参数数目 许多函数拥有一个具有相同数据类型、相同顺序、参数数目可以变化的参数。它同时还允许PFC为常用的参数提供默认值。 
  只用于内部处理所重载的函数 
  除了公有类型的重载函数以外,PFC通常还有一个保护类型的版本,一般都是用来进行内部调用的。例如,n_cst_dwsrv_report中的of_Addline函数有4个公有类型的版本、一个保护类型的版本。这个保护类型的版本是供其他4个调用的。虽然有些时候可以调用这些保护类型的版本,但是他们纯粹是为了内部调用而设计的 
。 
  关于PFC事件的编程 
  PFC包括了预代码的事件、用于实现PFC Service的用户自定义事件。还有一些空的事件,你可以在其中为你的应用程序加入特定的代码,或者执行一些特定的任务。所有的事件都是公有的,你可以直接访问它们。 
  “预代码事件”与其他的用户自定义事件 
  预代码事件指的是那些已经在PFC层对象中编号代码的事件。PFC拥有许多具有一定功能的“预代码事件”。这意味着如果你开启了一个Service ,PFC的对象发现该Service已开启了,那么这些“预代码事件”将会执行其中的代码。
  例如:u_dw的Clicked事件就是一个“预代码事件”,它会自动调用那些开启的Service函数。你可以扩展这些事件,但是不可以覆盖它们。 
  空的用户自定义事件 
  PFC定义了许多空的用户自定义事件。你可以在其中为你的应用程序写入特定的代码。许多这种事件都是通过菜单而触发的。另外一些则是应用程序代码触发的。 
  例如: 
  在u_dw中有一个用户自定义事件pfc_Retrieve ,你可以在其中加入检索数据的代码。 
  Return this.Retrieve() 
  有关更多的关于PFC事件的内容请参考PFC Object Reference 
  PFC中的事件是如何起作用的 
  PFC是采用如下的方式调用Services中的事件的 
  1. 当用户触发某个对象的某个事件时,PFC将会调用相应的Service 的自定义事件,同时传递相应的参数。例如:u_dw的clicked事件会调用n_cst_dwsrv_sort的pfc_Clicked事件,同时传递X坐标、Y坐标、DW对象(这些其实也是DW的Clicked 事件的参数)。 
  2. 这些Services的事件同时还有可能调用其他对象函数。例如,n_cst_dwsrv_sort的pfc_Clicked事件中还调用了n_cst_dwsrv_sort的函数。 
  尽管你可以直接调用PFC的对象函数,但是调用相应的事件显得更简单,因为这些事件中已经包括了错误检测代码。
  关于事件触发前的一些处理 
  PFC有一种自定义事件名是Prename 。这意味着这些事件是发生在事件name之前的事件。我们把它叫做pre_event 。你可以随意在pre_event中增加代码用于扩充相应的事件处理能力。这些pre_event有: 
pfc_PreAbout 
pfc_PreClose 
pfc_PreLogonDlg 
pfc_PreOpen 
pfc_PrePageSetupDlg 
pfc_PrePrintDlg 
pfc_PreRestoreRow 
pfc_PreSplash 
pfc_PreToolbar 
pfc_PreUpdate  
  通常,这些事件中都有一个已经自动实例化了的用户对象的引用变量。这个对象的属性可以影响这个事件的运行。你可以修改这个用户对象的属性,从而达到改变事件的运行或扩展事件的运行效果。有些时候你还需要修改一些其他的对象。 
  例如,当你需要控制About对话框中的一个附加控件的显示效果时,你需要:
  1. 扩展用户对象n_cst_aboutattrib ,在其中增加一个用于在w_about中代表显示效果的实例变量(一个 user ID)。 
  2. 在w_about中增加控件(sle_userid) 
  3. 在w_about的Open事件中编写代码,将user ID的值放入单行编辑框中(sle_userid) 
sle_userid.text = inv_aboutattrib.is_userid 
  4. 在n_cst_appmanager的pfc_PreAbout事件中编写初始化代码: 
  inv_aboutattrib.is_userid = this.of_GetUserID() 
  然后当你需要显示w_about时,调用应用程序管理器的of_About函数即可。 
  如何使用属性对象 
  PFC提供了许多专门的属性用户对象。这些用户对象有如下特征: 
  l_ 包含公有性质的实例变量 
  l_ 自动实例化 
  l_ 名称以attrib结尾 
  l_ 通常用于向PFC的pre_event传递信息,例如pfc_PreAbout 
  l_ 可扩展,你可以在其中自己定义其他的实例变量。 
  因为,你有可能会扩展这些对象。因此,PFC使用对象而不使用对象。 
  同样你还可以定义对象函数,做到更随意的控制这些对象。 
  这些属性对象有: 
  属性对象有关的用法 
n_cst_aboutattrib Pfc_Pre_About(n_cst_appmanager) 调用n_cst_appmanager的of_About函数打开about对话框 
n_cst_calculatorattrib Constructor(u_calculator) 内部自动调用n_cst_dirattrib File service object 内部自动调用 
N_cst_dwobjectattrib Of_Describe(n_cst_dssrv与n_cst_dwsrv) 函数Of_De scribe返回DataWindow中的对象属性。 
n_cst_dwproperyattrib DataWindow Properties objects 内部自动调用 n_cst_errorattrib Error message service 用于传递显示内容到w_message窗口 
n_cst_filterattrib DataWindow filter service 用于传递信息到filter对话框 
n_cst_findattrib DataWindow find service 传递信息到Find对话框
n_cst_itemattrib PFC ListBox, PictureListBox, and TreeView 内部自动调用 
n_cst_linkageattr b DataWindow linkage service 内部自动调用 
n_cst_logonattrib Pfc_PreLogonDlg (n_cst_appman ger) 调用n_cst_appmanager的of_LogonDlg函数打开w_logon窗口 
n_cst_mruattrib MRU service 用于窗体的pfc_MRUProcess和pfc_PreMRUSave事 件 
n_cst_restoreroattrib DataWindow row manager service 内部自动调用 
n_cst_returnattrib DataWindow filter and sort services 内部自动调用 
n_cst_selectionattrib Selection service Populated with arguments to th 
e n_cst_selection of_Open function 
n_cst_sortattrib DataWindow sort service 用于传递信息到Sort对话框 
n_cst_splashattrib Pfc_PreSplash event (n_cst_appman ger) 调用n_cst_ap pmanager的of_Splash函数打开w_splash 。 
n_cst_sqlattrib SQL service 该属性对象中含有SQL语句的部分内容。 
n_cst_textstyleattrib PFC RichTextEdit control 用于设置和获取text属性(黑体、斜体等)。 
n_cst_toolbarattrib Pfc_PreToolbars event (w_frame) 调用w_frame的pfc_Toolbars事件打开w_toolbars 。 
n_cst_zoomattrib DataWindow print preview service 内部自动调用  
  PFC的常量 
  许多PFC对象都包含了常量。使用常量使得程序更加易读。例如:下面两段代码同样是设置Datawindow的linkage风格,但是第二段则显得更加容易理解: 
// 1 = Filter linkage style. 
dw_emp.inv_linkage.of_SetStyle(1) 
// FILTER 作为一个常量 
dw_emp.inv_linkage.of_SetStyle (dw_emp.inv_linkage.FILTER)  
  约定:PFC的所有常量都采用大写。 
  消息路由 
  消息路由器可以用于任何一个对象与窗体之间的通讯。不过,大部分时候都是用于菜单与窗体之间的消息传递。它提供了一种查找算法用于确定哪个对象来接收消息。 
  使用消息路由时:
  l_ 你菜单中的代码只需要知道代用哪个事件,你无须知道当前的窗口时哪个,或者与其相关的对象名称。 
  l_ 你的窗口无须维护用户事件,只需简单调用DataWindow的事件即可。从而减少了窗口需要维护的事件数量。 
  Message = user event 
  经过消息路由传递的消息实际上就是用户事件名。窗口、控件收到这些消息后就会调用相应的事件。 
  内置的debug消息 
  消息路由机制还提供了内置的debug 
  函数of_SendMessage的工作流程 
  当用户选择菜单项时,Clicked事件中的代码便以欲触发的用户事件名为参数(字符串的形式)调用of_SendMessage函数。Of_SendMessage调用n_cst_menu的of_SendMessage函数,n_cst_menu的of_SendMessage将会调用窗体的pfc_MessageRou ter事件,pfc_MessageRouter事件将会调用你所要触发的用户事件(即在Clicke d中传递字符串参数)。 
  在MDI与SDI应用程序中,函数Of_SendMessage调用pfc_MessageRouter时将有所不同。 
  消息路由是菜单与窗口之间的通讯桥梁。你不可以通过按钮来触发pfc_MessageRouter事件。因为,消息路由会调用GetFocus函数判断当前控件。这样当你按下按钮时,按钮便成了当前控件。 
  PFC中的事务对象 
  PowerBuilder的强大功能之一就是可以快速便利的访问多种数据库。PowerBuild er使用事务对象(Transaction Object)作为PowerBuilder与Database之间的桥梁。SQLCA就是一个默认的事务对象。 
  用户自定义对象n_tr 
  PFC中有一个n_tr对象。它是标准事务对象的子类。其中设有实例变量、用户自定义事件、函数,主要用于扩充与数据库的通讯能。 
  N_tr提供了一套标准函数用于连接、切断、提交、回滚等数据库操作。使用这些函数代替原有的数据库语句。例如使用of_Connect代替CONNECT语句。 
  两处地方使用n_tr 
  l_ 替代sqlca:在应用程序的属性对话框中将SQLCA的默认数据类型设为n_tr 。 
  l_ 附加的事务对象:当你需要访问多个数据库时,你可以再定义一个事务对象。 
  如果你使用了多个事务对象,你可以使用事务对象的registration service ,做到一次提交全部已打开的事务对象,一次回滚所有已打开的事务对象。 
  将SQLCA设置为n_tr类型 
  1. 打开应用程序画笔 
  2. 显示属性窗口,选中Variable页 
  3. 在SQLCA框中输入n_tr 
  4. 点击OK 
  使用n_tr
  1. 如果你不使用SQLCA ,而是使用其他的事务对象。 
  下面的例子假设itr_security是n_tr的实例变量 
  itr_security = CREATE n_tr 
  2. 初始化实例变量ib_autorollback 。这个变量的作用是当事务对象正处于连接状态时应用程序被关闭了或者是该事务对象被删除了的时候,该事务对象应该如何操作 
  itr_security.of_SetAutoRollback(FALSE) 
  关于初始化ib_autorollback的扩展你可以在n_tr的构造事件中初始化ib_autorollback 。 
  3. 使用n_tr的of_Init函数初始化事务对象的属性 
Integer li_return
String ls_inifile 
ls_inifile = gnv_app.of_GetAppIniFile() 
IF SQLCA.of_Init(ls_inifile,"Database") = -1 THEN 
MessageBox("Database","Error initializing from " + ls_inifile) 
HALT CLOSE 
End if  
  4. 调用of_Connect进行数据库连接 
IF SQLCA.of_Connect() = -1 THEN 
MessageBox("Database","Unable to connect using " + ls_inifile) 
HALT CLOSE 
ELSE 
gnv_app.of_GetFrame().SetMicroHelp("Connection complete") 
End if  
  5. 调用n_tr的成员函数 
  调用父类的函数、事件 
  在扩充父类的函数和事件时,你有可能需要先调用父类的函数或事件,然后再依据返回值进行下面的处理。这对那些具有返回值前缀是PFC的事件特别有意义。你在执行子类的代码前必须先确认父类的代码是否执行成功。 
  覆盖父类的函数 
  为了扩展父类的代码,获取父类的返回值。你必须覆盖父类的代码,然后显示的调用父类的函数或事件。 
  采用如下的语法格式调用父类的事件,同时传递参数、获取返回值: 
  Result = Super :: Event eventname(arguments
  采用如下的语法格式调用父类的函数,同时传递参数、获取返回值: 
  result = Super :: Function functionname(arguments
  下面的例子则覆盖了u_dw的pfc_Update事件。当父类的事件处理成功时,子类将信息纪录到日志中。 
Integer li_return 
// Call ancestor event, passing 
// descendant's arguments. 
li_return = Super::Event pfc_Update(ab_accepttext, ab_resetflag) 
IF li_return = 1 THEN 
// ue_WriteLog is a user-defined event. 
li_return = this.Event ue_WriteLog 
END IF 
Return li_return 
  在应用程序中增加联机帮助 
  联机帮助是应用程序中非常重要的一部分。PFC提供了许多函数、事件使得你可以方便的将联机帮助添加到你的应用程序中。
  相关信息:有关PFC的帮助对话框请参考“Deploying PFC dialog box HELP” 。 
  1. 使用n_cst_appmanager的of_SetHelpFile函数设置帮助文件。通常在构造事件中:
  this.of_SetHelpFile(“c:\eis\eisapp.hlp”) 
  2. pfc_PreOpen是为窗口设置帮助主题的最好的地方 
Long ll_helpid 
Ll_helpid = 1020 //1020是一个帮助主题的ID 
Ia_helptypeid = ll_helpid  
  采用这种方式你可以为用户选中的窗口提供详细的帮助。你可以将ia_helptypeid设置成长整形(此时PFC把它解释成帮助主题的ID),或者是字符串(此时PFC将它解释成关键字)。 
  3.(可选)如果你没有使用PFC的m_master的子类。那么,在你的HELP菜单项中调用窗体的pfc_Help事件。因为,pfc_Help定义在窗口w_master中,所以所有的PFC窗口都具有事件。 
  4. 对于对话框,则在其中的HELP按钮的Clicked事件中编写: 
  Parent.Event pfc_Help() 
  PFC自动处理窗口级别的帮助 
  当你从m_master的子类的菜单中选择Help->Help时,消息路由机制会自动的调用当前活动的窗口的pfc_help事件。 
  PFC的升级 
  PFC在发布PowerBuilder的升级版本时同时也包括了PFC的升级文件。如何升级PFC,请按如下规则: 
  l_ PFC的各层(PFC层、PFE层、中间层等)没有任何被修改时:你可以直接安装新的PBLs覆盖原有的PBLs。 
  注意:每次升级PFC时都保留一份原有的文件备份 
  l_ 如果你修改了PFC中的某一层:你必须保证你所作的修改不会被覆盖!请按如下的步骤进行: 
  将PFC升级到最新版本 
  1. 将所有扩展层的PBL文件移到一个不会被安装过程覆盖的目录中。 
  说明:你不应该对PFC的最基类(以PFC为前缀的对象)作任何修改,这里假设你没有对PFC的最基类作任何修改 
  2. 确定你当前的PFC的版本号。你可以在Readme.txt文件中查看,或者在pfc_n_cst_debug的实例变量中查看。版本号的格式:主版本号.次版本号.修正号 
  3. 执行安装程序,将PFC安装口的PBL文件放到PFC所在的目录中,覆盖原有的PFC最基类的PBLS ,即以PFC开头的库文件。 
  4. 合并已存在的扩展对象与新安装的扩展对象。首先详细阅读Readme.txt中说明的新扩展对象清单。然后按照一下的两种方法合并对象: 
  l_ 将新的对象COPY到你的扩展PBLS中。 
  l_ 将已经存在的对象COPY到新的扩展PBLS中。 
  5. 启动PowerBuilder 
  6. (可选)必要的时候调整一下应用程序的库列表 
  7. 打开库画笔,从新编译一边所有的对象。


雁过留声,人过留名

 2008-09-24 13:36

   

freele_china

Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:JiNan
等 级:版主
威 望:6
帖 子:352
专家分:0
注 册:2007-4-6

第 3 楼

  得分:0 

   

PFC编程快速入门

PFC编程快速入门


//------------------------------------------------------------
1前言及PFC的编程特点概述(暂不详述)
//------------------------------------------------------------

  俗话说:实践出真知。所以,笔者一开始并不打算和大家讲什么高深的理论,而是和大家从PFC的实际应用编程着手,带领大家一步一步由浅入深、由点到面地用PFC编写一个实用的MIS(信息管理系统)。至于理论方面的知识,在程序编写的过程中遇到时才结合应用中的实例给大家讲解。当你跟着笔者完成这个PFC实战之旅后,相信你已经能够系统地掌握PFC的编程思想和方法了。
  虽然现在市面上已经有一些关于PFC的书了,但它们都是着重于介绍理论的,对于实际应用于编程的方法的书则没有。由于缺少实践机会,令读者读起来比较难明。所以,我想,我们可以写一本一开始就以PFC的实际应用编程为主,带领读者一步一步由浅入深、由点到面地用PFC编写一个实用的MIS的书。至于理论方面的知识,在程序编写的过程中遇到时才结合应用中的实例给大家讲解。当读者依书完成这个PFC的应用编程后,相信已经能够系统地掌握PFC的编程思想和方法了。然后,我们可以将PFC中各个对象、服务中常用、主要、重要的功能介绍给大家(就不像那本PFC手册那样,什么都写),可能更受大家的欢迎。最后,还以介绍一些高级的编程方法及理论,如:快速开发的理论等。

  在开始编程之前,请大家先准备好以下的编程环境:
  1、PowerBuilder7.0,并且安装了最新的补丁:
  2、数据库系统:
  3、数据库:。本文所有的例子均是基于该数据库进行的。


       作为一种可视化的、面向对象的快速应用开发(RAD)工具,PowerBuilder已被广大数据库应用于开发人员所使用,并获得好评。PowerBuilder全面支持面向对象编程,是集成强大并易于使用的编程语言,内置包括数据窗口(DataWindow)在内的多种对象类,可以方便地访问数据库。
    对于一个数据库应用系统来说,选择PowerBuilder开发工具进行程序设计与开发,是一种快速、高效、省时、省力的方法。PowerBuilder以简洁、直观、实用的编程方式为程序员节约了大量的时间和精力,使得程序员可以把大部分业务放在提高程序执行效率和完善系统功能上,这样做的结果使程序开发时间缩短,开发成本降低,程序编制质量也会大大提高。
    开发一个小型的数据库应用系统,使用PowerBuilder提供的菜单编辑器、窗口编辑器、数据窗口生成器等可视化编程工具,结合PowerBuilder Script脚本语言直接开始程序的编制工作,并不会影响程序的开发效率。然而,对于一个大(中)型数据库应用系统,并使用这种原始的编程方式进行开发与充分利用PowerBuilder提供的基础类库进行开发相比,在程序开发时间、效率、成本等方面,都会有明显的差别。
    PowerBuilder基础类库(PFC)是基于面向对象程序设计的思想而设计的,PFC封装PB Script。它包含了大多数应用共有的内容,例如各种菜单、窗口、用户对象、数据窗口以及错误处理、报表预览、打印、主细录入、查询等等。通过继承,程序员可以方便地把这些类加载到自己的程序中,从而达到提高开发效率的目的。
       作为一种可视化的、面向对象的快速应用开发(RAD)工具,PowerBuilder已被广大数据库应用于开发人员所使用,并获得好评。PowerBuilder全面支持面向对象编程,是集成强大并易于使用的编程语言,内置包括数据窗口(DataWindow)在内的多种对象类,可以方便地访问数据库。
    对于一个数据库应用系统来说,选择PowerBuilder开发工具进行程序设计与开发,是一种快速、高效、省时、省力的方法。PowerBuilder以简洁、直观、实用的编程方式为程序员节约了大量的时间和精力,使得程序员可以把大部分业务放在提高程序执行效率和完善系统功能上,这样做的结果使程序开发时间缩短,开发成本降低,程序编制质量也会大大提高。
    开发一个小型的数据库应用系统,使用PowerBuilder提供的菜单编辑器、窗口编辑器、数据窗口生成器等可视化编程工具,结合PowerBuilder Script脚本语言直接开始程序的编制工作,并不会影响程序的开发效率。然而,对于一个大(中)型数据库应用系统,并使用这种原始的编程方式进行开发与充分利用PowerBuilder提供的基础类库进行开发相比,在程序开发时间、效率、成本等方面,都会有明显的差别。
    PowerBuilder基础类库(PFC)是基于面向对象程序设计的思想而设计的,PFC封装PB Script。它包含了大多数应用共有的内容,例如各种菜单、窗口、用户对象、数据窗口以及错误处理、报表预览、打印、主细录入、查询等等。通过继承,程序员可以方便地把这些类加载到自己的程序中,从而达到提高开发效率的目的。

//------------------------------------------------------------
2概述
//------------------------------------------------------------


一、PFC编程的总原则:
  1、任何时候也不能对以“pfc”开头的库文件进行修改。
  2、必须遵守PFC的命名约定。
  3、任何时候创建对象(如:菜单、窗口)时,都不要用“New”(新建),而应该用“Inherit”(继承),从PFC的扩展层中继承父类。
  4、任何时候使用控件时,都不要用标准的控件,而应该选“user object”,再从PFC的扩展层中选择相应的对象。
  5、(更多的有待补充)

二、PFC的命名约定
Naming conventions
命名约定:
Object naming conventions
对象命名约定
PFC uses the following prefix standard for object names:
PFC使用以下的前缀作为对象命名的标准:
    pfcobject_type_objectname
    Pfc_对象类型_对象名称
where:
其中:

?pfcobject indicates whether the object is part of the PFC level or the extension level. Objects that are part of the PFC level have the prefix PFC_
 “pfcobject”指出该对象是PFC层的对象。如果该对象是PFC层的,则该对象的名称必须以“PFC_”作为前缀。如果是非PFC层的对象,则可以省略该前缀。
?type indicates the object type
 “type”指出该对象的类型。

This table describes the object types.
下表列出了所有对象的命名规则:

Prefix    Description
前缀    说明
m_    Menu
m_    菜单(Menu)
n_    Standard class user object
n_    标准类用户对象(Standard class user object)
n_cst    Custom class user object
n_cst    定制类用户对象(Custom class user object)
s_    Global structure
s_    全局结构休(Global structure)
u_    Visual user object
u_    可视用户对象(Visual user object)
w_    Window
w_    窗口(Window)


For example:
例如:
?Pfc_w_master is the master window and is in the PFC level
 Pfc_w_master    代表PFC层的主窗口对象。
?Pfc_u_tvs is the TreeView visual user object and is in the PFC level
 Pfc_u_tv    代表PFC层的树状浏览(TreeView)可视用户对象。
?U_dw is the DataWindow visual user object and is in the extension level
 U_dw        代表扩展层的数据窗口(DataWindow)可视用户对象。
?N_cst_dwsrv is the custom class user object for DataWindow services and is in the extension level
 N_cst_dwsrv    代表扩展层的提供数据窗口服务(DataWindow services)的定制类用户对象。
?N_tr is the transaction standard class user object and is in the extension level
 N_tr        代表扩展层的事务处理标准类用户对象。

Variable naming conventions
变量的命名约定:
PFC uses the following standard for variable names:
PFC使用以下的前缀作为变量命名的标准:
    <scope><datatype>_variablename
    <作用域><数据类型>_变量名称
Scope is one of the following:
作用域包括了以下几种:

Prefix    Description
前缀    说明
a    Argument to an event or function
a    事件或函数的参数
g    Global variable
g    全局变量
i    Instance variable
i    实例变量
l    Local variable
l    局部变量
s    Shared variable
s    共享变量


For standard data types, datatype is one of the following:
对于标准的数据类型,<数据类型>包括了以下几种:

Prefix    Description
前缀    说明
a    Any
a    Any(and类型)
blb    Blob
blb    Blob(大二进制对象)
b    Boolean
b    Boolean(布尔类型)
ch    Character
ch    Character(字符类型)
d    Date
d    Date(日期类型)
dtm    DateTime
dtm    DateTime(日期时间类型)
dc    Decimal
dc    Decimal(带符号十进制小数型)
dbl    Double
dbl    Double(双精度类型)
e    Enumerated
e    Enumerated(枚举类型)
i    Integer
i    Integer(整型)
l    Long
l    Long(长整型)
r    Real
r    Real(实型)
s    String
s    String(字符串类型)
tm    Time
tm    Time(时间类型)
ui    UnsignedInteger
ui    UnsignedInteger(无符号整型)
ul    UnsignedLong
ul    UnsignedLong(无符号长整型)


For reference variables, datatype is one of the following:

Prefix    Description
app    Application
app         Application(应用)
ab    ArrayBounds
cbx    CheckBox
cbx       CheckBox(复选框)
cb    CommandButton
cb        CommandButtOn(命令按钮)
cd    ClassDefinition
cdo    ClassDefinitionObject
cn    Connection
cn          Connection(链接)
cninfo    ConnectionInfo
cninfo      ConnectionInfo(链接信息)
cno    ConnectObject
cno         ConnectObject(链接对象)
cxk    ContextKeyword
cxinfo    ContextInformation
cpp    cplusplus
ds    DataStore
ds        DataStore(数据存储)
dw    DataWindow
dw          DataWindow(数据窗口)
dwc    DataWindowChild
dwc         DataWindowChild(子数据窗口)
drg    DragObject
drg        DragObject(拖动对象)
drw    DrawObject
drw       DrawObject(画图对象)
ddplb    DropDownPictureListBox
ddplb        DropDownPictureListBox(下拉式图形列表框)
ddlb    DropDownListBox
ddlb        DropDownListBox(下拉式列表框)
dwo    DWobject
dwo       DWobject(数据窗口的对象)
dda    DynamicDescriptionArea
dda       DynamicDescriptionArea(动态描述区)
dsa    DynamicStagingArea
dsa         DynamicStagingArea(动态状态区)
ed    EnumerationDefinition
eid    EnumerationItemDefinition
em    EditMask
em         EditMask(编辑屏蔽框)
env    Environment
env         Environment(环境变量)
err    Error
err         Error(错误信息)
ext    ExtObject
ext         ExtObject
gr    Graph
gr         Graph(统计图)
go    GraphicObject
go        GraphicObject(统计图对象)
grax    GrAxis
grax        GrAXis
grda    GrDispAttr
grda       GrDispAttr
gb    GroupBox
gb        GroupBOx(组选框)
hsb    HorizontalScrollBar
inet    Inet
ir    InternetResult
ln    Line
lb    ListBox
lv    ListView
lvi    ListViewItem
mfd    MailFileDescription
mm    MailMessage
mr    MailRecipient
ms    MailSession
mdi    MDIClient
m    Menu
mc    MenuCascade
msg    Message
mle    MultiLineEdit
nv    NonVisualObject
oc    OleControl
oo    OleObject
ostg    OleStorage
omc    OmControl
omcc    OmCustomControl
omec    OmEmbeddedControl
omo    OmObject
omstm    OmStream
omstg    OmStorage
oval    Oval
p    Picture
pb    PictureButton
pbcpp    PBToCPPObject
plb    PictureListBox
pl    Pipeline
po    PowerObject
procall    ProfileCall
proclass    ProfileClass
proln    ProfileLine
prort    ProfileRoutine
pro    Profiling
rb    RadioButton
rec    Rectangle
rem    RemoteObject
rte    RichTextEdit
rrec    RoundRectangle
rteo    RteObject
scrd    ScriptDefinition
sle    SingleLineEdit
sle           SingleLineEdit(单行编辑器)
srv    Service
st    StaticText
st          StaticText(静态文本)
std    SimpleTypeDefinition
str    Structure
str           structrue(结构)
tab    Tab
tab         Tab(标签)
tabpg    TabPage
tabpg       TabPage(标签页)
tcan    TraceActivityNode
tcbe    TraceBeginEnd
tcerr    TraceError
tcf    TraceFile
tcln    TraceLine
tcgc    TraceGarbageCollect
tco    TraceObject
tcrt    TraceRoutine
tcsql    TraceSQL
tct    TraceTree
tctn    TraceTreeNode
tcterr    TraceTreeError
tctsql    TraceTreeSQL
tctgc    TraceTreeGarbageCollect
tctln    TraceTreeLine
tcto    TraceTreeObject
tctrt    TraceTreeRoutine
tctu    TraceTreeUser
tcu    TraceUser
td    TypeDefinition
tr    Transaction
tr          Transaction(事务对象)
trp    Transport
trp         Transport 
tv    TreeView
tv          TreeView(树状浏览)
tvi    TreeViewItem
tvi         TreeViewItem(树状测览项)
uo    UserObject
uo          UserObject(用户对象)
vrcd    VariableCardinalityDefinition
vrd    VariableDefinition
vsb    VerticalScrollBar
vsb           VerticalScrollBar(垂直滚动条)
wo    WindowObject
wo          WindowObject(窗口对象)
w    Window
w           Window(窗口)


Function naming conventions
函数的命名约定:

Global functions use the f_ prefix and object functions use the of_ prefix.
全局函数(Global functions):使用“f_”作为函数的前缀。
对象函数(object functions):使用“of_”作为函数的前缀。


  三、PFC的面向对象特点
  PFC的面向对象特点是学习PFC编程中一定要重点掌握的知识。可以这么说:PFC的应用,实际上就是面向对象技术的应用。PFC的一切,就是面向对象技术。PFC是PowerBuilder面向对象技术的体现。
  由于PFC采用了面向对象的程序设计方法,程序的封装性和继承性使得程序的后期维护工作变得更为轻松,性能价格比更为优越。这完全得益于面向对象这种程序设计方法的合理性,它把一个复杂的问题分解成与该问题相关的各个部分的子模块,再把这些子模块抽象为对象。若一个由祖先继承而来的对象出现错误,可以简单地对该于对象进行修改而不必去涉及其祖先对象,反之,若对处于同一层次的全部子对象进行类似的修改,可直接修改其祖先对象。
  PowerBuilder面向对象的特点主要体现在用户对象的技术运用上。PFC基础类库把PowerBuilder的多种对象以类的形式存储在库文件中,要正确有效地利用PowerBuilder基础类库进行程序的开发设计,必须了解面向对象的编程技术,了解PFC基础类库的面向对象特点。
  PowerBuilder把一些常用的、具有共性特征的对象(例如:窗口、菜单、数据窗口、用户对象等)提炼出来,并在每个对象中封装了不同的服务,构造了PFC基本类库。
      PFC基础类库完美地体现了面向对象程序设计的三方面重要特征:
  ·继承性(Inheritance)
  ·封装性(Encapsulation)
  ·多态性(Polymorphism)

  用户对象是PFC面向对象的具体表现,PFC的面向对象特点完全在用户对象中表现出来。
  以下着重介绍PFC中常用的用户对象:
  用户对象有两种类型:可视的用户对象(Visua1 user object)和类用户对象(Class user object)。
  (1)可视用户对象指的是一个可重用的可视控件或一个含有预定义行为的可视控件。
  PFC包含了两种类型的可视用户对象:
  标准可视用户对象
  PFC标准可视用户对象由PowerBuilder的标准可视控件继承而来,通过扩充标准控件的定义,完成特定的功能。每个PFC的标准可视用户对象都与窗口控件进行通信,这些对象中包含了预定义的程序,实现各种PFC应用服务。
  定制可视用户对象
  PFC定制的可视用户对象是将几个可视控件打包成一组的对象,它将多种服务有计划地组合在一起,完成一个复杂的功能。
  (2)类用户对象指的是在不使用可视用户对象时,完成一个执行过程而定义的可重用的不可视控制,它是不可见的,无法在窗口上直接看到,需通过程序来调用。
  PFC包含了两种类型的类用户对象:
  标准的类用户对象
  PFC标准的类用户对象由PowerBuilder的不可视标准控件继承而来,通过扩充标准控件的定义,完成特定的功能。  PFC为事务传输、错误处理和其他所有的扩展系统对象都提供了标准的类用户对象。
  定制的类用户对象
  从PowerBuilder的非可视对象类中继承了各种定义,封装了数据和代码。
  定制的类用户对象允许程序员定义自己的对象类。
  PFC使用定制的类用户对象执行多种服务,它还提供了一些接口参数,程序员可以通过这些接口参数与对象内部的实例变量、函数和事件进行通信。


  应用PFC编程时,在面向对象程序设计的三方面主要特征中,我们接触最广泛的是“继承”特征了。可以这么说:在构成应用界面的每一个元素,如:窗口、菜单、控件等等,无一不是从PFC的对象中继承而来的。所以,在这里,将给大家详细讲下PFC中的继承特性,请大家一定要注意体会掌握,因为,在以后的编程中,你无时无刻不都在与“继承”打交道。
  继承是一对象获取另一对象之性质的过程,它使得那些与基本类共享的性质能很方便地进行延续和扩展。继承对象类具备被继承对象类的所有属性、变量、函数、结构、控件和程序。对祖先对象的修改会使其所有子孙对象做相应的修改,子孙对象可修改或扩充祖先对象的属性和服务,但不能对祖先对象的控件进行删减。正是这种继承机制才使得一个对象成为某一基础类的实例。
  继承具有以下优点:
  ·可充分利用系统资源,减少程序的重复开发,大大提高了开发效率;
  ·使应用的对象保持一致,维护了系统的整体一致性;
  ·减少了人为程序错误的发生概率;
  ·使程序更易于维护。
  在PFC基础类库中,各种基础类的对象均可以被继承,如窗口、菜单、结构、数据窗口、用户对象等等。由继承而来的子孙对象包含了祖先对象的所有属性、变量、函数、结构、控件和程序,并可对它们进行修改和扩充。对于一个通过继承创建的后代窗口,可以进行如下进一步的处理:改变窗口的属性;在窗口中增加新的控件;在窗口中修改现存控件;改变窗口的大小和位置;改变窗口中控件的大小和位置;为窗口及控件编制新的处理程序;为窗口和控件扩展继承来的处理程序;用新的处理程序覆盖继承来的处理程序;引用祖先的函数、结构和变量;为该窗口定义新的函数、结构和变量。
  对于一个通过继承创建的后代菜单,可以进行如下进一步的处理:改变菜单项的属性;在菜单中插入菜单项;修改菜单项;为没有处理程序的菜单项增加处理程序;扩展继承来的处理程序;用新的处理程序覆盖继承来的处理程序。
  对于一个通过继承创建的后代用户对象,可以进行如下进一步的处理:改变属性和变量的值;为没有事件处理程序的事件增加处理程序;扩展继承来的事件处理程序;用新的处理程序覆盖继承来的处理程序;为可视用户对象添加控件;引用祖先的函数、事件和结构。
  值得注意的是,对于继承来的可视对象不能对其包含的控件进行删减,若某一控件确实不用,可通过修改其属性使之不可用或不可见。


  四、PFC的结构是一种基于服务的结构(Service-Based Architecture),PowerBuilder提供了各种类库和它们的源代码,程序员可以很方便地对类中的程序和控件进行修改和扩充,使之符合自己的需求。
  PFC基础类库基于服务的结构模式为基础类库的扩展提供了广阔的空间,它包含了PowerBuilder提供的多种对象以及它们各自所封装的多种服务,分别完成特定的功能。
  在PFC对象内封装的函数、事件和实例变量能够完成许多与应用环境无关的操作,称之为服务。程序员通过调用基础类对象来获得封装在对象中的服务。
  具体的服务有以下几种:应用服务;数据窗口服务;菜单服务;窗口服务;尺寸调整服务;转换服务;日期/时间服务;文件服务;INI文件服务;数据服务;平台服务;选择服务;SQL解析服务;字符串处理服务;元类服务;逻辑单元服务等。




//------------------------------------------------------------
03基本准备
//------------------------------------------------------------

四、实战之旅:
  一、更新库的搜索路径。
  1、为应用程序创建一个新的库文件。打开库管理面板(Library),点击工具条上的“Create Library”图标,并从弹出的“Create Library”对话框(如图所示)中选择新库的保存路径,输入新库的名称。这里我们假设将库保存到D:根目录下,并命名为:Design.pbl。
  2、创建应用对象。点击工具条上的“New”图标,从弹出的对话框中选择“Start Wizards”页面,双击“Application”图标。我们将看到如图所示的界面,在“Application Name”下输入应用对象的名称,我们这里命名为:design;并在“Library”下选择将该应用对象保存到什么库中。我们这里当然是将其保存到D:根目录下的Design.pbl中。单击“Finish”完成应用对象的创建。
  3、选择“File”菜单下的“Library List...”命令,在弹出的“Library List”窗口中单击“Browse...”按钮,如图所示。
  4、从弹出的“Select Library”对话框中选择需要的库文件:进入存放PFC库文件的目录下,按下[Ctrl]键并点击鼠标来选中下列文件:Pfcapsrv.pbl、PfcDwsrv.pbl、Pfcmain.pbl、Pfcutil.pbl、Pfcwnsrv.pbl、Pfeapsrv.pbl、Pfedwsrv.pbl、Pfemain.pbl、Pfeutil.pbl、Pfewnsrv.pbl。如图所示。
  5、点击“Open”按钮,选中的库文件就显示到库文件的搜索路径列表中。
  6、点击“Apply”按钮,PowerBuilder将上述PFC文件添加到应用文件列表中。

  ***理论知识:(这里要介绍的知识比较多,主要涉及到PFC的面向对象的特点、PFC各个库文件所包含的内容及作用、如何扩展PFC、如何升级PFC等,我还没整理好。)
  根据基础类实现的阶段划分为如下两类:
  ·基础类库文件:放置基础类对象的原始设计;
  ·扩展基础类库文件:放置继承基础类进行扩展设计后的扩展对象。
  没有任何一种类库能够包容用户所有的需求,典型的做法是把PFC库中的对象进行修改和扩充,使它和应用中的函数、对象融合为一体,如果没有基础类库的扩展层,就会导致这样一个问题:如何升级一个新版的PFC库,新版的应用将覆盖以前定制的类,迫使你重新进行手工改动以适应新的版本。
  PFC利用其继承性建立了扩展层,如下表所示。所有的扩展对象都放置在相对独立的PBL文件中,对扩展层可方便地进行升级和更新,而不会对其祖先层产生任何影响。
    表 PFC提供的服务在PBL库文件中的分布
内容            祖先层            扩展层
应用和全局性服务        PFCAPSRV.PBL        PFEAAPSRV.PBL
数据窗口服务        PFCDWSRV.PBL        PFEDWSRV.PBL
可视的和标准的类用户对象    PFCMAIN.PBL        PFEAMIN.PBL
实用程序的服务        PFCUTIL.PBL        PFEUTIL.PBL
窗口服务            PFCWNSRV.PBL        PFEWNSRV.PBL

  祖先层类库中的对象包含了所有的实例变量、事件和函数;扩展层类库中的对象是祖先库中相应对象的子孙对象,通过继承它们可以调用祖先对象的实例变量、事件和函数。可以使用PowerBuilder Browse浏览子孙对象内含的实例变量、事件和函数。
  使用扩展层有两个突出的优点:
  ·可以增加控件、部件和特殊逻辑的应用到扩展层对象;
  ·对扩展层进行升级不会影响类库程序的兼容性。
  需要注意的是:
  (1)为保持与旧版程序的兼容,在PFCOLD.PBL中存放了新版已放弃使用的对象。如果运行一个旧版的PFC程序,需要将PFCOLD.PBL加入到应用的搜索路径中去;
  (2)程序员可以通过修改扩展层的对象来定制PFC应用,但不能去修改祖先层的对象。例如:应用程序可以使用扩展层的用户对象并且从扩展层继承一个窗口。


        基础类库的部件
  PFC由以下几个部件构成:
  ·一组PBL类库文件;
  ·一个PFC数据库;
  ·一组支持快速开发的PBL库(Quickstart PBLS);
  ·PFC编程示例;
  ·一个简单的应用。

        PFC基础类库的库结构及其存放位置
  PowerBuilder的基础类库文件和扩展基础类库文件共有十三个,根据所包含基础类的不同功能进行了划分,其中以PFC开头的是基础类库文件,以PFE开头的是扩展基础类库文件,具体说明如下表所示。
                          表  PowerBuilder基础类库在PBL文件中的分布
库文件名            说    明                    安装路径
PFCMAIN.PBL    包含标准类用户对象、窗口对象、菜单            ..\pb6\adk\pfc
PFEMAIN.PBL    对象和标准可视类用户对象                ..\pb6\adk\pfc

PFCAPSRV.PBL    包含提供应用服务所必须的定制类用            ..\pb6\adk\pfc
PFEAPSRV.PBL    户对象                        ..\pb6\adk\pfc

PFCDWSRV.PBL    包含提供数据窗口服务需要的定制类            ..\pb6\adk\pfc
PFEDWSRV.PBL    用户对象                        ..\pb6\adk\pfc

PFCWNSRV.PBL    包含窗口服务需要的定制类用户对象            ..\pb6\adk\pfc
PFEWNSRV.PBL                            ..\pb6\adk\pfc
                                                   
PFCUTIL.PBL    其他服务需要的对象,例如DEBUG服            ..\pb6\adk\pfc
PFEUTIL.PBL    务和SQL测试服务等                ..\pb6\adk\pfc

PFESECAD.PBL    包含安全管理服务需要的各类对象            ..\pb6\adk\pfc\security

PFCECSC.PBL    包含安全检测需要的各类对象            ..\pb6\adk\pfc\security

PFCOLD.PBL    存放新版PB基础类库淘汰的各种对象            ..\pb6\adk\pfc

  注:基于PowerBuilder5.0版基础类库开发的应用升级到6.0版时,用户必须将PFCOLD.PBL添加到检索路径当中才能够顺利地实现升级。
  以上是PowerBuilder基础类库在PBL文件中的分布。


        如何安装PFC的升级版
  在PowerBuilder从一个正式版本升级到另一个正式版本时,还定期发布一些修正版本。作为PowerBuilder升级版的附加部份,每个修正版也包括了新的PFC升级版,对使用旧版PFC编制的应用程序来说,将面临一个PFC的升级问题。但由于PFC这种将不同层次的对象存放在不同的库文件中给我们的升级带来了极大的方便。
  这可能出现以下两种情况:
  (1)使用旧版PFC时,并没有对PFC的祖先层和扩展层做任何扩充和修改,只是直接通过继承使用PFC。如果是这种情况,简单地安装新版的文件覆盖旧版的文件。
  (2)使用旧版PFC时,创建了一个或多个中间扩展层,或对PFC的扩展层进行了修改和扩充。如果是这种情况,需确保新建的中间层和所做的扩充不被新版程序覆盖。可以按以下步骤进行版本升级:
  a. 将所有的PFC扩展文件备份到另外一个目录,确保新程序安装时不被覆盖。
  b. 查看当前的版本信息。可以在当前PFC的Readme.txt文件中找到有关的版本信息,或者在pfc_n_cst_debug中定义的实例变量majorrevision . minorrevision . fixesrevision中得到当前的版本信息。
  c. 运行新版的安装程序,用新的PFC文件覆盖旧的文件,PFC祖先层得到更新。
  d. 合并新的扩展层对象和旧的扩展层对象。查看新版PFC的Readme.txt文件,有一个新增扩展层对象的列表,可用以下两种方法进行合并:
  <1>把新增的扩展层对象全部全部复制到以前定制的PFC扩展层PBL文件中。从新版的PFC扩展层PBL文件中找出新添加的对象,并反它复制到以前定制的PFC扩展层PBL文件中。然后将新版的PFC扩展层文件移走,将备份的扩展层文件恢复到PFC路径下;
  <2>将定制的对象复制到新版的PFC扩展层中。将备份的PFC扩展层PBL文件中的所有对象复制到新版PFC的扩展层PBL文件中。
  e 启动PowerBuilder。
  f (可选地)根据情况更新应用物搜索路径。
  g 打开库管理面板,将应用重建。



  二、使用n_tr与SQLCA建立链接。
  1、打开应用对象面板,打开“Properties”(属性)设置窗口。
  2、点击“General”页面的“Additional Properties”按钮,我们将看到如图5所示的设置窗口。
  3、切换到“Variable Types”标签页,,如图6所示。
  4、将“SQLCA”下的输入框中的“transaction”改为“n_tr”。
  5、点击“OK”按钮,返回到应用对象设计面板,保存修改。

  ***理论知识:关于n_tr
  n_tr是一个从系统事务对象继承而来的定制的事务对象。这个定制的事务对象中包含了实例变量、事件和函数,扩展并封装了数据通信服务。
  n_tr提供了一套标准的函数完成数据库的链接、断开、提交和恢复,可帮助程序员管理事务对象。
  程序员可用n_tr内的函数代替原先的SQLCA事务对象管理命令。例如:链接数据库用of_Connect函数取代CONNECT命令语句。
  假设应用程序使用了多个事务对象,程序员可以使用事务对象注册服务提供的函数,完成对多个事务对象的管理。如:提交所有打开的事务或回滚所有打开的事务。

  三、创建一个应用管理器。
  ㈠关于应用管理器:
  PFC在应用管理器中控制各种应用的处理过程。这策略的优点有:1、可扩充性;2、可重用性。

  ㈡我们通过继承n_cst_appmanager创建应用管理器。具体步骤如下:
  1、点击工具条上的“Inherit”(继承)按钮,弹出“Inherit From Object”对话框,如图所示。
  2、在“Application Libraries:”下的库文件列表中选中Pfeapsrv.pbl,在显示的用户对象列表中选中。然后,在显示的用户对象列表中选中“n_cst_appmanager”,点击“OK”按钮,将出现如图所示的用户对象设计面板。
  3、保存该用户对象:将其保存到Design.pbl库中,命名为:n_cst_designmanager。    

  ㈢应用管理器一般用于完成以下功能:
  1、初始化应用程序的全局变量,如:帮助文件名;INI文件名;注册信息等等。(在Constructor事件中完成)
  2、(可选)控制用户的登录。(在pfc_open事件中完成)
  3、使用事务对象注册服务注册SQLCA。如果需要控制用户的登陆,则该事件在pfc_LogonDlg事件中写,否则在pfc_open中写。
  4、打开应用程序的初始化窗口。这一事件一般就在pfc_open事件中完成。

  具体分析及代码:
  1、Constructor事件的代码:
    this.of_SetAppIniFile("Design.ini")
    this.of_SetHelpFile("Design.hlp")
    this.of_SetLogo("Design.bmp")
    this.of_SetCopyRight("CopyRight by BS2001")
    this.of_SetVersion("版本  0.1")

  ***理论知识:
  注意以述代码,这里使用了调用PFC对象里封装了服务、功能的最基本、直接的方法:通过调用PFC函数启用相应功能。
  几乎所有的PFC函数都是对象函数,这些函数都定义在PowerBuilder的对象(如:窗口、菜单和用户对象)中。封装在PowerBuilder的对象中的函数可以使用户很快地明白该对象提供了什么样的功能。
  PFC函数使用了Set/Get/Is的命名规则来控制对实例变量的访问:
  of_Set    函数可设置实例变量的值
  of_Get    函数可访问非布尔型的实例变量
  of_Is    函数可确定布尔型的实例变量的状态值

  对于其他类型的实例变量,例如公用的实例变量,可以直接对它们进行操作。此外,还有一些变量仅供内部使用,外部函数不需也不能对它们进行操作。

  调用PFC对象函数的注意事项:
  (1)首先要确信已创建了该对象的一个实例
  PowerBuilder在窗口打开时创建窗口、菜单和可视用户对象,还可以使用of_Setservicename函数(定义在u_dw、n_cst_appmanager和w_master中)创建更多的类用户对象。例如,u_dw对象函数产生一个排序的服务并在实例变量inv_sort中存入一个该服务的引用,程序员可以把调用这个函数的代码写在数据窗口的Constructor事件中。如:
    this.of_Setsort(TURE)
  一些PFC对象使用了PowerBuilder的自动实例化特性,这些对象没有设置实例化函数,PowerBuilder在使用它们定义一个变量时自动为其创建实例对象。

  (2)在应用程序中正确地调用对象函数
  下面的例子使用了排序服务,指定了按数据窗口的列名进行排序、按显示的值或点击的列进行排序,当用户选择菜单条的“View”-“Sort”项时,显示一个具有拖动风格的对话框:
    this.inv_sort.of_SetColumnNameSource(This.inv_sort.HEADER)
    this.inv_sort.of_SetUseDisplay(TRUE)
    this.inv_sort.of_SetColumnHeader(TRUE)
    this.inv_sort.of_Style(This.inv_sort.DRAGDROP)




  2、控制用户的登陆:
  在应用管理器的pfc_open中写如下代码:
    integer li_rc
    li_rc=of_LogonDlg()
    if li_rc=1 then        //写成功登陆的代码...
        open(w_design_frame)    //这是最常见的成功登陆后的事件:完成上述第4步的工作:打开应用程序的初始化窗口。具体分析见下面的“创建一个框架(frame)窗口”部份。
    end if

  代码分析:
  of_LogonDlg函数的使用:该函数会调用w_logon(PFC中的登陆窗口)。当用户输入的必要信息:用户名称及登陆密码后,并按下该窗口中的“确定”按钮,程序会调用该窗口的pfc_default事件,其中一行关键代码会调用应用管理器中的pfc_Logon事件,并会传递两个参数:sle_userid.text和sle_password.text给pfc_Logon事件。而且,w_logon的pfc_default事件会接收pfc_Logon的返回值作相应的处理,主要是:用户输入信息合法的处理及如果用户输入的信息不合法,还可以重试的次数(详见以下的代码分析)。当w_logon关闭时,它会返回一个整型的值给of_LogonDlg:返回值为1时,代表用户信息合法;为0时,表示用户按了“取消”按钮,取消登陆;为-1时,表示用户信息不合法。所以,在调用of_LogonDlg后,可以作相应的处理,见上述代码。

  注意:如果你调用了of_LogonDlg函数,一定要在应用管理器的pfc_Logon事件中写相应的连接数据库的代码,也就是完成第3步的工作:使用事务对象注册服务注册SQLCA。of_LogonDlg执行的第一个代码就是调用pfc_Logon事件初始化登陆参数。见以下代码:
  在应用管理器的pfc_LogonDlg中写如下代码:
    SQLCA.DBMS = "ODBC"
    SQLCA.AutoCommit = False
    SQLCA.DBParm = "ConnectString='DSN=New_City;UID=' " + as_userid + " ' ;PWD=' " + as_password + " ' '" 

    //以下4行代码就是判断是否成功登陆,如果是,则返回1给w_logon,否则,返回-1。
    if SQLCA.of_Connect() <> 0 THEN
        Return -1
    else
        Return 1
    end if

  ***小技巧:在用户登陆数据库时,当用户输入的信息不合法时,如何控制用户重试的次数?
  w_logon中的pfc_default事件是通过一个变量:ii_logonattempts来控制的。要设置该变量的值,可以在应用管理器的pfc_prelogondlg事件中写如下代码:
    anv_logonattrib.ii_logonattempts = 3    //“3”就代表用户可以重试的次数是3次。
    anv_logonattrib.is_logo ="logo.bmp"    //指定显示在登陆窗口上的图片。
  anv_logonattrib是一个n_cst_logonattrib类型的对象,是pfc_prelogondlg事件的一个参数,当调用(触发)pfc_prelogondlg事件时,会传递这个参数过来。n_cst_logonattrib中封装了如下的变量:
    Public:
    integer    ii_rc = -99
    integer    ii_logonattempts = 1
    string    is_userid
    string    is_password
    string    is_logo
    string    is_appname
    powerobject    ipo_source
  以上各个参数一般都于pfc_prelogondlg事件中设置。以上各个参数的含义及作用请参阅n_cst_logonattrib的帮助。

  ***触类旁通:
  与n_cst_logonattrib相类似的结构还有很多,它们主要用于控制一些属性的设置。具体请参阅PB的在线帮助:PowerBuilder Foundation Class Library (PFC)下的Global Structures and Structure Objects项。
  这些结构对象统称为属性对象(attribute object)。PFC包含了一些专门提供属性服务的用户对象。这些用户对象特有以下特点:
  a. 内含共有的实例变量;
  b. 可自动实例化;
  c. 对象名以attrib结尾;
  d. 经常被用来为pfc_pre事件处理程序传递消息,如:pfc_preAbout事件;
  e. 具备了可扩充性。可以追加自定义的实例变量。

  鉴于这些对象可以灵活方便地进行扩展,PFC使用它们代替了结构。
  除了可定义附加的公共实例变量以外,还可以使用可存取级控制和对象函数进一步定制对象的行为,如下表所示:







  一般来说,还经常在应用管理器中设置的的全局变量还有:
  ①n_cst_aboutattrib:在pfc_preabout事件中设置,主要用于控制“关于”的信息。要在程序启动时调用“关于”窗口,请于pfc_open中调用函数of_about。(下文还有详细介绍“关于”窗口的使用的内容)
  ②n_cst_splashattrib:在pfc_presplash事件中设置,主要用于控制“启动屏幕”的信息。要在程序启动时显示“启动屏幕”,请于pfc_open中调用函数of_splash。(下文还有详细介绍“启动屏幕”窗口的使用的内容)

  四、定义全局变量。
  PFC在程序运行时使用全局变量gnv_app来实现应用管理器的功能,具体步骤如下:
  1、打开应用对象设计面板。
  2、定义全局变量,并将其类型设为:n_cst_designmanager(即第三步里设计的用户自定义对象):
    n_cst_designmanager gnv_app
  注意:这个全局变量的名称一定要为gnv_app,不可更改。定义gnv_app为n_cst_designmanager的类型后,程序员可以象访问n_cst_designmanager一样访问在n_cst_designmanager中新增的变量、用户事件和函数。
  3、在“Open”事件中加入如下代码:
    gnv_app = CREATE n_cst_designmanager
    gnv_app.Event pfc_open(commandline)
  4、在“close”事件中加入如下代码:
    gnv_app.Event pfc_Close()
    DESTROY gnv_app
  5、保存修改。

  至此,前期的准备工作已经完成了,下面,我们将进入利用PFC进行正式的程序界面、功能的设计。

//------------------------------------------------------------
04创建框架
//------------------------------------------------------------
        第二部份 程序框架的构建

一、创建应用界面的第一步:创建一个框架(frame)窗口
  创建一个典型的多文档应用,先要定义一个多文档的frame窗口。在这个frame窗口中可以打开多个sheet窗口。PFC提供了w_frame类,它包括了许多文档的特征,如:状态提示条和sheet窗口管理。
  一个MDI应用程序的典型方案:使用w_frame,w_sheet窗口作为你的框架窗口与表单窗口的父类。在w_sheet窗口中增加你的应用程序中所有表单窗口需要的事件、实例变量、函数。你必须为每一个表单窗口定义菜单。
  第一步:通过继承w_frame创建一个后代frame窗口
  具体步骤:
  1、点击工具条上的“Inherit”(继承)按钮,弹出“Inherit From Object”对话框,如图所示。在“Object Type”处选“Windows”。
  2、在“Application Libraries:”下的库文件列表中选中pfemain.pbl。然后,在显示的窗口对象列表中选中“w_frame”,点击“OK”按钮,将出现如图所示的窗口对象设计面板。
  3、修改一些必要的属性:如,可以将窗口的“Title”的属性改为:“PFC设计实战”。
  4、保存该窗口对象:我们一般将其保存到Design.pbl库中,命名为:w_design_frame。

  第二步:根据需要添加一些必要的代码。
  一般地,框架窗口(frmae)主要是用来调用实际的功能模块的,也就是打开相应模块的表单窗口(Sheet)。所以,我们一般要在frmae窗口的pfc_open中写入如下代码:
    string ls_sheet
    w_sheet lw_sheet
    ls_sheet = Message.Stringparm
    OpenSheet(lw_sheet,ls_sheet,this,0,Layered!)

  这段程序打开了一个由Message.StringParm参数指定的sheet窗口,这么参数一般是由菜单的clicked事件触发时传递过来,这在创建菜单对象的章节再详述。请大家注意:在第3行代码中,出现了一个PowerBuilder中一个非常重要、应用非常广泛的概念:消息路由(Message Router),在以后的应用中,经常要使用到Message.StringParm来传递信息,例如窗口的名称。
  PFC使用消息路由控制窗口和菜单之间的通信,这个定制的消息传送结构被加载到所有的PFC菜单和窗口中。消息路由可以在任何类型的对象和窗口之间实现通信,但常用的还是在菜单和窗口之间传送信息。它根据定义好的规则将消息传递给正确的接收对象。
  使用信息路由,有以下的优点:
  a. 在菜单的脚本程序中只需知道需调用的事件,而不必关心当前的窗口或其他链接对象的名称;
  b. 窗口中的用户事件简单地调用数据窗口中的事件,这样减少了对窗口事件的维护。

  通过消息路由传递的信息实际上就是包含了用户事件名称的一个字符串,窗口或其他的控件接收到传来的信息后,触发相应的事件。
  信息路由还内置了调试信息,可以在出现错误时自动提示错误信息。
  当用户选择了某一菜单项,这个菜单项的Click事件被触发,调用菜单的of_SendMessage函数传送要调用的用户事件名。of_SendMessage函数又调用了n_cst_menu中的of_SendMessage函数,该of_SendMessage函数调用了窗口的pfc_MessageRouter事件,在这里激活指定的事件。

  针对MDI和SDI这两种不同风格的程序设计方式,PFC调用消息路由年度计划芤有所不同。如图所示。

  pfc_MessageRouter用户事件调用传来的指定事件,该事件可以是定义在窗口、当前的控件或激活的数据窗口中。如图所示。

  消息路由是进行菜单和窗口间通信的主要工具。除数据窗口外,不能使用命令按钮调用pfc_MessageRouter事件。这是因为消息程序调用了GetFocus事件访问当前的控件,如果点击了一个命令按钮,将访问它本身。


  还可以根据需要,在pfc_PreOpen事件中开启框架窗口提供的服务,如:
    this.of_SetSheetManager(TRUE)    //开启sheet窗口管理服务,它提供了最小化所有sheet窗口和恢复最前一个sheet窗口排列的命令。
    this.of_SetStatusBar(TURE)        //开启状态提示服务。
    this.inv_statusbar.of_SetTimer(TRUE)    //把时间和日期显示在状态条上。

  第三步:修改应用管理器,在n_cst_designmanager的pfc_Open事件中加入打开框架窗口w_design_frame的代码。详见第一部份第三章:创建一个应用管理器里关于控制用户的登陆的代码。

  二、创建菜单
  在PFC应用程序中,所有菜单都是由m_master或它的后代窗口继承而来的,程序员根据需要增加、修改或隐藏一部份菜单项。m_master为所有PFC窗口、数据窗口和可视化控件提供了相应的菜单项。
  在pfewnsrv.pbl库内,有两个菜单对象:m_master和m_frmae。m_master直接继承自菜单对象的最原始祖先:pfc_m_master,自m_master后的菜单都是继承m_master所得。一般典型的应用是:使用m_master作为应用程序Sheet窗口的祖先菜单,使用m_frame作为应用程序的Frame窗口菜单。程序员可以在m_master菜单中加入所有应用菜单都要使用的特定菜单项,然后创建一个由m_master继承而来的Sheet窗口菜单,并在恰当的时候控制这些菜单项是否有效。m_frame由m_master继承而来,作为Frame窗口菜单,一般只具有调用相应的功能模块的功能,其它菜单项都可以隐藏起来。。
  m_master中包含了一些标准的菜单项,可调用相应窗口中的事件处理,使用时应注意以下几点:
  1、如果某一菜单项对当前窗口无效,应使之不可见;
  2、如果菜单项支持对当前窗口的操作,应查看当前-窗口中相应的用户事件处理程序。
  每一个m_master菜单项都会触发相应的事件,但有些事件中并没有编写任何程序代码。程序员必须添加事件处理程序以完成特定的功能。

  具体步骤及代码分析:
  下面将为应用程序创建一个主菜单,由m_master继承而来,具体步骤如下:
  1、点击工具条上的“Inherit”(继承)按钮,弹出“Inherit From Object”对话框,如图所示。在“Object Type”处选“Menus”。
  2、在“Application Libraries:”下的库文件列表中选中pfewnsrv.pbl。然后,在显示的菜单对象列表中选中“m_master”,点击“OK”按钮,将出现如图所示的菜单对象设计面板。
  3、保存该菜单对象:我们一般将其保存到Design.pbl库中,命名为:m_design_master。

  下面将通过继承m_design_master创建一个frame菜单。注意:frame菜单仅用于frame窗口,而frame窗口的功能仅仅用于调用相应的功能模块的sheet窗口,所以,frame菜单中有很多功能是没用的,所以,需要将那些不用的菜单项隐藏起来。具体步骤如下:
  1、点击工具条上的“Inherit”(继承)按钮,弹出“Inherit From Object”对话框,如图所示。在“Object Type”处选“Menus”。
  2、在“Application Libraries:”下的库文件列表中选中Design.pbl。然后,在显示的菜单对象列表中选中“m_design_master”,点击“OK”按钮,将出现如图所示的菜单对象设计面板。
  3、将没用的菜单项隐藏起来。
  4、保存该菜单对象:我们一般将其保存到Design.pbl库中,命名为:m_design_frame。

  以上创建的m_design_master菜单将作为整个应用程序的菜单祖先,以后凡是用到菜单的地方都将从m_design_master中继承而来。


  三、将菜单链接到窗口上。
  目前,我们只是创建了一个窗口:w_design_frame。它将是应用程序运行后看到的第一个窗口,应用程序的所有功能模块的sheet窗口都将从它的菜单项里调用。我们将菜单m_desing_frame链接到该窗口上。
  步骤如下:
  1、打开w_design_frame窗口。
  2、在“Properties(属性)”窗口里设置“General”页面里的“MenuName”属性,点击选择图标,选择Design库中的m_design_frame作为窗口的菜单。
  3、保存修改。

  好了,现在请按下工具条上的“Run”(运行)按钮,你将可以看到如图的运行界面。注意:如果此时你还没有必要连接数据库,请将应用管理器的pfc_Open事件中的这一行代码注释掉:li_rc=of_LogonDlg()。



//------------------------------------------------------------
05功能模块
//------------------------------------------------------------

        第三部份 功能模块的设计
  一、建立一个数据窗口对象。
  1、点击工具条上的“New”(新建)按钮,从弹出的对话框中选择“DataWindow”页面,再选择“Grid”,按“OK”按钮,开始创建一个风格风格的数据窗口对象。
  2、在如图的“Choose Data Source for Grid DataWindow”窗口中,选择“Quick Select”,按“Next”按钮。
  3、在如图的“Quick Select”窗口,在“Tables”列表框中选择“employee”表,然后,点击“Add All”按钮,全部选中“Columns”列表中的所有字段。单击“OK”按钮。
  4、在如图的“Select Color and Border Settings”窗口中,单击“Next”按钮。
  5、在如图的“Ready to Create Grid DataWindow”窗口中,单击“Finish”按钮。
  6、我们将看到如图的数据窗口对象设计面板。将该数据窗口对象保存到Design.pbl库中,命名为:d_employee。

  二、建立第一个sheet窗口
  本节将通过继承PFC的w_sheet窗口创建一个多文档sheet窗口。
  具体步骤:
  1、点击工具条上的“Inherit”(继承)按钮,弹出“Inherit From Object”对话框,如图所示。在“Object Type”处选“Windows”。
  2、在“Application Libraries:”下的库文件列表中选中pfemain.pbl。然后,在显示的窗口对象列表中选中“w_sheet”,点击“OK”按钮,将出现如图所示的窗口对象设计面板。
  3、修改一些必要的属性:如,可以将窗口的“Title”的属性改为:“员工资料”。
  4、保存该窗口对象:我们一般将其保存到Design.pbl库中,命名为:w_employee。

  三、在窗口上增加一个数据窗口控件
  注意:应用PFC编程时,我们不应再用PowerBuilder的标准控件了,而应该用PFC中的用户对象。
  具体步骤:
  1、点击工具条上选择控件的图标旁边的倒三解按钮,从弹出的下拉选择框中选择“Create User Object control”,将弹出“Select Object”对话框,如图所示。
  2、在“Application Libraries:”下的库文件列表中选中pfemain.pbl。然后,在显示的用户对象列表中选中“u_dw”,点击“OK”按钮返回。
  3、在窗口设计面板上点一下,将在窗口上增加一个数据窗口控件。
  4、修改数据窗口控件的名称:在“Properties”(属性)窗口的“General”页面设置“Name”属性为:dw_employee。
  5、修改数据窗口控件连接的数据窗口对象:在“Properties”(属性)窗口的“General”页面设置“DataObject”属性:点击“DataObject”下的输入框旁的按钮,将弹出如图的数据窗口对象选择框。首先在“Application Libraries:”下的库文件列表中选中Design.pbl。然后,在显示的数据窗口对象列表中选中“d_employee”,点击“OK”按钮返回。
  6、修改一些常用的属性:在“Properties”(属性)窗口的“General”页面的“HScrollBar”属性前的复选框打勾,为数据窗口控件增加一个水平滚动条(默认只有垂直滚动条)。
  7、保存窗口对象的修改。

  四、创建w_employee窗口的菜单
  1、点击工具条上的“Inherit”(继承)按钮,弹出“Inherit From Object”对话框,如图所示。在“Object Type”处选“Menus”。
  2、在“Application Libraries:”下的库文件列表中选中Design.pbl。然后,在显示的菜单对象列表中选中“m_design_master”,点击“OK”按钮,将出现如图所示的菜单对象设计面板。
  3、保存该菜单对象:我们一般将其保存到Design.pbl库中,命名为:m_employee。

  五、将菜单链接到w_employee窗口上
  1、打开w_employee窗口设计面板。
  2、修改w_employee窗口的属性:在“Properties”(属性)窗口的“General”页面设置“MenuName”属性:点击“MenuName”下的输入框旁的按钮,将弹出如图的菜单对象选择框。首先在“Application Libraries:”下的库文件列表中选中Design.pbl。然后,在显示的菜单对象列表中选中“m_employee”,点击“OK”按钮返回。
  3、保存修改。

  六、代码的编写
  1、在数据窗口控件的Constructor事件中写入如下的代码:
    this.of_SetRowSelect(TRUE)    //激活数据窗口控件的行选择功能。
    this.of_SetRowManager(TRUE)    //激活数据窗口控件的行管理功能。
    this.of_SetSort(TRUE)    //激活数据窗口控件的排序功能。
    this.of_SetProperty(TRUE)    //激活数据窗口控件的属性选择功能。
    this.of_SetTransObject(SQLCA)    //设置数据窗口控件的事务对象。

    this.inv_rowselect.of_SetStyle(dw_employee.inv_rowselect.EXTENDED)    //对行选择服务进行初始设置。
    this.inv_sort.of_SetStyle(dw_employee.inv_sort.DRAGDROP)    //对排序服务进行初始设置。
    this.inv_sort.of_SetColumnHeader(TRUE)

    //以下代码用于完成数据的检索。
    If this.of_Retrieve() = -1 Then
        SQLCA.of_Rollback()
        Messagebox("错误","数据不能正确查询!")
    Else
        SQLCA.of_Commit()
        this.SetFocus()
    End If

  2、在数据窗口控件的pfc_retrieve事件中写入如下的代码:
    Return this.Retrieve()    //从数据库中检索出需要的数据。

  3、在窗口的pfc_preopen事件中写入如下的代码:
    this.of_SetResize(TRUE)    //激活窗口对象的调整大小的服务。
    this.inv_resize.of_Register(dw_employee,0,0,100,100)        //对dw_employee控件设置调整大小服务,并进行初始设置。

  4、保存修改。

  这样,一个具有基本功能的MIS的应用程序已经编写完成了。下面,让我们来看一看它可以完成什么工作吧:

//------------------------------------------------------------
06报表
//------------------------------------------------------------
        第四部份 报表的设计

  作为一个信息管理系统,报表输出是不可或缺的一部份。PFC对报表输出也提供了强大的支持。下面,让我们齐来看一看怎样用PFC设计一张报表。
  一、设计报表窗口
  为了方便起见,我们就将第三部份所做的w_employee窗口对象修改一下,改成一个报表窗口。
  1、打开w_employee窗口设计面板。
  2、修改数据窗口控件的Constructor事件的代码,将原来的代码全部删除,修改为:
    this.of_SetReport(TRUE)    //激活报表服务
    this.of_SetPrintPreview(TRUE)    //激活打印预览服务
    this.of_SetTransObject(SQLCA)    //设置事务对象
    this.of_SetUpdateable(FALSE)    //将数据窗口控件设置为不可更新

    //以下代码用于完成数据的检索。
    If this.of_Retrieve() = -1 Then
        SQLCA.of_Rollback()
        Messagebox("错误","数据不能正确查询!")
    Else
        SQLCA.of_Commit()
        this.SetFocus()
    End If
  3、保存修改。



  一个以PFC为开发基础,具有一定数据管理能力的信息管理系统就编写完成了。回头看一看:程序代码写了还不够一百行,但却可以实现大部份信息管理系统的功能,是不是为PFC的强大威力而叹服呢?不过,PFC的应用博大精深,以上介绍的只是PFC的入门知识。要想掌握PFC的精髓,还要你不断地深入学习,同时,将你学到的新元素加到上面那个程序里面,实际应用一下,看一看运行的效果,不断地探索、尝试。


雁过留声,人过留名

 2008-09-24 13:37

   

freele_china

Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:JiNan
等 级:版主
威 望:6
帖 子:352
专家分:0
注 册:2007-4-6

第 4 楼

  得分:0 

   

关于PFC

   关于PFC 

这一章介绍的是PFC的基础,PB的首要概念,面向对象的内容,并附有一个PFC的 
组成图。 

理解PFC: 
PFC是一组PowerBulider的对象,它可以由用户自己定制,扩充。你可以象搭积木 
一样使用它,使程序紧密的连接起来。PFC还包括许多有用的对象,例如:debug对 
象。 
PFC是由PowerBuilder提供的PB对象,并支持PowerScript 源代码。它使用的是先 
进的PowerBuilder面向对象技术,其一个特征是面向服务设计。确使你的程序占 
用最少的计算机资源。 
PFC使用了许多先进的编码技巧,你可以使用PowerBuilder的PowerScript编译器 
来检查对象,实例,事件,和继承PFC父类的函数。 
这本书说的是PFC的概念(PFC是什么东西和你为什么使用它)还有使用信息(如何计 
划.使用PFC) 
为了更详细的了解PFC的对象,实例,事件,和继承PFC父类的函数,请看PFC Object 
Reference 。 

理解PowerBuilder: 
使用PFC可以创建先进的面向对象式的PowerBuild类库。要想掌握PFC和它的面向 
对象特征,首先需要了解PowerBuilder和它的面向对象特征。这一节将告诉你应 
该熟悉PowerBuilder的基本概念。 
PFC原是为建类库准备的,但并不是不让你用它创建应用程序。通过看PowerBuild 
er User's Guide可以完全了解的PowerBuilder的概念。 

PowerBuilder类库和对象: 
PFC是作为PowerBuilder Libraries(PBLS)发行的。PBLs包括你用于写程序的父类 
和派生类对象。在使用任何PFC对象之前,你一定要在你的应用程序库的搜索路径 
中把PFC类库加进去。PowerBuilder在执行程序时通过搜索路径找到程序所引用的 
对象。 

PB标准对象 用途 
Windows PowerBuilder应用程序和它的用户之间的联系界面。 
Menus 用户在当前活动窗口用来搜索命令的表。 
DataWindow objects 用于接收,实时处理数据。 
User objects 由用户自己定义的对象(一次定义可以重复使用)。 
User objects 有两种类型: 
(一):Visual user objects (可视化用户对象) 
一个可视化用户对象是一个可以重复使用的可视化控制,或者是一批预先确定的可 
视化控制.PFC包括两种可视化用户对象类型. 
1.标准的可视化用户对象类: 
PFC提供了一套丰富的标准的可视化用户对象.每个PFC的标准的可视化用户对象都 
相当于一个PowerBuilder的窗口控件.这些对象包括以PFC服务预想确定完全的综 
合操作。 特别值得一提的是u_dw DataWindow 用户对象,这是以PFC服务来提供 
广泛的综合功能。 
2.用户自定义的可视化用户对象 
PFC也提供了用户自定义的可视化用户对象,这些对象包括一组窗口控件,并提供 
先进的函数用在某些特别情况。 (PFC没有使用外部用户对象和VBX用户对象,要 
想进 一步了解可视化用户对象,请看"PowerBuilder User's Guide") 
(二):Class user objects(非可视用户对象类) 
一个非可视用户对象是一个用来实现非可视的处理时使用的控件。PFC包括两种非 
可视用户对象类型。 
1.标准的非可视用户对象: 
标准的非可视用户对象是继承 PowerBuilder内嵌的系统对象而来。PFC提供了许 
多标准的非可视用户对象,例如:处理事务,错误对象,和其他所有的扩展系统对 
象。 
2.用户自定义的非可视用户对象: 
用户自定义的非可视用户对象是继承 PowerBuilder非可视对象类而来,它把数据 
和代码进行封装。这种类型的用户对象允许你从SCRATCH定义一个对象。 
PFC用Class user objects来执行它的许多服务以及提供这些服务对象的函数。它 
也提供?reference variables(引用变量),何谓 rdference variables呢?即是 
一个对象指针。你可以用它来存取一个对象的实例变量,函数,事件。 

Functions(函数): 
PowerBuilder支持全局函数和对象函数。PFC通过user_object function执行它的 
处理。一个函数就是执行一些处理的PowerScript语句的集合,你可以传递数据或 
者是什么也不传,它来返回一个值。 
详细信息册参考PFC Object Reference。 

Events and user events(事件和用户事件): 
PowerBuilder的Windows,user objects,contols,都有一些预先设定的事件。PFC 
通过定义用户事件为许多PFC 对象增加事件。事件可以接受数据和返回值。共有 
三种PFC 事件: 

事件类型 触发时间 
PowerBuilder预先设定的事件 某个动作导致操作系统调用事件 
预先编好代码的用户事件 某个动作(例如选择一个菜单)导致PFC触发用户事件 

空的用户事件(可以加入代码) 某个动作(例如选择一个菜单)导致PFC触发用 
户事件 
除非另有说明,本书的event都指的是这三种。 

Function and events compared (函数和事件比较) 

函数和事件在许多方面都是相似的: 
(1)他们都可以接收数据,返回值; 
(2)他们都由PowerBuilder语句构成; 
(3)他们都可以被调用,触发,传递。 
但他们还是有些不同的: 
使用特征 函数 事件 
调用一个不存在的 将会出现运行时错误 TriggerEvent返回-1 
覆盖父类脚本 直接覆盖父类脚本 可以扩展或者覆盖 
访问 可以是Public、Private、Protected 永远是Public 
重载 可以重载 不可以重载 

面向对象式的设计 
面向对象的编程工具支持三个基本规则:inheritance(继承),encapsulation 
(封装),polymorphism(多态)。 

如何使用PFC扩展层: 
在PFC中没有类库完全适合你的需要,你可以代表性的修改PFC来满足你的程序的 
需要。假如没有PFC扩展层,就会出现一个问题:当PFC版本升级时,新版本的PF 
C恢复该这些修改,而你不得不用手工改变。 

一个特别的扩展层: 
PFC产生一个扩展层是通过继承所有的层实现的。所有的扩展对象都在单独的PBL 
S,这在PFC升级时不会影响。 

内容 祖先层 
Application and global services PFCAPPSRV.PBL 
DataWindow services PFCDWSRVPBL 
Visual and standard class user objects PFCMAIN.PBL 
Utility services PFCUTIL.PBL 
Window services PFCWNSRV.PBL 

祖先层的类库中的对象包括所有的实例变量,事件,函数;扩展层的类库中的对 
象是相应祖先层类库中的对象的不可修改的子类。即使是继承,也可以访问祖先 
的实际变量,事件和函数。 
通过PowerBuilder Bowser来察看子类的对象的实际变量,事件和函数。 

使用扩展层有二个优点: 
1. 你可以增加一些点,部门,还有程序逻辑。 
2. 不会影响版本升级。 

旧版本对象: 
PFCOLD。PBL Library包含旧的对象。如果你有一个存在的PFC程序,你有可能需 
要把他加在你的library list. 

注意: 
你要通过修改扩展层的对象来定制PFC程序。千万不要轻易修改祖先对象。你的程 
序中的对象要使用扩展层的对象并且继承扩展层的窗口。 

迅速开始: 
在用PFC编程时,程序经常需要修改,存取,以及从扩展层中继承对象。PFC装置 
中有一套扩展库(PFC Quickstart Libraries)。它包括扩展层的基本功能,使 
你的程序快速发展。 

PFC命名规则: 
PFC遵循以下命名规则: 
Level Name 
PFC层对象 用前缀pfc_ 
扩展层对象 和它的祖先有同样的名字但没有前缀pfc_ 

例如:DataWindow selection service object的祖先是pfc_n_cst_dwsrv,扩展层 
的子类是 
n_cst_dwsrv.Pfc_n_cst_dwsrv 包括所有服务的代码。n_cst_dwsrv 是不可修改 
的子类(你可以在假如程序指定的实例变量和代码。)。 

PFC定义的用户事件: 
PFC定义用户实践也用前缀pfc_prefix.这使得你的应用程序的用户事件和PFC 的 
用户事件更加容易。 

PFC文档使用扩展层名字 
当指定一个服务对象时,PFC文档总是用扩张层命名。例如:当论述基类窗口时这 
书指向w_master不是pfc_w_master.但要记住,w_master的实际变量,事件和可用 
函数实际上是在pfc_w_master定义的。 
PFC命名习惯详细资料请看PFC Object Reference 

我们不难想到: 
PFC的对象继承允许你在每一层假如扩展逻辑。例如:pfc_w_sheet是从w_master 
继承的,w_master的实际变量,函数,你加在它的事件在它的子类窗口中都已存 
在。 

如何加扩展层 
扩展层通过PFC升级类有效的实现应用程序内部的重用和单个程序的重用。但是, 
在大部门或者是多部门合作时,一定要考虑好扩展的标准,方法,注意部门的规 
则和商业规律。 
如果你是在一个组织里使用PFC,你要考虑创建一个新层(包括这个组织的所有的 
变量函数,事件)。应用程序还是使用PFC扩展库的对象,可是调用实例变量,事 
件,函数的祖先变了。 

PFC构成: 
PFC是由以下构成的: 
l 一套PBLS 
l 一个数据库 
l Quickstart PBLS 
l 实例代码 
l 一个简单的应用程序 
Localized PFC(局部化的PFC) 
局部化的PFC 将会在PFC新版本公布后升级。 

The PFC PBLs 
PFC是分布在PBLS包含的祖先对象和PBLS扩展层包含的对象。每个祖先对象扩张层 
包含提供以下服务的对象 
Libraries Contents 
PFCAPSRV.PBLPFEAPSRV.PBL 应用程序管理器,应用程序服务对象和全局服务对象 
。 
PFCMAIN.PBLPFEMAIN.PBL 标准可视化用户对象,自定义可视化用户对象,标准用 
户对象类。 
PFCUTIL.PBLPFEUTIL.PBL 有用的对象和服务。 
PFCWNSRV.PBLPFEWNSRV.PBL 窗口服务,包括用户对象和有用的窗口。 
PFCOLC.PBL 旧的用户对象。(基层和扩展层的对象) 

使用library画笔: 
使用library画笔来看到PFC中所有对象 

PFC 数据库 
PFC装载了pfc.db本地数据库。这个数据库包括以下几个表: 
Table Usage 
Messages 错误信息服务。 
Security_apps 安全服务。 
Security_groupings 安全服务。 
Security_info 安全服务。 
Security_template 安全服务。 
Security_users 安全服务。 
PFC本地数据库是由开发者预先设定的,如果你要使用错误信息服务和安全服务一 
定要在你的数据库中复制指定的表。连接”Deploying database tables” 

The PFC Quickstart PBLs 
使用PFC Quickstart libraries用来是程序配置和运行迅速。他们包括经过挑选 
的PFC扩展层对象的保护子集。 
做一个PFC Quickstart libraries备份,你就有了后援了。 

The PFC code example 
使用它是为了了解PFC的对象和服务。学习如何编码并且实现PFC的基本功能。Th 
e PFC Quickstart有广泛的参照和使用资料。 

The PFC sample application 
使用PEAT可以看到PFC的例子是如何进行工程预算和跟踪系统的。


PFC编程基础


概要: 
这一章阐述了 PFC 编程的基本技巧,同时也告诉了你如何开始运用 PFC 编写应 
用程序。 


设置应用程序管理器 
首先建立一个PFC应用程序的第一步就是配置应用程序以及建立应用程序管理器- 
-n_cst_appmanager。应用程序管理器将替代原来的应用程序对象。原来在应用程 
序对象中编写的脚本将全部改写在应用程序管理器中。应用程序管理器中同时还 
通过实例变量、函数来维护应用程序的属性。其中有框架窗口、应用程序与用户 
的INI文件或注册键以及帮助文件等。 

注意: 
使用分开的物理文件 
每个独立的应用程序都必须拥有自己独立的一套文件。你不可以共享父类文件, 
也就是那些以PFC开头的文件。这是由PFC的内部继承关系而决定的。 
例如,假设应用程序1与应用程序2都拥有它们自己的一套扩展的PFC库文件,但 
是它们共享父类文件(PFC库文件)。这时应用程序1在自己的PFE(PFC扩展库) 
的w_master中增加了一个函数名为of_SetData。这样这个函数将在w_master的所 
有子类中都有效,这些子类是pfc_w_main,pfc_w_frame,pfc_w_sheet 等。而这 
些对象恰恰在这两个应用程序共享的父类文件(PFC库文件)中。这样当应用程序 
2重新生成应用程序时(regenerate)由于应用程序2的PFE文件中没有of_SetDat 
a函数。这样w_master的所有子类中的关于of_SetData函数的指针都将被删除。这 
样当应用程序1运行时将会导致运行时错误与编译错误。 


具体步骤 

1. 打开应用程序画笔。 

2. 定义库文件列表。 
PFCAPSRV.PBL 
PFCDWSRV.PBL 
PFCMAIN.PBL 
PFCUTIL.PBL 
PFCWNSRV.PBL 
PFEAPSRV.PBL 
PFEDWSRV.PBL 
PFEMAIN.PBL 
PFEUTIL.PBL 
PFEWNSRC.PBL 
PFCOLD.PBL(如果你的应用程序是使用老版本的PFC库那么请增加该文件到库列表 
中) 

3. 在应用程序画笔中打开脚本画笔,定义n_cst_appmanager类型的全局变量gnv 
_app。 
n_cst_appmanger gnv_app 
这个变量名必须是gnv_app,因为PFC的对象、函数、事件都需要这个n_cst_appm 
anager或它的子类的全局变量-gnv_app。 

4. 增加如下代码到应用程序对象的OPEN事件中。它的用途是创建n_cst_appmana 
ger、调用pfc_Open事件。 
gnv_app = Create n_cst_appmanager 
gnv_app.Event pfc_Open(commandline) 

5. 增加如下代码到应用程序对象的CLOSE事件中。 
gnv_app.Event pfc_Close() 
Destroy gnv_app 

6. 增加如下代码到应用程序对象的SystemError事件中。调用pfc_SystemError事 
件。 
gnv_app.Event pfc_SystemError() 

7. 关闭应用程序画笔,保存所作的修改。 

8. 打开用户自定义对象画笔。在PFEAPSRV.PBL中找到n_cst_appmanager并打开, 
或者是它的子类。 

9. 在n_cst_appmanager的构造事件(Constructor Event)中调用它的函数来初 
始化关于软件版本号、公司、和INI文件的实例变量。 

10. 在 n_cst_appmanager的pfc_Open事件中打开你所想要的应用程序Service 。 

你所想打开的Service 调用函数 
Application preference of_SetAppPreference 
DataWindow caching of_SetDWCache 
Error of_SetError 
Most recently used object of_SetMRU 
Transaction registration of_SetSecurity 
Debug of_SetDebug 

11. 在pfc_Open事件中增加打开你的初始窗口的代码,例如框架窗口(Frame Wi 
ndow)或者调用显示快闪窗口的of_Splash()函数。 

12. (可选)增加代码到pfc_PreAbout,pfc_PreLogonDlg,pfc_PreSplash事件 
中,用于定制关于对话框(About box)、登录对话框(Logon box)、快闪窗口 
(splash screen)。 

13. (可选)增加代码到pfc_idle,pfc_ConnectionBegin,pfc_ConnectionEnd 
事件中。 
l_ 在应用程序对象的idle事件中调用pfc_idle事件。 
l_ 在应用程序对象的ConnectionBegin事件中调用pfc_ConnectionBegin事件。 

l_ 在应用程序对象的 ConnectionEnd事件中调用pfc_ConnectionEnd事件。 

14. 保存n_cst_appmanager 

如何显示快闪窗口 
非常简单,只需在pfc_Open事件中,在打开第一个窗口的代码之前写上如下代码 
: 
this.of_Splash(1) 
Open(w_tut_frame)(根据不同的应用程序有不同的变化!) 

如何显示登录窗口 
1. 在框架窗口的Open事件中调用of_LogonDlg函数: 
Integer li_return 
li_return = gnv_app.of_LogonDlg( ) 
IF li_return = 1 THEN 
this.SetMicroHelp("Logon successful") 
ELSE 
MessageBox("Logon", "Logon failed") 
Close(this) 
End If 
Of_LogonDlg函数将显示w_logon对话框,同时还会提示输入用户名、密码,当用 
户点击OK按钮时还会触发n_cst_appmanager的pfc_Logon事件。 
同样,你也可以在n_cst_appmanager的pfc_Open事件中的打开框架窗口之后立即 
调用Of_LogonDlg函数。但是绝对不要在Of_Splash之后立即调用Of_LogonDlg 。 


2. 在n_cst_appmanager的pfc_logon事件中编写登录到数据库的代码。这个例子 
假设有一个INI文件,它包含了所有的需要登录到数据库的信息,除了用户名、密 
码以外。同时还假设你已将SQLCA的默认类型改为n_tr(PFC制定的书屋对象类型 
)。 
Integer li_returnString ls_inifile, ls_userid, ls_password 
ls_inifile = gnv_app.of_GetAppIniFile() 
IF SQLCA.of_Init(ls_inifile,"Database") = -1 THEN 
Return -1 
END IF 
// as_userid and as_password are arguments 
// to the pfc_Logon event 
SQLCA.of_SetUser(as_userid, as_password) 
IF SQLCA.of_Connect() = -1 THEN 
Return -1 
ELSE 
gnv_app.of_SetUserID(as_userid) 
Return 1 
End If 

建立应用程序 
建立一个MDI应用程序 
使用w_frame,w_sheet窗口作为你的框架窗口与表单窗口的父类。在w_sheet窗口 
中增加你的应用程序中所有表单窗口需要的事件、实例变量、函数。 
你必须为每一个表单窗口定义菜单。 
具体步骤: 
1. 为应用程序在w_frame窗口中作特定的修改。最好是建立一个w_frame窗口的子 
类,然后再修改这子类。 
2. (可选)在w_sheet中增加实例变量、函数、用户自定义事件。 
3. 建立继承w_sheet的表单窗口。 
4. 建立一个框架窗口(frame window)用的菜单,通常是选用w_frame 。 
5. 为框架窗口指定相应的框架窗口菜单。 
6. 建立表单窗口的菜单 
7. 为表单窗口(sheet window)指定相应的表单菜单。 
8. 在n_cst_appmanager的pfc_Open事件中加入打开框架窗口的代码。 
9. (可选)在必要时候,开启框架窗口Service 。 
l_ 调用w_frame的of_SetStatusBar函数开启状态条Service 。 
l_ 调用w_frame的of_SetSheetManager函数开启表单管理Service 。 

在MDI应用程序中打开表单窗口: 
1. 在菜单项的Clicked事件中编写有关打开表单窗口的脚本。你需要将表单窗口 
的名称以字符串的形式传递给Message.StringParm,然后以pfc_Open为参数调用 
of_SendMessage函数: 
n_cst_menu lnv_menu 
Message.StringParm = "w_products" 
lnv_menu.of_SendMessage(this,”pfc_Open”) 

2. 在w_frame的pfc_Open事件中访问Message.StringParm,打开指定的表单窗口 
。 
String ls_sheet 
w_sheet lw_sheet 

ls_sheet = Message.StringParm 
OpenSheet(lw_sheet, ls_sheet, this, 0, Layered!) 

建立一个SDI应用程序 
在使用PFC建立SDI应用程序中,你将使用w_main窗口作为你的所有main类型窗口 
的父类。为了使得你的事件、函数、实例变量能够在所有的窗口中都有效,只需 
将它们加到w_main中。 
如果你的窗口需要菜单,那么你必须为每一个窗口定义菜单。 
具体步骤 
1. 继承w_main窗口,建立一个main类型窗口,最为主窗口。最好是直接修改w_m 
ain窗口。 
2. 建立一个主菜单。 
3. 根据需要建立其他的菜单与窗口。 
4. 在n_cst_appmanager的pfc_Open事件中编写打开主窗口的脚本。 

PFC编程过程中的函数使用方法 
几乎所有的PFC函数都是对象级函数。这就意味着你必须定义POWERBUILDER对象后 
才可以使用函数。经过PB封装后的函数使你很轻易的看到哪个函数属于哪个对象 
。 

PFC使用Set/Get/Is 命名规则来控制实例变量。 
l_ of_Set函数允许你为实例变量赋值 
l_ of_Get函数允许你获得一个非布尔类型的变量的值 
l_ of_Is函数允许你确定一个布尔类型变量的真与假 
其他类型实例变量的访问规则 
PFC定义变量时同时指定为公共类型(public),那么你将可以随意直接访问。 

另外,有些变量由于只是在内部使用,因此不能通过函数进行访问。 
除了Set/Get/Is命名规则以外,PFC在为某一Service定义入口参数时使用Regist 
er/UnRegister规则。例如,你可以调用u_calculator对象的of_Register函数来 
定义Datawindow的那个列使用下拉日历。 

Object qualificationPFC uses access levels (public, private, protected 
) to control your access to functions designed for 内部自动调用 use. 

When you call these functions from outside the object, use dot notatio 
n to qualify the function name. Qualify the function name with the ref 
erence variable used to create the object (in some cases you qualify t 
he function name with the actual object name). 

调用PFC对象函数 
1. 确认对象是已否被创建 
PowerBuilder在当窗口打开的时候会建立窗口、菜单和可视的用户对象。你 
要使用函数of_Setservicename来建立大部分的不可视的用户对象。例如,下面u 
_dw的对象函数创建了排序Service(n_cst_dwsrv_sort user object),并且在 
u_dw’s中的实例变量inv_sort中保留它的引用。通常这些代码都在Datawindow的 
构造事件中: 
this.of_SetSort(True) 
自动实例化对象 
某些PFC对象利用了Powerbuilder提供的自动实例化功能。这些对象没有Set函数 
。PowerBuilder会在它们声明的时候自动实例化它们。 

2. 在应用程序中调用适当的对象函数 
这个例子展示了排序Service将利用DataWindow的列名、排序已显示值、 
实现当用户点击后排序。同时可以在菜单栏上显示下拉对话框。 

this.inv_sort.of_SetColumnNameSource(this.inv_sort.HEADER) this.inv_s 
ort.of_SetUseDisplay(TRUE) this.inv_sort.of_SetColumnHeader(TRUE) 
this.inv_sort.of_SetStyle(this.inv_sort.DRAGDROP) 

函数重载PFC使用函数重载提供了一个丰富的、富有弹性的编程接口。它通过两种 
方法实现函数重载。 
l_ 多种语法 多个函数具有不同的参数类型、不同的参数顺序。这使得PFC的函数 
可以处理多种数据类型的参数。 
l_ 随意的参数数目 许多函数拥有一个具有相同数据类型、相同顺序、参数数目 
可以变化的参数。它同时还允许PFC为常用的参数提供默认值。 

只用于内部处理所重载的函数 
除了公有类型的重载函数以外,PFC通常还有一个保护类型的版本,一般都是用 
来进行内部调用的。例如,n_cst_dwsrv_report中的of_Addline函数有4个公有类 
型的版本、一个保护类型的版本。这个保护类型的版本是供其他4个调用的。虽然 
有些时候可以调用这些保护类型的版本,但是他们纯粹是为了内部调用而设计的 
。 

关于PFC事件的编程 
PFC包括了预代码的事件、用于实现PFC Service的用户自定义事件。还有一些空 
的事件,你可以在其中为你的应用程序加入特定的代码,或者执行一些特定的任 
务。所有的事件都是公有的,你可以直接访问它们。 

“预代码事件”与其他的用户自定义事件 
预代码事件指的是那些已经在PFC层对象中编号代码的事件。PFC拥有许多具有一 
定功能的“预代码事件”。这意味着如果你开启了一个Service ,PFC的对象发现 
该Service已开启了,那么这些“预代码事件”将会执行其中的代码。 
例如:u_dw的Clicked事件就是一个“预代码事件”,它会自动调用那些开启的S 
ervice函数。你可以扩展这些事件,但是不可以覆盖它们。 

空的用户自定义事件 
PFC定义了许多空的用户自定义事件。你可以在其中为你的应用程序写入特定的 
代码。许多这种事件都是通过菜单而触发的。另外一些则是应用程序代码触发的 
。 
例如: 
在u_dw中有一个用户自定义事件pfc_Retrieve ,你可以在其中加入检索数据的 
代码。 
Return this.Retrieve() 
有关更多的关于PFC事件的内容请参考PFC Object Reference 

PFC中的事件是如何起作用的 
PFC是采用如下的方式调用Services中的事件的 
1. 当用户触发某个对象的某个事件时,PFC将会调用相应的Service 的自定义事 
件,同时传递相应的参数。例如:u_dw的clicked事件会调用n_cst_dwsrv_sort的 
pfc_Clicked事件,同时传递X坐标、Y坐标、DW对象(这些其实也是DW的Clicked 
事件的参数)。 
2. 这些Services的事件同时还有可能调用其他对象函数。例如,n_cst_dwsrv_s 
ort的pfc_Clicked事件中还调用了n_cst_dwsrv_sort的函数。 
尽管你可以直接调用PFC的对象函数,但是调用相应的事件显得更简单,因为这些 
事件中已经包括了错误检测代码。 

关于事件触发前的一些处理 
PFC有一种自定义事件名是Prename 。这意味着这些事件是发生在事件name之前的 
事件。我们把它叫做pre_event 。你可以随意在pre_event中增加代码用于扩充相 
应的事件处理能力。这些pre_event有: 

pfc_PreAbout 
pfc_PreClose 
pfc_PreLogonDlg 
pfc_PreOpen 
pfc_PrePageSetupDlg 
pfc_PrePrintDlg 
pfc_PreRestoreRow 
pfc_PreSplash 
pfc_PreToolbar 
pfc_PreUpdate 

通常,这些事件中都有一个已经自动实例化了的用户对象的引用变量。这个对象 
的属性可以影响这个事件的运行。你可以修改这个用户对象的属性,从而达到改 
变事件的运行或扩展事件的运行效果。有些时候你还需要修改一些其他的对象。 
例如,当你需要控制About对话框中的一个附加控件的显示效果时,你需要: 
1. 扩展用户对象n_cst_aboutattrib ,在其中增加一个用于在w_about中代表显 
示效果的实例变量(一个 user ID)。 
2. 在w_about中增加控件(sle_userid) 
3. 在w_about的Open事件中编写代码,将user ID的值放入单行编辑框中(sle_u 
serid) 
sle_userid.text = inv_aboutattrib.is_userid 
4. 在n_cst_appmanager的pfc_PreAbout事件中编写初始化代码: 
inv_aboutattrib.is_userid = this.of_GetUserID() 
然后当你需要显示w_about时,调用应用程序管理器的of_About函数即可。 

如何使用属性对象 
PFC提供了许多专门的属性用户对象。这些用户对象有如下特征: 
l_ 包含公有性质的实例变量 
l_ 自动实例化 
l_ 名称以attrib结尾 
l_ 通常用于向PFC的pre_event传递信息,例如pfc_PreAbout 
l_ 可扩展,你可以在其中自己定义其他的实例变量。 
因为,你有可能会扩展这些对象。因此,PFC使用对象而不使用对象。 
同样你还可以定义对象函数,做到更随意的控制这些对象。 
这些属性对象有: 
属性对象 有关的 用法 
n_cst_aboutattrib Pfc_Pre_About(n_cst_appmanager) 调用n_cst_appmanag 
er的of_About函数打开about对话框 
n_cst_calculatorattrib Constructor(u_calculator) 内部自动调用 
n_cst_dirattrib File service object 内部自动调用 
N_cst_dwobjectattrib Of_Describe(n_cst_dssrv与n_cst_dwsrv) 函数Of_De 
scribe返回DataWindow中的对象属性。 
n_cst_dwproperyattrib DataWindow Properties objects 内部自动调用 
n_cst_errorattrib Error message service 用于传递显示内容到w_message窗口 

n_cst_filterattrib DataWindow filter service 用于传递信息到filter对话框 

n_cst_findattrib DataWindow find service 传递信息到Find对话框 
n_cst_itemattrib PFC ListBox, PictureListBox, and TreeView 内部自动调用 

n_cst_linkageattr b DataWindow linkage service 内部自动调用 
n_cst_logonattrib Pfc_PreLogonDlg (n_cst_appman ger) 调用n_cst_appmana 
ger的of_LogonDlg函数打开w_logon窗口 
n_cst_mruattrib MRU service 用于窗体的pfc_MRUProcess和pfc_PreMRUSave事 
件 
n_cst_restoreroattrib DataWindow row manager service 内部自动调用 
n_cst_returnattrib DataWindow filter and sort services 内部自动调用 
n_cst_selectionattrib Selection service Populated with arguments to th 
e n_cst_selection of_Open function 
n_cst_sortattrib DataWindow sort service 用于传递信息到Sort对话框 
n_cst_splashattrib Pfc_PreSplash event (n_cst_appman ger) 调用n_cst_ap 
pmanager的of_Splash函数打开w_splash 。 
n_cst_sqlattrib SQL service 该属性对象中含有SQL语句的部分内容。 
n_cst_textstyleattrib PFC RichTextEdit control 用于设置和获取text属性( 
黑体、斜体等)。 
n_cst_toolbarattrib Pfc_PreToolbars event (w_frame) 调用w_frame的pfc_T 
oolbars事件打开w_toolbars 。 
n_cst_zoomattrib DataWindow print preview service 内部自动调用 

PFC的常量 
许多PFC对象都包含了常量。使用常量使得程序更加易读。例如:下面两段代码同 
样是设置Datawindow的linkage风格,但是第二段则显得更加容易理解: 
// 1 = Filter linkage style. 
dw_emp.inv_linkage.of_SetStyle(1) 

// FILTER 作为一个常量 
dw_emp.inv_linkage.of_SetStyle (dw_emp.inv_linkage.FILTER) 
约定:PFC的所有常量都采用大写。 

消息路由 
消息路由器可以用于任何一个对象与窗体之间的通讯。不过,大部分时候都是用 
于菜单与窗体之间的消息传递。它提供了一种查找算法用于确定哪个对象来接收 
消息。 
使用消息路由时: 
l_ 你菜单中的代码只需要知道代用哪个事件,你无须知道当前的窗口时哪个,或 
者与其相关的对象名称。 
l_ 你的窗口无须维护用户事件,只需简单调用DataWindow的事件即可。从而减少 
了窗口需要维护的事件数量。 
Message = user event 
经过消息路由传递的消息实际上就是用户事件名。窗口、控件收到这些消息后就 
会调用相应的事件。 

内置的debug消息 
消息路由机制还提供了内置的debug 

函数of_SendMessage的工作流程 
当用户选择菜单项时,Clicked事件中的代码便以欲触发的用户事件名为参数(字 
符串的形式)调用of_SendMessage函数。Of_SendMessage调用n_cst_menu的of_S 
endMessage函数,n_cst_menu的of_SendMessage将会调用窗体的pfc_MessageRou 
ter事件,pfc_MessageRouter事件将会调用你所要触发的用户事件(即在Clicke 
d中传递字符串参数)。 
在MDI与SDI应用程序中,函数Of_SendMessage调用pfc_MessageRouter时将有所不 
同。如图: 

pfc_MessageRouter的工作流程 
如图: 
菜单与窗口之间的消息传递 
消息路由是菜单与窗口之间的通讯桥梁。你不可以通过按钮来触发pfc_MessageR 
outer事件。因为,消息路由会调用GetFocus函数判断当前控件。这样当你按下按 
钮时,按钮便成了当前控件。 


PFC中的事务对象 
PowerBuilder的强大功能之一就是可以快速便利的访问多种数据库。PowerBuild 
er使用事务对象(Transaction Object)作为PowerBuilder与Database之间的桥 
梁。SQLCA就是一个默认的事务对象。 

用户自定义对象n_tr 
PFC中有一个n_tr对象。它是标准事务对象的子类。其中设有实例变量、用户自定 
义事件、函数,主要用于扩充与数据库的通讯能力。 
N_tr提供了一套标准函数用于连接、切断、提交、回滚等数据库操作。使用这些 
函数代替原有的数据库语句。例如使用of_Connect代替CONNECT语句。 

两处地方使用n_tr 
l_ 替代sqlca:在应用程序的属性对话框中将SQLCA的默认数据类型设为n_tr 。 

l_ 附加的事务对象:当你需要访问多个数据库时,你可以再定义一个事务对象。 

如果你使用了多个事务对象,你可以使用事务对象的registration service ,做 
到一次提交全部已打开的事务对象,一次回滚所有已打开的事务对象。 

将SQLCA设置为n_tr类型 
1. 打开应用程序画笔 
2. 显示属性窗口,选中Variable页 
3. 在SQLCA框中输入n_tr 
4. 点击OK 

使用n_tr 
1. 如果你不使用SQLCA ,而是使用其他的事务对象。 
下面的例子假设itr_security是n_tr的实例变量 
itr_security = CREATE n_tr 
2. 初始化实例变量ib_autorollback 。这个变量的作用是当事务对象正处于连接 
状态时应用程序被关闭了或者是该事务对象被删除了的时候,该事务对象应该如 
何操作 
itr_security.of_SetAutoRollback(FALSE) 
关于初始化ib_autorollback的扩展 
你可以在n_tr的构造事件中初始化ib_autorollback 。 
3. 使用n_tr的of_Init函数初始化事务对象的属性 
Integer li_return 
String ls_inifile 
ls_inifile = gnv_app.of_GetAppIniFile() 
IF SQLCA.of_Init(ls_inifile,"Database") = -1 THEN 
MessageBox("Database","Error initializing from " + ls_inifile) 
HALT CLOSE 
End if 
4. 调用of_Connect进行数据库连接 
IF SQLCA.of_Connect() = -1 THEN 
MessageBox("Database","Unable to connect using " + ls_inifile) 
HALT CLOSE 
ELSE 
gnv_app.of_GetFrame().SetMicroHelp("Connection complete") 
End if 
5. 调用n_tr的成员函数 

调用父类的函数、事件 
在扩充父类的函数和事件时,你有可能需要先调用父类的函数或事件,然后再依 
据返回值进行下面的处理。这对那些具有返回值前缀是PFC的事件特别有意义。你 
在执行子类的代码前必须先确认父类的代码是否执行成功。 
覆盖父类的函数 
为了扩展父类的代码,获取父类的返回值。你必须覆盖父类的代码,然后显示的 
调用父类的函数或事件。 
采用如下的语法格式调用父类的事件,同时传递参数、获取返回值: 
Result = Super :: Event eventname(arguments叄? 
采用如下的语法格式调用父类的函数,同时传递参数、获取返回值: 
result = Super :: Function functionname(arguments叄? 
下面的例子则覆盖了u_dw的pfc_Update事件。当父类的事件处理成功时,子类将 
信息纪录到日志中。 
Integer li_return 
// Call ancestor event, passing 
// descendant's arguments. 
li_return = Super::Event pfc_Update(ab_accepttext, ab_resetflag) 
IF li_return = 1 THEN 
// ue_WriteLog is a user-defined event. 
li_return = this.Event ue_WriteLog 
END IF 
Return li_return 

在应用程序中增加联机帮助 
联机帮助是应用程序中非常重要的一部分。PFC提供了许多函数、事件使得你可以 
方便的将联机帮助添加到你的应用程序中。 
相关信息:有关PFC的帮助对话框请参考“Deploying PFC dialog box HELP” 。 

1. 使用n_cst_appmanager的of_SetHelpFile函数设置帮助文件。通常在构造事件 
中: 
this.of_SetHelpFile(“c:\eis\eisapp.hlp”) 
2. pfc_PreOpen是为窗口设置帮助主题的最好的地方 
Long ll_helpid 
Ll_helpid = 1020 //1020是一个帮助主题的ID 
Ia_helptypeid = ll_helpid 
采用这种方式你可以为用户选中的窗口提供详细的帮助。你可以将ia_helptypei 
d设置成长整形(此时PFC把它解释成帮助主题的ID),或者是字符串(此时PFC将 
它解释成关键字)。 
3. (可选)如果你没有使用PFC的m_master的子类。那么,在你的HELP菜单项中 
调用窗体的pfc_Help事件。因为,pfc_Help定义在窗口w_master中,所以所有的 
PFC窗口都具有事件。 
4. 对于对话框,则在其中的HELP按钮的Clicked事件中编写: 
Parent.Event pfc_Help() 
PFC自动处理窗口级别的帮助 
当你从m_master的子类的菜单中选择Help->Help时,消息路由机制会自动的调用 
当前活动的窗口的pfc_help事件。 

PFC的升级 
PFC在发布PowerBuilder的升级版本时同时也包括了PFC的升级文件。如何升级PF 
C,请按如下规则: 
l_ PFC的各层(PFC层、PFE层、中间层等)没有任何被修改时:你可以直接安装 
新的PBLs覆盖原有的PBLs 。 
注意:每次升级PFC时都保留一份原有的文件备份 
l_ 如果你修改了PFC中的某一层:你必须保证你所作的修改不会被覆盖!请按如 
下的步骤进行: 

将PFC升级到最新版本 
1. 将所有扩展层的PBL文件移到一个不会被安装过程覆盖的目录中。 
说明:你不应该对PFC的最基类(以PFC为前缀的对象)作任何修改,这里假设你 
没有对PFC的最基类作任何修改 
2. 确定你当前的PFC的版本号。你可以在Readme.txt文件中查看,或者在pfc_n_ 
cst_debug的实例变量中查看。版本号的格式:主版本号.次版本号.修正号 
3. 执行安装程序,将PFC安装口的PBL文件放到PFC所在的目录中,覆盖原有的PF 
C最基类的PBLS ,即以PFC开头的库文件。 
4. 合并已存在的扩展对象与新安装的扩展对象。首先详细阅读Readme.txt中说明 
的新扩展对象清单。然后按照一下的两种方法合并对象: 
l_ 将新的对象COPY到你的扩展PBLS中。 
l_ 将已经存在的对象COPY到新的扩展PBLS中。 
5. 启动PowerBuilder 
6. (可选)必要的时候调整一下应用程序的库列表 
7. 打开库画笔,从新编译一边所有的对象。 


PFC的服务 

 

概要: 

这一章主要介绍了什么是PFC的Services ,以及如何使用它们。 

1 应用程序服务 

PFC提供了以下各种应用程序Services : 

DataWindow caching 

Debugging 

Error 

Application preference 

Most recently uesed object 

Security 

Transaction registration 

你必须通过n_cst_appmanager(应用程序管理器)来控制这些Services (这些S 

ervices实际上是应用程序管理器的是数据成员)。应用程序管理器(applicati 

on manager)通过调用成员函数来开启与关闭Services 。由于它们在应用程序管 

理器的范围内有效。而应用管理器是全局变量,因此你可以在你的应用程序的任 

何地方是使用应用程序Services 。 

1. DataWindow caching service 

概要: 

Datawindow caching service为Datawindow提供了数据缓冲。它将数据保存在内 

存中,从而减少了程序访问数据库的频率,加快了程序的执行速度。Datawindow 

caching service支持如下的数据源: 

l_ Datawindow对象,它的数据可以来自于数据库表也可以来自存储过程。 

l_ SQL语句 

l_ Datawindow控件 

l_ DataStore对象 

l_ 数组中的数据 

l_ 文件 

PFC使用Powerbuilder的Datastore来实现Datawindow caching service 。它对应 

的对象是n_cst_dwcache 。 

PFC的代码实际只在父类对象中 

这本书讲述的都是扩展类的对象,就像n_cst_dwcache 。而实际上PFC的代码全在 

父类的对象中(pfc_n_cst_dwcache)。 

使用方法 

使用DataWindow caching 可以将数据库访问频率降到最低,可以加快程序运行速 

度。 

2 开启DataWindow caching 

l_ 调用n_cst_appmanager的of_SetDWCache函数 

gnv_app.of_SetDWCache(TRUE) 

2 使用Datawindow caching : 

1. 调用of_Register函数进行数据缓存,同时依据不同的数据提供相应的参数。 

l_ 缓存Datawindow对象从数据库中检索出的数据时:你需要传递标识符(ident 

ifier)、事务对象、Datawindow对象名、其他参数(如果存在的话)。 

l_ 缓存SQL语句从数据库中检索出的数据时:你需要传递标识符(indentifier) 

、事务对象、SQL语句。 

l_ 将数据缓存到数组中:传递标识符(identifier)、Datawindow对象名、数据 

。 

l_ 缓存DataWindow控件中的数据:传递标识符(identifier)、Datawindow控件 

。 

l_ 缓存DataStore中的数据:传递标识符(identifier)、DataStore对象。 

l_ 缓存文件中的数据:传递标识符(identifier)、文件名。 

2. 你可以使用函数of_IsRegistered(参数是对象本身),确定DataWindow对象 

是否已经在caching service中注册了。 

3. 调用函数of_GetRegistered函数访问已经缓存的数据。 

Gnv_app.inv_dwcache.of_GetRegistered(攄_emplist敚琲ds_datastore) 

Ids_datastore.ShareData(dw_emplist) 

4. 调用函数of_Refresh检索已经缓存数据的DataWindow 。 

5. 调用函数of_UnRegister函数停止数据缓存服务。 

6. (可选)调用n_cst_appmanager的of_SetDWCache函数关闭DataWindow cachi 

ng service 。 

gnv_app.of_SetDWCache(FALSE) 

通常你没必要显示的关闭DataWindow caching service 。PFC在删除对象n_cst_ 

dwcache时会自动的关闭它。 

2. Debugging service 

概要: 

Debugging service 在应用程序遇到错误时会自动显示错误信息。PFC的消息路由 

当发现需要调用的事件不存在时便会使用Debugging service显示出错信息。 

重要说明:PFC debugging service 只是一个开发工具。在用户的应用程序中不 

要开启它。 

使用方法 

使用debugging service 可以帮助你在PFC的开发过程中解决问题。 

1. 调用n_cst_appmanager的of_SetDebug函数开启Debugging service 。 

gnv_app.of_SetDebug(TRUE) 

2. PFC的对象首先检测应用程序的debugging状态,然后在适当的情况下显示错误 

信息。 

3. (可选)调用n_cst_appmanager的 of_SetDebug函数关闭Debugging service 

。 

gnv_app.of_SetDebug(FALSE) 

多数情况下,你不需要显示的关闭Debugging service 。 

关于PFC提供的两个工具(SQL Spy 和DataWindow Property)的使用请参考第七 

章揚FC Utilities敗?

 

3. Application preference service 

概要: 

你可以利用Application preference service保存、恢复应用程序、用户的信息 

到INI文件或WINDOWS的注册表中。保存和恢复应用程序设置有如下两个好处: 

l_ 延续性:保存应用程序的设置可以使得用户在下次使用软件时可以看到他上次 

关闭软件的样子。也就是说用户不必每次使用软件时都重新设置他的软件环境。 

l_ 容易维护:你可以无须更改n_cst_appmanager的代码的情况下更新应用程序的 

设置。 

PFC通过用户自定义对象n_cst_apppreference提供Application preference ser 

vice 。 

这个Service保存应用程序的如下信息: 

用户键(User key) 

MicroHelp 

Help File 

Version 

Logo bitmap 

Copyright notice 

DDETimeOut property 

DisplayName property 

DWMessage Title property 

MicrohelpDefault property 

RightToLeft property 

ToolbarFrameTitle property 

ToolbarPopMenuText property 

ToolbarSheetTitle property 

ToolbarUserControl property 

Application preference service 同时保存如下的用户信息 

ToolbarText property 

ToolbarTips property 

User ID 

保存、恢复设置 

Application perference service 在应用程序开启的时候会自动恢复应用程序在 

关闭时保存的设置。这些信息可以保存到注册表中(只限于Windows95和Windows 

NT)或者INI文件中。你可以按照如下说明: 

l_ 保存到注册表中:调用函数of_SetUserKey ,指定你需要保存的键。 

l_ 保存到INI文件中:调用函数of_SetUserINIFile ,指定用于保存信息的INI文 

件名。 

使用步骤: 

1. 调用n_cst_appmanager的of_SetAppPref函数开启Application preference s 

ervice 。 

gnv_app.of_SetAppPref(TURE) 

2. 依据不同的执行平台采用不同的方式保存应用程序信息。下面的例子就是在应 

用程序的构造事件中保存应用程序的信息。同时假设你已经在n_cst_appmanager 

中建立好了应用程序信息键、用户信息键、应用程序INI文件、用户INI文件。 

IF this.of_IsRegistryAvailable() THEN 

this.inv_apppref.of_SetAppKey(this.of_GetAppKey()) this.inv_ 

apppref.of_SetUserKey(this.of_GetUserKey()) 

ELSE 

this.inv_apppref.of_SetAppINIFile(this.of_GetAppINIFile()) this.inv_ap 

ppref.of_SetUserINIFile(this.of_GetUserINIFile()) 

END IF 

3. 调用函数of_SetRestoreApp和of_SetRestoreUser函数设置需要保存信息的类 

型: 

this.inv_apppref.of_SetRestoreApp(TRUE) 

this.inv_apppref.of_SetRestoreUser(TURE) 

4. Most recentily used object service 

概要 

你可以使用Most recentily used object service(最近使用对象Service)将最 

经使用的对象、表单列在文件菜单下。默认情况下只允许显示5个最经使用对象。 

但是,你可以改变这个数量。 

PFC 通过n_cst_mru用户自定义对象提供MRU Service(Most recentily uesd ob 

ject service)。 

MRU Service在应用程序启动时会自动的将应用程序关闭时保存的最经使用过的对 

象信息加载到应用程序中。这些信息可以保存到注册表或者INI文件中。你可以通 

过如下的方式: 

l_ 保存到注册表中:调用函数of_SetUserKey函数确定要保存到注册表中的MRU信 

息。 

l_ 保存到INI文件中:调用函数of_SetUserINIFile函数指定用于保存MRU信息的 

INI文件。 

l_ 

你必须还要额外编写代码: 

为了使用MRU Service ,你必须在你想启用MRU Service的窗口的两个事件中编写 

代码。 

l_ pfc_MRUProcess :在窗口开启时加载MRU信息。 

l_ pfc_PreMRUSave :在窗口关闭时保存MRU信息。 

与PFC菜单的结合 

PFC的m_master菜单的FILE菜单包括了五个MRU菜单项,你还可以自己添加。 

如果你的应用程序没有使用PFC的菜单,那么请以m_master为模板建立你自己的M 

RU菜单项。 

使用MRU Service步骤 

1. 调用n_cst_appmanager中的of_SetMRU函数开启MRU Service 。 

gnv_app.of_SetMRU(TRUE) 

2. 调用n_cst_appmanager的函数of_SetUserKey(尽适用于WIN95与WINNT)或of 

_SetUserINIFile函数(使用于所有的平台)确定需要保留的信息。下面的例子假 

设你已经为n_cst_appmanager建立好了的用户键(保存到注册表)或者INI文件( 

保存到INI文件)。下面的代码位于应用程序管理器(n_cst_appmanager)的构造 

事件。 

IF this.of_IsRegistryAvailable() THEN 

this.inv_mru.of_SetUserKey(this.of_GetUserKey()) 

ELSE 

this.inv_mru.of_SetUserINIFile(this.of_GetUserINIFile()) 

END IF 

3. Register IDs with the MRU service by calling the n_cst_mru of_Regis 

ter function. An ID is the identifier that the window will use to retr 

ieve information out of the MRU service. This is an example of code yo 

u can add to the pfc_PreOpen event of the MDI frame window: 

IF IsValid(gnv_app.inv_mru) THEN gnv_app.inv_mru.of_Register("myapp") 

END IF 

4. Extend the pfc_MRUProcess event in each window that uses exclusive 

processing, adding code to open the sheet passing the necessary argume 

nts (be sure to add similar code to the frame window if you want to sp 

ecify exclusive items on the frame menu): 

Window lw_frame, lw_window n_cst_menu lnv_menu n_cst_mruattrib lnv_mru 

attrib // Check parameters. IF IsNull(ai_row) THEN Return -1 END IF 

IF NOT IsValid(gnv_app.inv_mru) THEN Return -1 END IF // Retrieve row 

from DataStore. gnv_app.inv_mru.of_GetItem & (ai_row, lnv_mruattri 

b) // Get the MDI frame, if necessary. lnv_menu.of_GetMDIFrame(this.me 

nuid, lw_frame) OpenSheet(lw_window, & lnv_mruattrib.is_classname, 

lw_frame) Return 1 

Performing other actions in the pfc_MRUProcess eventTo see other types 

of processing you can perform in the pfc_MRUProcess event, see the co 

mments in the pfc_w_master pfc_MRUProcess event.5Extend the pfc_PreMRU 

Save event in each window that uses the MRU service. In this event, po 

pulate the n_cst_mruattrib object with the id, classname, key, item, a 

nd MicroHelp to be saved: 

anv_mruattrib.is_id = "myapp" anv_mruattrib.is_classname = this.ClassN 

ame() anv_mruattrib.is_menuitemname = this.Title anv_mruattrib.is_menu 

itemkey = this.ClassName() anv_mruattrib.is_menuitemmhelp = & "O 

pens " + this.Title Return 1 6Extend the pfc_MRURestore event in eac 

h window that uses the MRU service. In this event, set the ID of the i 

nformation you want to display on the menu: 

If IsValid(gnv_app.inv_mru) Then Return gnv_app.inv_mru.of_Restore 

("myapp", This) End If 

5. Error message service 

概要 

Error Message service提供了许多用于显示、纪录应用程序的错误信息。你既可 

以显示PowerBuilder提供的标准的Message对话框,也可以显示PFC的W_Message对 

话框。两种显示效果都具有如下的功能: 

l_ 消息日志:将消息纪录到文件中,支持多种平台。PFC会自动的将严重级别大 

于某个值的消息纪录到文件中。 

l_ 支持MAPI:通过Email发出错误警告。PFC会自动将严重级别大于某个值的消息 

作为邮件发出。 

l_ 消息数据库:通过已经定义好的形式(可以是数据库或文件)来存取消息。定 

义好了消息格式,使得消息有一种标准的形式、消息的重复减到最少、容易查询 

。 

l_ 参数替代:消息可以具有参数,这样它会依据程序运行而变化。 

l_ 不显示,直接纪录:消息可以不显示直接纪录到日志中。 

l_ 注释与打印:用户可以打印消息,甚至可以增加注释。对消息日志用于邮件时 

非常有用的。 

l_ 自动关闭:w_message过了数秒后会自动关闭。 

W_message 位图 

如果你使用w_message ,位图在运行时必须有效。 

用法 

Error service可以处理应用程序所有的错误信息。如果你打算将错误信息保存到 

数据库中,你可以使用PFC.DB中关于消息的几个表,或使用消息管道将它传到你 

的数据库中。 

使用Messages表 

大多数情况下,你应该将Messages表复制到你的数据库中。这个表已经包含了PF 

C的错误信息格式。 

使用步骤: 

1. 调用n_cst_appmanager的of_SetError函数开启error message service(创建 

n_cst_error实例),下面的代码位于n_cst_appmanager的pfc_Open事件: 

this.of_SetError(TRUE) 

2. 定义错误消息的源: 

l_ 如果消息源是文件,调用如下函数: 

this.inv_error.of_SetPredefinedSource(揷:\eisapp\eiserr.txt? 

l_ 如果消息源是数据库,调用如下函数: 

this.inv_error.of_SetPredefinedSource (itr_error) 

消息源:当你使用文件作为消息源时,文件中必须包括PFC.DB中Messages表中的 

所有数据。同时列必须由TAB键隔开。 

PFC uses predefined messages in certain situations. If you enable the 

error message service and receive message display errors, make sure th 

e error message source has been established correctly. Additional user 

-defined messages must conform to the format of the messages table (al 

so used by the d_definedmessages DataWindow object). 

l_ (可选)设置日志文件名(调用函数of_SetLogFile参数为空字符串可以不进 

行日志纪录): 

this.inv_error.of_SetLogFile(擟:\pb6\errlog.txt敚?

l_ (可选)设置用户ID(用于日志文件): 

this.inv_error.of_SetUser(this.of_GetUserID()) 

l_ (可选)设置什么类型的消息需要自动纪录: 

this.inv_error.of_SetNotifySeverity(5) 

this.inv_error.of_SetLogSeverity(4) 

l_ (可选)如果你的应用程序使用了错误自动通告功能。你需要设置当前用户的 

Email、密码。还可以设置其他的Email用户与密码。下面的例子展示了如何设置 

Email ID与Password 。 

this.inv_error.of_SetNotifyConnection(ims_mailsess) this.inv_error.of 

_SetNotifyWho(is_autonotify) 

说明:以上的代码都可以在n_cst_appmanager的pfc_Open事件中。 

l_ 在应用程序的错误检测中,使用函数of_Message显示对话框。同时你还可以将 

它纪录到日志中。函数of_Message可以使用数据库中的消息,也可以动态的指定 

消息。下面的例子就是使用数据库中的消息: 

gnv_app.inv_error.of_Message(擡IS0210敚?

使用参数表(只限于已定义的消息) 

1. 在消息表中定义如下的数据。%运行时将被替换: 

EIS1030 Unable to find the file % in % 

2. 定义一个参数数组: 

String ls_parms[] 

ls_parms[1] = 揕ogfile.txt?

ls_parm[2] = 揷:\windows\system?

3. 调用of_Message ,传递参数: 

gnv_app.inv_error.of_Message(擡IS1030敚琹s_parms) 

PFC在显示消息时使用数组中的第一个元素替换第一个% ,第二元素替换第二个% 

。 

6. Security service 

概要 

PFC的安全机制可以处理许多你的应用程序安全性问题。它包括应用程序管理员组 

件、安全对象(security object)n_cst_security 。 

用法:在使用Security service时,你必须要定义用户组与用户,然后分别与窗 

口、菜单、用户对象、控件相关联,然后再编写代码。 

使用步骤: 

1. 定义用户、用户组。参考第七章擯FC Utilities?

为你的窗口控件、菜单、用户对象、其他控件定义安全属性。参考第七章擯FC 

Utitities?

2. 调用n_cst_appmanager的of_SetSecurity函数创建安全对象 

this.of_SetSecurity(TRUE) 

3. 为安全对象建立一个事务对象。 

Itr_sec = Create n_tr 

Connect using itr_sec; 

4. 调用函数of_InitSecurity初始化安全对象。 

This.inv_security.of_InitSecurity(itr_sec.擡ISAPP敚琯nv_app.of_GetU 

serID(),擠EFAULT敚?

5. 以上的代码全部在n_cst_appmanager的pfc_Open事件中编写。 

6. 应用程序关闭时,断开事务对象的连接、删除事务对象。以下的例子在n_cst 

_appmanager的pfc_Close事件中。 

Disconnect using itr_sec; 

Destroy itr_sec 

7. 在你需要使用安全对象的窗口的Open事件或pfc_PreOpen事件中调用函数of_S 

etSecurity() 

IF NOT gnv_app.inv_security.of_SetSecurity(this) THEN 

MessageBox("Security","Unable to set security") 

Close(this) 

End if 

说明:你可以在其他对象(Datawindow、可视用户对象、菜单,所有你想实现安 

全机制的对象)。 

7. Transaction registration service 

概要 

Transaction registration service可以追踪你的应用程序中的事务对象的使用 

过程。这个服务只对基于n_tr的对象有效。PFC使用n_cst_trregistration对象实 

现Transaction registration service 。 

用法 

当应用程序中使用多个事务对象时,你应该使用Transaction registration ser 

vice跟踪所有的事务对象。当你的应用程序关闭时,该对象将会自动删除所有已 

注册的事务对象。使用n_tr的函数of_SetAutoRollback设置ib_autorollback的值 

。如果ib_SetAutoRollback的值为False ,则事务对象关闭时将会自动提交。如 

果ib_SetAutoRollback的值为True ,则事务对象关闭时会自动回滚。 

启动 Transaction registration service 

l_ 调用n_cst_appmanager的of_SetTrRegistration函数 

gnv_app.of_SetTrRegistration(True) 

当应用程序关闭时,应用程序会自动删除 Trasaction registration service 。 

 

注册事务对象: 

l_ 调用n_cst_trregistration的of_Register函数 

gnv_app.inv_trregistration.of_Register(SQLCA) 

控制当事务对象正处于连接时被删除时的行为 

l_ 调用n_tr的of_SetAutoRollback函数 

SQLCA.of_SetAutoRollback(True) 

如果你设置为True ,同时该对象正处于连接状态,当它被删除时Service会回滚 

该事务。如果你设置为False ,Service回提交该事务。尽管如此,你应该显示的 

提交或回滚、断开连接。 

2 Datawindow服务 

概要 

大部分的PowerBuilder的应用程序都大量的使用了Datawindow控件。PFC因此提供 

了功能强大的Datawindow Services 。大部分的Service使用时只需一点代码或者 

根本不需要编码。PFC的Datawindow Servies实际上都是由一个公共的父类对象( 

不可视用户自定义对象)继承而来。这个父类对象包括了许多Service的函数、事 

件、实例变量。同时么每个Datawindow Service还有自己的函数、事件、实例变 

量。 

访问Datawindow Services 

为了使用DataWindow Services,你应该建立基于u_dw的Datawindow对象。U_dw对 

象包括: 

l_ 用于开启、关闭Datawindow Services的函数。 

l_ 用于调用各种Services的函数、事件、实例变量的引用变量。 

l_ 调用Datawindow Service的函数、事件的Precoded事件、用户事件 

l_ 可供你编写代码的空事件 

在你的应用程序中所有的DataWindow控件都必须是u_dw的子类。 

开启DataWindow Services 

只开启Datawindow控件需要的Servie ,这样才能将应用程序的负荷将到最小。以 

下表格列出了所有的Datawindow Service ,以及对应的对象。 

DataWindow Service 对应的对象 

Datawindow service的基类 n_cst_dwsrv 

Dropdown search service n_cst_dwsrv_dropdownsearch 

Filters service n_cst_dwsrv_filter 

Find andreplace service n_cst_dwsrv_find 

Linkage service n_cst_dwsrv_linkage 

Multitable update service n_cst_dwsrv_multitable 

Print preview service n_cst_dwsrv_printpreview 

DataWindow property service n_cst_dwsrv_property 

Querymode service n_cst_dwsrv_querymode 

Reporting service n_cst_dwsrv_report 

Required column service n_cst_dwsrv_reqcolumn 

DataWindow resize service n_cst_dwsrv_resize 

Row management service n_cst_dwsrv_rowmanager 

Row selection service n_cst_dwsrv_rowselection 

Sort service n_cst_dwsrv_sort 

8. DataWindow Services 的父类 

概要 

DataWindow Services的父类包括了所有DataWindow Services需要的Instance变 

量、事件、函数。PFC使用n_cst_dwsrv实现DataWindow Services的父类。 

DataStore Service:DataStore Service的对象是n_cst_dssrv 

用法 

你可以使用这些Service实现如下功能 

l_ 获取、设置DataWindow信息 

l_ 修改、获取DataWindow脚本函数 

l_ 默认DataWindow service 

父类函数在子类中有效 

因为n_cst_dwsrv是所有DataWindow services的父类,因此所有在n_cst_dwsrv的 

函数在它的子类中都有效。 

开启Basic DataWindow service 

l_ 调用u_dw的of_SetBase函数 

dw_emplist.of_SetBase(TRUE) 

当Datawindow被删除时u_dw会自动删除该Service 。 

访问DataWindow 

l_ 调用n_cst_dwsrv中的函数 

函数 调用 

of_Describe 访问DataWindow的属性、列。 

Of_GetHeaderName 确定某一列的列名 

Of_GetHeight 确定某一列的高度 

Of_GetObject 依据对象名访问DataWindow中的对象 

Of_GetWidth 确定某一列的宽度 

Of_GetItemOf_GetItemAny 获取DataWindow中某一列的数据(任何类型数据)。 

 

给DataWindow设置数据 

l_ 调用n_cst_dwsrv中如下函数: 

函数 调用 

of_Modify 修改DataWindow属性、列。 

Of_SetItem 设置、修改DataWindow的数据(任何数据类型)。 

刷新DataWindow中所有的下拉DataWindow: 

l_ 调用函数of_PopulateDDDWs 

Integer li_return 

li_return = dw_emplist.inv_base.of_PopulateDDDWs() 

gnv_app.of_GetFrame().SetMicroHelp(String(li_return) + " DDDW columns 

refreshed") 

访问DataWindow service的默认值: 

l_ 调用如下的函数 

函数 调用说明 

of_GetColumnDisplayName 确定DataWindow中某一列的显示名。 

Of_GetColumnNameStyle 确定当DataWindow需要显示列时那些列需要显示 

Of_GetDefaultHeaderSuffix 确定DataWindow列名的默认后缀。 

Of_GetDisplayItemOf_GetDisplayUnits 确定关闭时显示的消息 

Of_SetColumnDisplayNameStyle 确定当DataWindow Service需要显示列时显示的 

信息l_ DataWindow列名l_ Database列名l_ DataWindow列标题名 

Of_SetDefaultHeaderSuffix 设置默认的DataWindow列标题的后缀 

Of_SetDisplayItemOf_SetDisplayUnits 设置关闭时显示的信息 

9. Dropdown DataWindow search service 

概要 

PFC下拉DataWindow seach service提供了一个当用户敲入一个字母后自动滚到该 

字母开头的数据项上。它对应的对象是n_cst_dwsrv_dropdownsearch 。 

使用方法 

开启Dropdown DataWindow search service 

1. 调用u_dw的of_SetDropDownSearch函数 

this.of_SetDropDownSearch(TRUE) 

U_dw被删除时会自动删除这些Service 。 

2. 在DataWindow控件的EditChanged事件中调用n_cst_dropdownsearch的pfc_Ed 

itChanged事件: 

this.inv_dropdownsearch.event pfc_EditChanged(row,dwo,data) 

3. 在DataWindow控件的ItemFocusChanged事件中调用n_cst_dwsrv_dropdownsea 

rch的pfc_ItemFocusChanged事件 

this.inv_dropdownsearch.Event pfc_ItemFocusChanged(row,dwo) 

4. 调用函数of_AddColumn为DataWindow的列启用DropDown DataWindow search 

service 。 

this.inv_dropdownsearch.of_AddColumn(揹ept_id? 

10. Filter service 

概要 

PFC的Filter service提供了一个非常简单易用的过滤功能。它对应的对象是n_c 

st_dwsrv_filter 。 

使用说明 

Filter service自动的显示过滤对话框。你所要作的只是开启Service、指定过滤 

类型。你可以选择三种过滤对话框。 

l_ PowerBuilder标准对话框 

l_ 两种PFC提供的对话框 

l_ w_filtersimple 下拉Listbox界面。 

l_ w_filterextended Tabbed界面。 

开启Filter service 

l_ 调用u_dw的of_SetFilter函数,设置事务对象,指定过滤对话框使用DataWin 

dow的列标题: 

dw_emp.of_SetFilter(TRUE) 

dw_emp.of_SetTransObject(SQLCA) 

dw_emp.inv_filter.of_SetColumnDisplayNameStyle(dw_emp.inv_filter.HEADE 

R) 

u_dw在被删除时会自动删除该Service 。 

设置过滤风格: 

l_ 调用函数of_SetStyle,指定对话框风格: 

dw_emplist.inv_filter.of_SetStyle(dw_emp.inv_filter.SIMPLE) 

显示过滤对话框: 

l_ 调用事件pfc_FilterDlg事件: 

dw_emplist.inv_filter.event pfc_FilterDlg() 

你无须显示的调用该事件。大多数情况下,用户通过选择View>Filter菜单显示过 

滤对话框。 

11. Find and replace service 

概要 

PFC的Find and replace service使得你可以在你的应用程序中加入查找与替换功 

能。它对应的对象是n_cst_dwsrv_find 。 

使用说明 

你可以使用该服务为DataWindow提供查找与替换的功能。可以显示w_find窗口或 

w_replace窗口。如果用户在m_master菜单的子类中选择了Edit>Find或Edit>Rep 

lace时该服务将自动显示w_find或m_master窗口。 

开启Find service 

l_ 调用u_dw的of_SetFind函数: 

dw_emplist.of_SetFind(TRUE) 

U_dw被删除时将自动删除该服务 

显示w_find对话框: 

l_ 调用u_dw的pfc_FindDlg事件 

dw_Emplist.Event pfc_FindDlg() 

你无须显示的调用该事件。用户选择Edit>Find时会自动显示w_find对话框。 

显示w_replace对话框: 

l_ 调用u_dw的pfc_ReplaceDlg事件: 

dw_emplist.Event pfc_ReplaceDlg() 

你无须显示的调用该事件。用户选择Edit>replace时会自动显示w_replace对话框 

。 

12. Linkage service 

概要 

PFC的linkage service帮助你实现主/从窗口合作处理。 

Linkage service包括如下功能: 

l_ Linkage style(连接风格):控制从窗口的DataWindow检索数据、过滤数据 

、滚动到特定行。 

l_ Update style(更新风格):控制Linkage service更新DataWindows的方式( 

top-down, bottom-up, top-down then bottom-up, bottom-up then top-down, 

or a developer-specified custom update) 

l_ 数据发生变化时的提醒窗口:当主数据发生变化,从数据即将丢失时,该选项 

可以显示一个提醒窗口。 

l_ 删除数据时的提醒窗口:当用户删除数据时可以显示提醒窗口 

l_ Cascading key changes:当用户改变主纪录时,Linkage service会自动修改 

从纪录 

l_ 删除风格:当你删除主纪录时,该选项可以设成删除从纪录、不理会从纪录。 

l_ 更新扩展:允许你将其他的控件也作为默认数据保存过程。 

使用说明 

你可以使用Linkage service处理各种DataWindow中的合作。尽管如此,大部分时 

候都是用于处理主/从关系的DataWindow 。 

开启Linkage service: 

l_ 调用u_dw的of_SetLinkage函数: 

dw_emplist.of_SetLinkage(TRUE) 

u_dw自动删除所有Service 。 

使用Linkage service实现主/从处理: 

1. 在主从DataWindow中同时开启Linkage service: 

dw_master.of_SetLinkage(TRUE) 

dw_detail.of_SetLinkage(TRUE) 

2. 分别为主从DataWindow设置事务对象: 

dw_master.inv_linkage.of_SetTransObject(SQLCA) 

dw_detail.inv_linkage.of_SetTransObject(SQLCA) 

3. 将从DataWindow连接到主DataWindow中: 

dw_detail.inv_linkage.of_SetMaster(dw_master) 

4. 调用函数of_Register注册关联列: 

dw_dwtail.inv_linkage.of_Register(攅mp_id?攅mp_id敚?

5. (可选)(Optional) Specify that the service updates DataWindows fro 

m the bottom of the linkage chain on up (the default is to update top 

down): 

dw_detail.inv_linkage.of_SetUpdateStyle(dw_detail.inv_linkage.BOTTOMUP 



6. 调用函数of_SetStyle建立当主数据改变时从数据的动作。 

下面的例子说明了当主数据改变时从数据检索数据: 

dw_detail.inv_linkage.of_SetStyle(dw_detail.inv_linkage.RETRIEVE) 

7. 调用主DataWindow的of_Retrieve函数: 

IF dw_master.of_Retrieve()= -1 特Then 

MessageBox(擡rror?擱etrieve error敚?

Else 

Dw_Master.SetFocus() 

End if 

你可以将以上的代码全部写在一个事件中。 

8. 在主DataWindow的pfc_Retrieve事件中添加检索数据的代码: 

Return this.Retrieve() 

检索数据:如果Linkage service刷新了从数据。你只需要编写代码检索主DataW 

indow。如果你打开了filter和scroll选项,你必须在从DataWindow中编写检索数 

据函数。 

数据改变时的提醒窗口(尽限于retrieval风格) 

1. 在从DataWindow中调用of_SetUpdateOnRowChange函数: 

dw_detail.inv_linkage.of_SetUpdateOnRowChange(TRUE) 

2. 在从Datawindow中调用of_SetConfirmOnRowChange函数 

dw_detail.inv_linkage.of_SetConfirmOnRowChange(TRUE) 

数据删除时的提醒窗口 

1. 在从DataWindow中调用of_SetUpdateOnRowChange函数: 

dw_detail.inv_linkage.of_SetUpdateOnRowChange(TRUE) 

2. 在从DataWindow中调用of_SetConfirmOnDelete函数 

dw_detail.inv_linkage.of_SetConfirmOnDelete(TRUE) 

开启casacding key 

l_ 在所有关联的DataWindow中调用of_SetSyncOnKeyChange函数 

dw_master.inv_linkage.of_SetSyncOnKeyChange(TRUE) 

dw_detail.inv_linkage.of_SetSyncOnKeyChange(TRUE) 

设置删除风格: 

l_ 在主DataWindow中调用函数of_SetDeleteStyle 

dw_master.inv_linkage.of_SetDeleteStyle(dw_cust.inv_linkage.DISCARD_R 

OWS) 

启用更新扩展: 

l_ 为其他需要添加到默认保存过程中的控件调用函数of_SetOtherSaveObjects 

PowerObject lpo_objs[ ] 

// This example adds the lv_salesinfo ListView 

// to the save process. 

lpo_objs[1] = lv_salesinfo 

dw_master.inv_linkage.of_SetOtherSaveObjects(lpo_objs) 

13. Multitable update service 

PFC的多表更新服务(Multitable update service)使得你的DataWindow可以轻 

松更新多表。它对应的对象是n_cst_dwsrv_multitable 。 

DataStore services 

该服务同样适用于DataStore ,对应的对象是n_cst_dssrv_multitable 。 

使用说明: 

当你需要更新的数据涉及到多个表时就需要使用该服务。当你调用w_master的pf 

c_Save事件时。PFC会更新所有的表。 

开启多表更新服务: 

l_ 调用函数u_dw的函数of_SetMultiTable: 

dw_emplist.of_SetMultiTable(TRUE) 

u_dw会自动删除所有的服务 

指定需要更新的表: 

l_ 调用函数of_Register设定需要更新的表: 

String ls_projcols[] = {損roj_id攠 

String ls_taskcols[] = {損roj_id?攖ask_id攠 

Dw_project.inv_multitable.of_Register(損roject?ls_projcols) 

Dw_project.inv_multitable.of_Register(搕ask?ls_taskcols) 

(可选)更新包含多表数据的DataWindow 

l_ 调用w_master的函数pfc_Save事件 

Integer li_return 

Li_return = w_sheet.Event pfc_Save() 

… 

14. Print preview service 

概要 

PFC的打印预览服务使你的DataWindow可以具备打印预览的功能: 

l_ 打印预览 

l_ 第一页、下一页、上一页、最后一页 

l_ 放大、缩小 

菜单m_master的子类会自动访问这些功能。它对应的对象是n_cst_dwsrv_printp 

review 。 

该服务对DataStore同样有效,它对应的对象是n_cst_dssrv_printpreview 。 

使用说明 

该服务使得你的应用程序具备了打印预览的功能。用户选择File>Print Preview 

菜单项便进入预览模式。 

开启打印预览模式: 

l_ 调用u_dw的of_SetPrintPreview函数: 

dw_emplist.of_SetPrintPreview(TRUE) 

u_dw自动会删除所有的服务。 

15. DataWindow properties service: 

概要 

DataWindow属性服务允许你显示DataWindow的属性窗口。还可以 

l_ 开启、关闭其他的DataWiindow服务 

l_ 察看某个服务的PFC语法 

l_ 交互式的访问、修改DataWindow的属性,具体如下: 

DataWindow buffers 

Row and column status 

Statistics 

Properties of all objects on the DataWindow object 

详情察看擠ataWindow Properties window?

使用说明: 

开启DataWindow属性服务(DataWindoe Properties service) 

1. 调用函数of_SetProperty: 

dw_emplist.of_SetProperty(TRUE) 

U_dw会自动的删除所有的Service 。 

2. 当DataWindow出现时,右击,选择DataWindow属性: 

16. Query mode service 

概要 

PFC的查询模式使得你可以轻松的在你的应用程序中加入查询模式。它也可以帮助 

你懂得如何使用、理解查询模式。在查询模式中,用户可以点击右键,在弹出式 

菜单中选择显示的列、操作符、数据。它对应的对象是n_cst_dwsrv_querymode 

。 

使用说明 

你可以使用PFC的Query service实现如下功能: 

l_ 开始、中止查询模式 

l_ 选择某列 

l_ 将查询结果保存到文件中,调用以前的查询结果。 

开启查询模式服务 

l_ 调用u_dw的of_SetQuerymode函数 

dw_emplist.of_SetQuerymode(TRUE) 

u_dw会自动删除所有的Service 。 

进入查询模式: 

l_ 调用函数of_SetEnabled,参数为TRUE 

dw_emplist.inv_querymode.of_SetEnabled(TRUE) 

结束查询模式: 

l_ 调用函数of_SetEnabled,参数为FALSE 

dw_emplist.inv_querymode.of_SetEnabled(FALSE) 

设定查询列: 

l_ 调用函数of_SetQueryCols,参数为需要查询的列数组: 

String ls_cols[] 

Ls_cols[1] = 揺mp_dept_id?

Ls_cols[2] = 揺mp_id?

Dw_emplist.inv_querymode.of_SetQueryCols(ls_cols) 

当你调用函数of_SetEnabled ,查询模式服务会保护为被选择的列。 

将查询保存到文件中: 

1. 调用函数of_SetEnabled(TRUE)开始查询模式。 

2. 许用户设定查询条件。 

3. 调用函数of_Save 

该函数会出现一个对话框提示用户输入用于保存数据的文件名。 

从文件中加载查询: 

l_ 调用函数of_Load 

该函数出现一个对话框提示用户输入用于加载的文件名。 

17. Reporting service 

概要 

PFC的报表服务增强了DataWindow的显示、打印功能。该服务中的许多函数既可以 

修改DataWindow中的对象也可以获得DataWindow中的修改语法,并为你的修改语 

句所用。If you code more than two consecutive report service functions 

, consider returning the Modify syntax, concatenating the strings and 

issuing the Modify function from within your own code 。 

DataWindow必须使用PBUs或者pixels 

使用该Service,DataWindow必须使用PBUs或者pixels作为度量单位。它不允许使 

用英尺、公分(It does not work with DataWindows that use thousandths o 

f an inch or thousandths of a centimeter as the DataWindow Unit)。它对 

应的对象是n_cst_dwsrv_report 。 

该服务同样适用于数据存储(DataStore),对应的对象是n_cst_dssrv_report 

。 

使用说明 

你可以使用该服务实现如下功能: 

l_ 给DataWindow增加一项 

l_ 建立复合报表。操纵起来就像使用一个报表一样。 

l_ 格式化与打印 

l_ 设置背景、颜色、边框 

l_ 放大、缩小 

On Macintosh:函数of_AddComputer、of_AddText、of_GetTextSizePos函数不可 

用。 

开启报表服务: 

l_ 调用函数of_SetReport 

dw_emplist.of_SetReport(TRUE) 

U_dw会自动删除所有的service 。 

给DataWindow增加一项: 

l_ 调用n_cst_dwsrv_report中的如下函数 

函数 用途 

of_AddCompute 增加一个计算列 

of_AddLine 增加一行 

of_AddPicture 增加一幅图片 

of_AddText 增加字符 

建立符合报表: 

1. 调用函数of_CreateComposite,传递需要复合的DataWindow信息: 

String ls_dws[ ], ls_trailfooter[ ] 

String ls_slide[ ] 

String ls_return 

Integer li_return 

Boolean lb_vertical 

Border lbo_border[ ] 

lb_vertical = TRUE 

ls_dws[1] = "d_employee" 

ls_dws[2] = "d_benefits" 

ls_trailfooter[1] = "No" 

ls_trailfooter[2] = "Yes" 

ls_slide[1] = "AllAbove" 

ls_slide[2] = "AllAbove" 

lbo_border[1] = Lowered! 

lbo_border[2] = Lowered! 

li_Return = dw_composite.inv_report.of_CreateComposite(ls_dws, lb_vert 

ical, ls_trailfooter, ls_slide, lbo_border) 

IF li_Return = 1 THEN 

dw_composite.SetTransObject(SQLCA) 

dw_composite.Event pfc_Retrieve( ) 

END IF 

2. 打印与显示复合报表 

dw_composite.inv_report.of_PrintReport(TRUE,FALSE) 

打印输出Datawindow: 

l_ 调用函数of_PrintReport。 

设置默认值、颜色、边框: 

调用n_cst_dwsrv_report中的如下函数 

函数 用途 

of_SetDefaultBackColor 修改DataWindow的默认值 

of_SetDefaultBorder 

of_SetDefaultCharset 

of_SetDefaultColor 

of_SetDefaultFontFace 

of_SetDefaultFontSize 

of_SetBorder 修改一个或多个DataWindow中的对象的边框 

of_SetColor 修改一个或多个DataWindow中的对象的颜色、背景色 

控制DataWindow的大小: 

l_ 调用函数of_SetRelativeZoom 

缩放与当前的显示有关:函数Of_SetRelativeZoom的参数是当前大小的百分数。 

例如DataWindow当前显示的大小是正常的80%,此时你调用函数of_SetRelativeZ 

oom(50),当前大小即变为40% 。 

18. Required column service 

概要 

PFC的非空列服务(Required column service)可以处理那些必须要输入数据的 

列。它使得你非常容易的处理那些输入不完整的数据。该服务只适用于那些具有 

nilisnull属性的列。例如,EditMasks不具备该属性,因此非空列服务不适用于 

Edit Mask 。 

它对应的对象是n_cst_dwsrv_reqcolumn 。 

使用说明 

DataWindow非空列的处理会与GUI界面的应用程序产生冲突。非空列服务可以将对 

非空列的处理留到用户输入数据完毕后处理。该服务允许你设置哪些列是非空列 

。 

非空列的检测:当你调用Window的pfc_Save事件时它会自动的进行非空列的检测。 

 

开启非空列服务 

l_ 调用函数of_SetReqColumn 

dw_emplist.of_SetReqColumn(TRUE) 

U_dw会自动删除所有的服务 

放弃某些列的非空处理: 

l_ 调用函数of_RegisterSkipColumn指定哪列需要保留PowerBuilder标准的非空 

列处理: 

dw_Emplist.inv_reqcolumn.of_RegisterSkipColumn(攄ept_id敚?

19. Row management service 

概要 

PFC的Row management service允许你插入、删除数据。同时还提供了恢复被删除 

的数据功能。它对应的对象是n_cst_dwsrv_rowmanager 。 

使用说明: 

该服务有如下作用: 

l_ 在DataWindow的最后加上一行空记录 

l_ 在两行数据之间插入一行记录 

l_ 删除一条或多条记录 

l_ 显示一个对话框用于允许你恢复已删除的记录。 

开启行管理服务(Row Management service) 

l_ 调用函数of_SetRowManager: 

dw_Emplist.of_SetRowManager(TRUE) 

在DataWindow的末尾增加一条记录: 

l_ 调用事件pfc_AddRow: 

Long ll_return 

ll_return = dw_emplist.inv_rowmanager.Event pfc_AddRow() 

IF ll_return = -1 THEN 

MessageBox("Error", "Error adding empty row") 

END IF 

当用户从弹出式菜单m_dw中选择Add时,PFC会自动的调用该事件。 

在两记录之间插入数据: 

l_ 调用事件pfc_InsertRow 

下面的例子在当前行中插入数据: 

Long ll_return 

ll_return = dw_emplist.inv_rowmanager.Event pfc_InsertRow() 

IF ll_return = -1 THEN 

MessageBox("Error", "Insert error") 

END IF 

当用户在弹出式菜单m_dw中选择Insert时,PFC会自动的调用该事件。 

删除数据: 

l_ 调用函数pfc_DeleteRow事件 

下面的例子删除当前行或选择的行: 

Long ll_return 

ll_return = dw_emplist.inv_rowmanager.pfc_DeleteRow() 

IF ll_return = -1 THEN 

MessageBox("Error", "Deletion error") 

END IF 

当用户选择弹出式菜单m_dw的Delete时,PFC会自动调用该事件。为了实现多选供 

功能使用行选择服务(row selection service。 

恢复已删除的数据: 

l_ 调用事件pfc_RestoreRow 

该事件调用 of_UnDelete,同时出现一个对话框给用户用于用户选择需要恢复的 

记录。 

20. Row selection service 

概要 

PFC的行选择服务(Row selection serviec)允许你在DataWindow中实现单个、 

多个、扩展的选择能力。它对应的对象是n_cst_dwsrv_rowselection 。 

使用说明: 

行选择服务自动处理的所有的行选择处理。所有你需要作的只是开启该服务、指 

定你所想要的风格 

l_ 单行选择:当你的DataWindow只允许实现单行选择是请采用此风格。 

l_ 多行选择:允许你的用户一次选择多条记录。这些记录可以是连贯的也可以是 

非连贯的。当使用多行选择风格时,程序运行时,用户单击后会触发row抯 选择 

状态。该特性与listbox的多项选择相似。 

l_ 扩展的选择:你可以使用键盘与鼠标共同实现选择操作,SHIFT+Click,CTRL 

+Click 。 

同样该风格也相似与listbox的扩展选择。 

开启行选择服务: 

l_ 调用u_dw的函数of_SetRowSelect(TRUE) 

U_dw会自动删除所有的服务。 

设定行选择风格: 

l_ 调用函数of_SetStyle ,指定你想设定的行选择风格: 

dw_emplist.inv_rowselect.of_SetStyle(dw_emplist.inv_rowselect.EXTENDE 

D) 

21. DataWindow resize service 

概要 

PFC的resize服务使得用户在改变窗口大小时自动的改变DataWindow中的列的大小 

。它对应的对象是n_cst_dwsrv_resize 。 

使用说明: 

你可以使用resize服务使得你的DataWindow中的列自动的随着Window的大小变化 

而变化。 

特别说明:你不可以在Composite或者RichTextEdit风格的Datawindow中使用Res 

ize服务。 

开启DataWindow的Resize服务: 

1. 调用u_dw的of_SetResize函数、设置事务对象、依据列标题指定排序对话框: 

dw_emp.of_SetResize(TRUE) 

u_dw会自动删除所有的服务。 

2. (可选)调用函数of_SetOrigSize设置DataWindow控件的原始大小。当你在M 

DI窗口下打开一表单(Sheet)时可以使用该函数替代枚举变量Original!: 

this.inv_resize.of_SetOrigSize(this.width,this.height) 

3. (可选)调用函数of_SetMinSize设定DataWindow的最小大小。 

This.inv_resize.of_SetMinSize(this.width ?50 , this.height - 100) 

4. 调用函数of_Register设定哪些列需要Resize、如何Resize : 

this.inv_resize.of_Register("emp_fname",0,0,50,50) 

this.inv_resize.of_Register("emp_lname",100, 0, 50, 50) 

5. 开启Window resize service,注册DataWindow控件 

this.of_SetResize(TRUE) 

this.inv_resize.of_Register(dw_1,0,0,100,100) 

6. (可选)调用函数of_UnRegister函数将某一列从列表中删除,即取消对某一 

列的resize service 。 

22. Sort service 

概要 

PFC的Sort服务使得你轻易的在你的DataWindow中增加了排序的功能。它对应的对 

象是n_cst_dwsrv_sort 。 

使用说明 

该服务会自动的显示排序对话框。所有你需要作的只是开启服务,指定你所想的 

排序风格。你有四种风格选择。 

l_ PowerBuilder标准排序风格 

l_ 拖拉风格(w_sortdragdrop) 

l_ 多列选择风格(w_sortmulti) 

l_ 单列选择风格(pfc_w_sortsingle) 

开启排序服务 

l_ 调用函数of_SetSort开启服务,同时指定排序对话框使用列标题: 

dw_emp.of_SetSort(TRUE) 

dw_emp.inv_sort.of_SetColumnDisplayNameStyle(dw_emp.inv_sort.HEADER) 

u_dw会自动删除所有的服务 

指定PFC的排序服务只对显示的数据进行排序还是对所有的数据进行排序: 

l_ 调用函数of_SetUseDisplay 

dw_emp.inv_sort.of_SetUseDisplay(TRUE) 

指定排序风格: 

l_ 调用函数of_SetStyle指定排序风格: 

dw_emp.inv_sort.of_SetStyle(dw_emp.inv_sort.DRAGDROP) 

显示排序对话框: 

l_ 调用事件pfc_SortDlg 

dw_emplist.Event pfc_SortDlg() 

通常你没必要显示的调用该事件,当用户选择View>Sort(菜单m_master的后代) 

时会自动的打开排序窗口。 

3 窗口服务 

为了使用窗口服务,你的窗口必须继承w_master或者它的后代: 

w_child 

w_frame 

w_main 

w_popup 

w_response 

w_sheet 

w_master包含: 

l_ 用于开启、关闭窗口服务的函数 

l_ 各个用户自定义对象的引用变量。 

l_ 用于执行窗口服务的已编号代码的事件 

l_ 空用户事件 

关于继承:当你继承窗口是一定要继承w_prefix开头的窗口,不要继承pfc_pref 

ix开头的窗口。Pfc_prefix开头的对象是用于升级PFC的。 

以下表格列出了各种窗口服务以及对应的变量: 

窗口服务 实现对象 

Basic window n_cst_winsrv以及函数、用户事件 

Preference service n_cst_winsrv_preference 

Sheet managerment service n_cst_winsrv_sheetmanager 

Status bar service n_cst_winsrv_statubar 

23. Basic window services 

概要 

PFC的窗口中有: 

l_ 窗口函数 

l_ 预代码事件、用户事件 

l_ 空用户事件 

这些函数、事件对你的应用程序中的所有窗口都有效。如果你使用PFC的标准可视 

控件、m_master的后代菜单,那么PFC回自动完成它们的连接。 

自动的关闭询问处理:PFC的所有窗口都会自动处理带有DataWindow的关闭询问处 

理。当用户在保存对话框中选择YES是,PFC会自动的将Datawindow的所有修改都 

保存。如果你需要作特定的保存处理,你可以覆盖CloseQuery事件。或者将变量 

ib_disableclosequery值设为True 。 

使用说明: 

基本窗口服务具有如下功能: 

l_ 消息路由、菜单集成 

l_ 由PFC菜单触发的空用户事件 

l_ 工具栏,只限于w_frame 

l_ 自动保存处理 

关于PFC窗口类型的资料请参考PFC Object Reference 。 

在菜单项的脚本中使用消息路由: 

l_ 调用菜单函数of_SendMessage ,以用户事件为参数: 

of_SendMessage(攑fc_CheckStatus敚?

该函数会将请求传递给n_cst_menu的of_SendMessage函数,然后n_cst_menu的of 

_SendMessage函数会将请求传递给当前窗口的pfc_MessageRoute事件,然后目标 

事件才会被调用。 

在非菜单函数或事件中使用消息路由: 

l_ 调用活动窗口的pfc_MessageRouter事件,传递需要调用的事件: 

this.Event pfc_MessageRouter(攑fc_CheckStatus敚?

事件pfc_MessageRouter将请求传递给当前窗口,然后目标事件便会触发。 

PFC的菜单使用菜单函数of_SendMessage调用窗口中的用户事件。 

使用空用户事件: 

l_ 为了某种目的在PFC的用户事件中添加代码。下面的例子说明了当你需要显示 

一个PageSetup对话框时,你可以在pfc_PageSetup事件中编写代码: 

Integer li_return 

li_return = idw_active.Event pfc_PageSetup() 

IF li_return > 0 THEN 

li_return = idw_active.Event pfc_PrintImmediate() 

END IF 

在PFC Object Reference中有关于该事件的其他必须代码的说明。 

显示用于控制工具栏的窗口 

l_ 调用框架窗口的pfc_ToolBars事件: 

gnv_app.of_GetFrame().Event pfc_Toolbars() 

当用选择m_master的后代菜单的Tools>Customize时,PFC会自动调用该事件。 

保存对数据库的修改: 

l_ 调用窗口的pfc_Save事件: 

Integer li_return 

Li_return = this.Event pfc_Save() 

当用户选择m_master的后代菜单的File>Save时,PFC会自动的调用该用户事件。 

同样对于w_master的后代窗口的CloseQuery事件当用户在提示保存窗口中选择Ye 

s时也会调用pfc_Save事件。 

将窗口定位在屏幕中间: 

1. 开启基本窗口服务: 

this.of_SetBase(True) 

2. 调用n_cst_winsrv的of_Center函数: 

this.inv_base.of_Center() 

24. Preference service 

概要 

选项服务提供了允许用户保存、恢复用户窗口设置,或者是关于注册表、INI文件 

。选项服务可以保存: 

l_ 大小 

l_ 位置 

l_ 工具栏设置 

它对应的对象是n_cst_winsrv_preference 。 

使用说明: 

使用该服务保存、恢复窗口设置: 

自动运行:如果你的w_master后代窗口开启了该服务,所有的操作将会自动执行 

。 

开启窗口选项服务: 

l_ 调用w_master的of_SetPreference函数。该函数对所有的PFC窗口都有效。因 

为w_master时所有PFC窗口的祖先。 

PFC会自动的删除所有的服务。 

指定特定的窗口选项需要恢复,调用如下的几个函数: 

l_ 根据需要调用如下的几个函数: 

of_SetToolbarItemOrder 

of_SetToolbarItemSpace 

of_SetToolbarItemVisible 

of_SetToolbars 

of_SetToolbarTitles 

of_SetWindow 

25. Sheet management service 

概要 

PFC的表单管理服务提供了一个供MDI应用程序管理多个表单的功能。当你启用该 

功能时,PFC会在WINDOW的菜单中增加如下几项: 

l_ 最小化所有的窗口 

l_ 恢复排列图表操作 

它对应的对象是n_cst_winsrv_sheetmanager 。 

使用说明: 

使用该服务管理MDI应用程序中的多个表单。 

开启表单管理服务: 

l_ 调用w_frame的of_SetSheetManager函数,该函数对w_frame的所有后代窗口都 

有效: 

this.of_SetSheetManager(TRUE) 

PFC回自动删除所有的服务。 

访问表单: 

l_ 根据需要如下的函数: 

of_GetSheetCount 

of_GetSheets 

of_GetSheetsByClass 

of_GetSheetsByTitle 

26. Status bar service 

PFC的状态栏服务可以在MDI父窗口的右下角状态栏处显示时间、内存信息。该服 

务提供的其他服务还有: 

l_ GDI、可用内存监视器 

l_ 支持进度条 

l_ 显示开发人员的文本 

有关进度条的详细说明请参考擴sing the progress bar control?

PFC的状态条服务对应的对象是n_cst_winsrv_statusbar用户自定义对象,它实际 

上是使用了一个窗口(w_statusbar)显示信息。 

你可以调用n_cst_winsrv_statusbar的函数来控制显示的项。 

在Macintosh和UNIX操作系统上:该服务不适用于这两种操作系统。 

使用说明: 

使用该服务在MDI父窗口中显示状态条信息。如果需要,你可以使用w_statusbar 

的函数修改显示的内容。 

开启状态条服务: 

1. 调用w_frame的of_SetStatusBar函数。该函数适用于所有w_frame的后代窗口 

。 

This.of_SetStatusBar(TRUE) 

PFC会自动删除所有的服务。 

2. 在w_frame的pfc_PreOpen事件中调用n_cst_winsrv_statusbar的函数指定需要 

在状态栏中显示的信息。各信息显示的从做到右顺序与其相关的函数的调用顺序 

相同。例如,下面例子内存信息显示在日期信息的左边: 

this.inv_statusbar.of_SetMem(TRUE) 

this.inv_statusbar.of_SetTimer(TRUE) 

3. 适当的时候调用n_cst_winsrv_statusbar的函数 

4 菜单服务 

概要 

PFC的菜单服务提供了菜单与菜单、菜单与窗体之间的通信功能。通时还有获取M 

DI父窗口、工具栏的信息的函数。你可以在菜单的脚本中时该服务提供的函数。 

它对应的对象是的n_cst_menu 。 

使用说明: 

你可以在非PFC的菜单中使用该服务访问框架窗口(Frame window)、与窗口通信 

。 

开启菜单服务: 

l_ 定义类型为n_cst_menu的变量: 

n_cst_menu lnv_menu 

该变量可以是菜单级的实例变量或者是菜单脚本中局部变量。你无须调用Create 

或Destroy语句,因为PFC已经将该对象定义为autoinstantiate(自动实例)。 

 

使用消息路由: 

l_ 在菜单的脚本中调用of_SendMessage函数: 

n_cst_menu lnv_menu 

Message.StringParm = 搘_emplist?

Lvn_menu.of_SendMessage(This, 損fc_Open敚?

访问MDI父窗口: 

l_ 在菜单脚本中调用函数of_GetMDIFrame访问MDI父窗口 

n_cst_menu lnv_menu 

w_frame lw_frame 

// This is an alternative to of_SendMessage. 

lnv_menu.of_GetMDIFrame(this, lw_frame) 

Message.StringParm = "w_emplist" 

lw_frame.Event pfc_Open() 

5 Resize服务 

概要 

PFC的resize服务提供了当用户改变窗口的大小、Tab页的大小时可以自动移动控 

件、改变控件大小的函数。该服务允许你当窗口、Tab页大小改变时控制其中的控 

件的移动、大小变化等。它对应的对象是n_cst_resize 。 

你可以使用n_cst_dwsrv_resize对象实现DataWindow的resize服务。 

使用说明: 

使用该服务控制窗口的大小变化。 

开启Resize服务: 

l_ 调用w_master、u_tab、u_tabpg的of_SetResize函数: 

this.of_SetResize(TRUE) 

PFC会自动的删除所有的服务。 

注册需要resize的控件: 

l_ 调用函数of_Register指定控件应该如何相应窗口、Tab页的resize 。注册时 

需要说明当发生resize时应该移动多少,大小变化的比例是多少。下面的例子使 

得DataWindow控件向下、向右扩展。 

This.inv_resize.of_Register(dw_emplist, 0, 100, 100, 100) 

设置Resize的下限: 

l_ 调用函数of_SetMinSize设置大小的下限。你可以将该代码放在窗体的Open事 

件中指定下限小于当前大小一点。 

Integer li_return 

Li_return = this.inv_resize.of_SetMinSize(this.width ?200, this.hei 

ght - 150) 

在带有表单的MDI应用程序中使用resize服务: 

l_ 采用如下方法之一: 

l_ 以表单原大小打开: 

OpenSheet(w_emp, 搘_emplist? w_frame, 0, Original!) 

l_ 如果你使用其他的枚举变量。那么在控件进行resize服务的注册之间调用函数 

of_SetOrigSize 。调用函数of_SetOrigSize时传递工作空间的宽度、高度为参数 

。 

This.inv_resize.of_SetOrigSize(1200, 1000) 

6 转换服务 

概要 

PFC的转换服务提供了数据类型转换函数。例如,你可以使用函数of_Boolean将整 

形或者字符串转换成布尔类型。它对应的对象是n_cst_conversion 。n_cst_con 

version是自动实例的,因此,它不需要Create、Destroy语句。 

使用说明: 

你可以使用该服务实现下列转换 

原数据类型 目标数据类型 

Integer or String Boolean 

Boolean、ToolbarAlignment、SQLPreviewType String 

Boolean Integer 

String ToolbarAlignment 

Button String 

Icon String 

String SQLPreviewType 

如果你想查看详细的说明请查看PFC Object Reference中的n_cst_conversion对 

象。 

声明n_cst_conversion变量 

定义n_cst_conversion成全局、实例或者局部变量。 

使用说明 变量类型 

贯穿整个应用程序 全局变量或者n_cst_appmanager的事例变量 

针对一个对象 对象的事例变量 

针对一段脚本 局部变量 

开启转换服务: 

l_ 定义类型为n_cst_conversion的变量 

n_cst_conversion inv_conversion 

因为n_cst_conversion是自动实例化,因此不需要使用Create或者Destroy语句。 

 

调用转换服务的函数: 

l_ 调用函数 

下面的例子假设inv_conversion是实例变量: 

String ls_checked 

Ls_checked = inv_conversion.of_String(cbx_confirmed.Enabled) 

MessageBox(擟onversion?擟heckBox is: ?+ ls_Checked) 

7 日期/时间服务 

概要 

PFC的日期/时间提供了许多用于计算日期、时间的函数。例如,你可以使用of_S 

econdsAfter函数计算两个时间之间的秒数。它对应的对象是n_cst_datatime 。 

对象n_cst_datatime对象是自动实例化,因此你无须使用Create或Destroy语句。 

 

使用说明: 

你可以使用日期/时间服务进行有关日期/时间的计算。该服务提供了以下函数: 

l_ 将Julian日期转换成Gregorian日期 

l_ 将秒数转换成小时 

l_ 将秒数转换成天数 

l_ 将Gregorian日期转换成Julian日期 

l_ 计算两日期之间的年数 

l_ 计算两日期之间的月份 

l_ 计算两日期之间的周数 

l_ 计算两日期之间的秒数 

l_ 计算两日期之间的毫秒 

l_ 判断日期是否有效 

l_ 判断某日是否是平日(非周日)。原文:Determine if a date falls on a 

weekday 

l_ 判断某日是否是周末 

l_ Halt processing until a specified date/time 

你可以将n_cst_datetime定义成全局变量、实例变量、局部变量。 

日期/时间函数使用说明 变量类型 

贯穿整个应用程序 全局变量或者n_cst_appmanager的实例变量 

针对一个对象 该对象的实例变量 

针对一段代码 局部变量 

开启日期/时间服务: 

l_ 定义类型为n_cst_datetime的变量 

n_cst_datetime inv_datetime 

类型n_cst_datetime是自动实例化的,因此无须使用Create或Destroy语句 

调用日期/时间服务的函数: 

l_ 直接调用函数 

下面的例子假设inv_datetime是实例变量 

Long ll_seconds,ll_days 

Ll_seconds = Long(sle_seconds.Text) 

Ll_days = inv_datetime.of_Days(ll_seconds) 

MessageBox(擠ate/Time敚琒tring(ll_seconds)+ ?seconds is equal t 

o ?+ String(ll_days) + ?days。摚?

8 文件服务 

概要 

PFC的文件服务使得你的应用程序可以具备文件管理器功能。例如,你可以使用o 

f_FileRename函数改变文件名称。文件服务支持多种操作系统,针对各种操作系 

统该服务会自动的调用相应的外部函数。它对应的对象是n_cst_filesrv 。 

使用说明: 

通过文件服务你可以使用如下操作: 

l_ Assembling a concatenated filename 。 

l_ 建立、删除目录。 

l_ 读、写、重命名、复制文件。适用于大于32765字节的文件。 

l_ 访问文件信息,包括日期、时间。 

l_ 在一个目录下创建、排序文件。 

你可以将n_cst_filesrv定义成全局、实例、局部变量。 

使用情况 变量类型 

贯穿整个应用程序 全局变量或者n_cst_appmanager的实例变量 

针对一个对象 对象的实例变量 

针对一段代码 局部变量 

由于PFC会根据特定的平台创建n_cst_filesrv的子类。因此它没有使用PB的自动 

实例化功能。你必须显示的调用Destroy语句删除该对象。 

开启文件服务: 

1. 定义类型为n_cst_filesve的变量 

n_cst_filesrv inv_filesrv 

2. 调用全局函数f_set_filesrv: 

f_SetFilesrv(inv_filesrv,TRUE) 

该函数会自动的建立对象inv_filesrv 。 

3. 使用完毕后删除对象 

Destroy inv_filesrv 

调用文件服务的函数: 

l_ 直接调用函数 

该例子调用函数of_FileRead访问文件信息。该例子假设inv_filesrv是实例变量 

: 

Integer li_return 

String ls_file[] 

li_return = inv_filesrv.of_FileRead(sle_filename.text, ls_file) 

CHOOSE CASE li_return 

CASE ? 

MessageBox("Error", "Error accessing file") 

CASE ELSE 

// File processing goes here 

END CHOOSE 

删除该服务: 

l_ 使用DESTROY语句 

DESTROY inv_filesrv 

9 INI文件服务 

概要 

PFC的INI文件服务提供了许多读、写INI文件的函数。它对应的对象是n_cst_ini 

file。 

使用说明: 

你可以使用INI文件做到如下: 

l_ 检索INI文件中的所有键 

l_ 检索INI文件中的所有段 

l_ 删除INI文件中的所有行 

l_ 删除INI文件中一行 

l_ 删除INI文件中一段 

你可以同时使用ProfileInt、ProfileString、SetProfileString访问INI文件。 

INI文件服务对大小写不敏感。 

开启INI文件服务: 

l_ 定义类型为n_cst_inifile的变量: 

n_cst_inifile inv_ini_handler 

该类型属于自动实例化,因此你无须调用Create与Destroy 。 

使用INI文件服务: 

l_ 调用n_cst_inifile的对象函数: 

String ls_keys[] 

Integer li_count, li_size 

Li_size = inv_ini_handler.of_GetKeys(gnv_app.of_GetAppINIFile(),?

CustApp敚琹s_keys) 

Lb_keys.Reset() 

For li_count = 1 to li_size 

Lb_keys.AddItem(ls_keys[li_count]) 

Next 

10 数字服务 

概要 

PFC的数字服务提供的函数使得你可以处理二进制数。例如,你可以使用of_GetB 

it函数判断一位是开还是关。 

使用说明: 

你可以使用数字服务中的函数做到: 

l_ 判断一位是开还是关 

l_ 将十进制转换成二进制 

l_ 将二进制转换成十进制 

与Window SDK共同使用该对象:Windows SDK中许多函数都使用位返回值。因此你 

需要使用函数of_GetBit 。 

你可以将n_cst_numerical定义成全局、实例、局部变量。 

使用说明 变量类型 

贯穿整个应用程序 全局变量或者n_cst_appmanager的实例变量 

针对一个对象 对象的实例的变量 

针对一段脚本 局部变量 

开启数字服务: 

l_ 定义类型为n_cst_numerical的变量 

n_cst_numerical inv_numerical 

类型n_cst_numerical自动实例化,你无须使用Create或者Destroy语句。 

调用数字服务(numerical service)函数: 

l_ 直接调用函数 

下面的例子假设inv_numerical是实例变量: 

Long ll_base10 

String ls_binary 

Ll_base10 = Long(sle_base10.text) 

Ls_binary = inv_numerical.of_Binary(ll_base10) 

MessageBox("Numerical", String(ll_base10) + " base 10 is equal to " + 

String(ll_base10) + " base 10 is equal to " + ls_binary + " in binary. 

") 

11 平台服务 

概要 

PFC的平台服务提供的函数使到你的应用程序可以使用特定平台的函数。你可以使 

用该服务实现支持多平台的应用程序,而无须在你的应用程序中加入有关平台检 

测的代码。例如,你可以调用函数of_GetFreeMemory确定现在所剩的内存大小。 

平台服务此时便会依据不同的平台调用相应的外部函数而完成工作。该服务对应 

的对象是n_cst_platform以及不同平台的相应的子类。 

打印与页面设置对话框:PFC的平台服务会根据不同的平台作相应的调整。 

使用说明: 

平台服务提供的函数有: 

l_ 确定可用内存空间 

l_ 确定可用资源空间 

l_ 确定某一字符串的高度、宽度,单位是PBUs 

你可以将n_cst_platform定义成全局变量、实例变量、局部变量 

使用说明 变量说明 

贯穿整个应用程序 全局变量、n_cst_appmanager的实例变量 

针对一个变量 对象的实例变量 

针对一段代码 局部变量 

平台服务没有使用自动实例化功能,因此你必须显示的删除n_cst_platform 。 

在Macintosh上:在Macintosh上函数of_GetTextSize无法使用。 

开启平台服务: 

1. 定义类型n_cst_platform的变量: 

n_cst_platform inv_platform 

2. 调用f_SetPlatform全局函数 

f_SetPlatform(inv_platform,TRUE) 

函数f_SetPlatform会自动建立该对象。 

调用平台服务函数: 

l_ 直接调用函数 

下面的例子调用函数of_GetFreememory在状态栏处显示可用内存的大小。 

Long ll_free_monery 

ll_free_memory = inv_platform.of_GetFreeMemory() 

gnv_app.of_GetFrame(). SetMicroHelp(擣ree memory:?+ String(ll_ 

free_memory)) 

删除服务 

l 调用 Destroy 语句 

Destroy inv_platform 

12 选择服务 

概要 

PFC提供了一个用于显示 w_selection 对话框的函数。当用户选择OK时该函数返 

回选中行的一列或者多列的值。它对应的对象是 n_cst_selection 。 

使用说明: 

你可以使用 of_Open 函数打开一个供用户选择数据的对话框,然后在由应用程序 

处理。 

共有三种版本的 of_Open 函数,每个函数的 w_selection显示信息都不一样: 

l 检索、显示 DataWindow 中的所有数据 

l 显示一部分数据。原文:W_selection displays a passed set of rows 

l 显示已保存的一部分数据。原文:W_selection displays rows that have be 

en saved as part of the passed DataWindow object 

你可以将 n_cst_selection定义成全局变量、实例变量、局部变量 

说明 变量类型 

贯穿整个应用程序 全局变量或者 n_cst_appmanager 的实例变量。 

针对一个变量 实例变量 

针对一段代码 局部变量 

开启选择服务: 

l 定义类型为 n_cst_selection 变量 

n_cst_selection inv_selection 

因为对象 n_cst_selection是自动实例化的,因此你无需调用Create 或者Dest 

roy 语句。 

使用选择服务: 

1. 定义供of_Open使用的变量 

n_cst_selection lnv_selection 

Any la_selected[] 

String ls_columsp[ 

Integer li_count 

2. 设定需要返回值的列 

ls_columns[1] = "emp_id" 

ls_columns[2] = "emp_lname" 

ls_columns[3] = "emp_fname" 

3. 调用函数of_Open显示w_selection窗口。该版本的of_Open将显示DataWindow 

中的所有数据。 

4. 访问返回的值 

FOR li_count = 1 to UpperBound(la_selected) 

lb_selected.AddItem (String(la_selected[li_count])) 

NEXT 

13 SQL语法分析服务 

概要 

PFC的SQL语法分析服务提供的函数可以让你分析你的SQL语句。他对应的对象是n 

_cst_sql 。 

使用说明: 

你可以使用SQL语法分析服务做到: 

l 由他的部分组件建立SQL语句。原文:Build a SQL statement from its comp 

onent parts 

l 分析组件中的SQL语句 

你可以将n_cst_sql定义成全局变量、实例变量、局部变量 

说明 变量类型 

贯穿整个应用程序 全局变量或n_cst_appmanager的实例变量 

针对一个对象 对象的实例变量 

针对一段代码 局部变量 

开启SQL语法分析服务: 

l 定义类型为n_cst_sql的变量 

n_cst_sql inv_sql 

由于n_cst_sql是自动实例化的,因此你无需使用Create或者Destroy语句 

To build a SQL statement from its component parts: 

l 调用of_Assemble函数 

String ls_sql 

n_cst_sqlattrib lnv_sqlattrib[] 

lnv_sqlattrib[1].s_verb = sle_verb.text 

lnv_sqlattrib[1].s_tables = sle_tables.text 

lnv_sqlattrib[1].s_columns = sle_columns.text 

lnv_sqlattrib[1].s_values = sle_values.text 

lnv_sqlattrib[1].s_where = sle_where.text 

lnv_sqlattrib[1].s_order = sle_order.text 

lnv_sqlattrib[1].s_group = sle_group.text 

lnv_sqlattrib[1].s_having = sle_having.text 

ls_sql = inv_sql.of_Assemble(lstr_sql) 

MessageBox("SQL", ls_sql) 

To parse a SQL statement into its component parts: 

l 调用函数of_Parse 

String ls_sql 

Integer li_return 

n_cst_sqlattrib lnv_sqlattrib[ ] 

li_return = inv_sql.of_Parse(mle_sql.text, lnv_sqlattrib) 

IF li_return > 0 THEN 

sle_verb.text= lnv_sqlattrib[1].s_verb 

sle_tables.text = lnv_sqlattrib[1].s_tables 

sle_columns.text = lnv_sqlattrib[1].s_columns 

sle_values.text = lnv_sqlattrib[1].s_values 

sle_where.text = lnv_sqlattrib[1].s_where 

sle_order.text = lnv_sqlattrib[1].s_order 

sle_group.text = lnv_sqlattrib[1].s_group 

sle_having.text= lnv_sqlattrib[1].s_having 

END IF 

14 字符串处理服务 

概要 

PFC的字符串服务提供的函数可以处理字符串。他对应的对象是n_cst_string。 

 

使用说明: 

你可以使用字符串服务做到: 

l 将具有定界符的字符串分割成数组。 

l 将数组转换成具有定界符的字符串。 

l 判断字符串的大小写,是否按字母排序、是否按数字、字母排序 

l 通用替代。原文:Global replacing 

l 计算字符串中数字出现的次数 

l 将字符串中的非字母除去 

l 判断一字符串是否是表达式 

l 将所有的字母都变成首字母大写 

你可以将n_cst_string定义成全局变量、实例变量、局部变量 

使用说明 变量类型 

贯穿整个应用程序 全局变量或者n_cst_appmanager的实例变量 

针对一个对象 对象的实例变量 

针对一段代码 局部变量 

开启字符串服务: 

l 定义类型为n_cst_string的变量: 

n_cst_string inv_string 

由于对象n_cst_string是自动实例化的,因此你无需调用Create或者Destroy语 

句 

调用字符串处理函数: 

l 直接调用函数 

这段代码来自n_cst_dwsrv_report的of_AddText函数。他调用函数of_ParseRoA 

rray as_text字符串转换成一个数组,其中lnv_string是局部变量 

n_cst_string lnv_string 

Integer li_newlines 

String ls_line[ ] 

... 

li_newlines = lnv_string.of_ParseToArray (as_text, "~r~n", ls_line) 

 

15 元类服务 

概要 

元类服务的函数提供了其他对象中的函数、事件、变量的信息。他对应的对象是 

n_cst_metaclass 。 

使用说明: 

元类服务最有用也是最常用的就是在调用对象函数、事件之前先判断它们是否存 

在。 

使用元类服务: 

1. 定义类型为n_cst_metaclass的变量: 

boolean lb_defined 

n_cst_metaclass lnv_metaclass 

classdefinition lcd_obj 

String ls_args[ ] 

Integer li_rc 

由于对象n_cst_metaclass是自动实例化的,因此你无需使用Create或者Destro 

y函数。 

2. 调用n_cst_metaclass函数 

lcd_obj = FindClassDefinition("w_sheet") 

lb_defined = lnv_metaclass.of_isFunctionDefined(lcd_obj,"of_Validatio 

n", ls_args) 

If lb_defined Then 

// Qualify with instance of w_sheet descendant. 

li_rc = w_sheet.Function Dynamic of_Validation () 

If li_rc < 0 Then 

Return -1 

End If 

16 工作逻辑单元服务 

概要 

工作逻辑单元提供了具有自动保存数据功能的对象(简称自更新对象)。一个具 

有自动保存数据功能的对象实际上是提供了一整套函数接口(self-updating ob 

ject API)供n_cst_luw对象执行保存操作时调用。这些函数再调用那些需要保存 

数据的对象的事件。工作逻辑单元服务自动的调用这些函数,并且作为默认保存 

操作的一部分。PFC有好几个具有自动保存数据功能的对象,它们是: 

U_dw 

N_ds 

U_lvs 

U_tab 

U_tvs 

U_base 

W_master 

查看这些对象的API的执行结果即可证实。 

默认情况下,w_master的pfc_Save会使用工作逻辑单元保存所有具有自动保存数 

据功能的对象。详细情况查看擴sing the pfc_Save process?

自更新对象的实现: 

工作逻辑单元更新所有的可更新的自更新对象。 

注意:大部分的自更新对象默认情况下是不可更新的。为了确保向后兼容性,u_ 

dw是唯一的默认可更新的。 

下面是所有的自更新对象的对外接口(API) 

函数 用途 

of_AcceptText 调用pfc_AcceptText事件,该事件再调用AcceptText函数 

of_UpdatesPending 调用pfc_UpdatesPending事件,该事件会判断该对象是否已 

经保存数据了。 

of_Validation 调用pfc_Validation事件,该事件会对数据进行有效性检验。 

of_UpdatePrep 调用pfc_UpdatePrep事件,该事件将会准备好那些将要更新的对 

象。 

of_Update 调用事件pfc_Update,该事件会更新数据库。 

of_PostUpdate 调用事件pfc_PostUpdate,该事件将会异步的执行更新操作。 

 

 

你可以使用Browser查看这些函数、事件的信息。 

编写你自己的自更新对象: 

要编写自己的自更新对象只需调用上述的函数和必须使用一组引用类型数组指向 

你的对象作为n_cst_luw中的某些函数的参数。 

扩展保存操作 

默认情况下,w_master的pfc_Save会保存其中的所有被修改的DataWindow。你可 

以按如下扩展该操作: 

l 其他的自更新对象:你可以在对象的构造事件中调用函数of_SetUpdateable将 

其他的自更新对象设置成可更新的。下面的代码来自u_lvs。 

this.of_SetUpdateable(TRUE) 

l 现在,工作逻辑单元将会将保存u_lvs的数据操作作为默认的保存操作 

l DataStore:你可以将一个或多个DataStore通过调用函数of_SetUpdateObject 

s列为需要更新的对象: 

PowerObject lpo_objs[] 

Integer li_count 

lpo_objs = this.control 

li_count = UpperBound(lpo_objs) 

li_count ++ 

lpo_objs[li_count] = ids_data 

this.of_SetUpdateObjects(lpo_objs) 

l 附加的窗口:你可以调用w_master的of_SetUpdateObjects将一个或者多个窗口 

列为需要更新的对象。 

PowerObject lpo_objs[ ] 

Integer li_count 

lpo_objs = this.control 

li_count = UpperBound(lpo_objs) 

li_count++ 

// Update w_other as well as this window 

lpo_objs[li_count] = w_other 

this.of_SetUpdateObjects(lpo_objs) 

 
使用PFC窗口和菜单


关于本章 本章解释如何使用 PFC窗口和菜单.
使用 PFC窗口
PFC提供了一个基类祖先窗口(w_master)并为每种标准窗口类型提供了祖先窗口.
每个这样的窗口都继承自w_master:
PFC窗口包含实例变量、事件和提供高级功能并可与其它PFC对象通信的函数。
窗口的基本用法
开发应用程序,典型地:
创建基类和继承的窗口
启动窗口服务
从菜单选项中打开窗口
使用PFC窗口进行开发
当你开始一个应用程序的开发,你应考察需要的功能以决定哪一个实例变量、事件以及函数应归入祖先窗口.
你定义特定应用程序祖先的不同行为取决于你的扩充策略:
策略
方法
创建中间扩展层 应用程序的祖先窗口使用PFC扩展层窗口.
例如,在 w_master定义共用的扩展和在 w_sheet定义工作表窗口扩展.
于是你的应用程序窗口从PFC扩展层窗口继承
典型地,因为在MDI应用程序中仅有一个框架窗口,你可以修改和使用w_frame代替继承的窗口


使用存在的PFC扩展层 你可以通过继承PFC扩展层窗口来创建一组应用程序的祖先窗口.
应用程序窗口于是继承自应用程序专有的祖先窗口 通过继承w_frame来创建框架窗口
启动窗口服务
PFC提供各种窗口服务是你能用来加入产品化应用程序特性.
许多这样的服务要求极少甚至不须编码.
窗口服务有:
基本窗口服务
偏好服务
状态栏服务 (限于框架窗口)
工作表管理服务 (限于框架窗口)
调整大小服务 (也适合属性页、属性页页面以及自定义的可视用户对象)
使用窗口服务:
1为窗口确定适当的窗口服务.
2使用of_Setservicename函数启动适当的窗口服务(本例子从窗口的 pfc_PreOpen事件启动偏好和调整大小服务):
this.of_SetPreference(TRUE)
this.of_SetResize(TRUE)
3按需要调用其它函数以初始化服务 (本例子为菜单项和工具栏启动偏好服务并为DataWindow务和两个按钮提供启动调整大小服务):
this.inv_preference.of_SetMenuItems(TRUE) this.inv_preference.of_SetToolbars(TRUE)
this.inv_resize.of_Register &
(dw_emplist,0,0,100,100) this.inv_resize.of_Register &
(cb_ok,0,100,0,0)
this.inv_resize.of_Register &
(cb_cancel,0,100,0,0)
参阅 有关每种窗口服务的具体用法,参见 "窗口服务" .
开启PFC窗口
在许多应用程序,用户通过选择菜单项打开窗口.
你能使用PFC消息路由器帮助以可变的和固定的方法处理本过程.
参阅 参见 "消息路由器" .
从菜单项打开PFC窗口:
1在该菜单项,将Message.StringParm设为窗口名并调用菜单服务of_SendMessage函数:
n_cst_menu lnv_menu Message.StringParm = "w_emplist"
lnv_menu.of_SendMessage(this, "pfc_Open")
2在框架窗口的 pfc_Open事件,添加代码到存取消息对象并打开请求的窗口:
String ls_window
w_sheet lw_sheet
ls_window = Message.StringParm
OpenSheet(lw_sheet, ls_window,this, 4,Original!)
其他选项 打开 PFC窗口的其它 方法.
这些包含直接从菜单选项打开窗口,扩充消息对象以包含传递的参数,以及通过定义框架窗口的附加用户事件打开窗口.
使用响应式窗口
典型地,你使用 w_response ( PFC响应式窗口)创建显示并收集数据、设置或参数选择的响应式窗口。
w_response的另一个用途 你还能使用 w_response创建响应式窗口以取代 MessageBox.
但是通常最好使用 w_message对话框 (出错信息服务部分).
W_response包含三个处理用户动作的用户事件,你可以在其中添加代码:
事件 使用它 更多信息
pfc_Apply 处理窗口内容,保持窗口打开 当前许多的应用程序包含Apply按钮来执行本功能
pfc_Cancel 忽略窗口内容并关闭窗口 你从赋与Cancel特性的按钮调用本事件
pfc_Default 处理窗口内容并关闭窗口 你从赋与Default特性的按钮调用本事件
使用w_response事件:
1创建一个继承自w_response的窗口.
2添加控件以处理显示和用户输入.
使用PFC标准可视用户对象 你能使用同PFC一起使用PowerBuilder窗口控件.
但是最好使用继承自PFC标准可视用户对象 (u_dw, u_lb, u_sle, u_cb,等等)的控件.
3添加代码支持这些控件.
例如,添加代码到窗口的pfc_PreOpen事件,存取在 INI文件值以显示在SingleLineEdit控件上.
4按需要在pfc_Apply、pfc_Cancel和pfc_Default事件中添加代码。.
例如, 可以在pfc_Default事件中保存窗口内容到INI文件并关闭窗口:
ls_String ls_temp ls_temp = trim(sle_base.Text)
SetProfileString("eisapp.ini",&
"Files","base",ls_temp)
ls_temp=trim(sle_x1.Text)
SetProfileString("eisapp.ini",&
"Files","extra1",ls_temp) ls_temp = trim(sle_x2.Text)
SetProfileString("eisapp.ini",&
"Files", "extra2", ls_temp)
Close(this)
5添加按钮以触发相应事件.
例如,OK按钮应调用 pfc_Default事件:
parent.Event pfc_Default()
使用 pfc_Apply
到最大化 reusability,把处理放置于pfc_Apply内和调用 pfc_Apply从 pfc_Default.
使用 pfc_Save过程
w_master pfc_Save事件为窗口中所有PFC和非PFC的 DataWindows自动确认并保存改动.
因为 pfc_Save调用许多其它事件, 保存大多数工作到工作服务的逻辑单元,你应该将它看作一个过程而不是作为一个单一的事件.
工作服务的逻辑单元 pfc_Save使用你通过调用of_SetLogicalUnitOfWork函数启动的工作服务逻辑单元,.
如果你启动工作服务的逻辑单元, w_master按需要自动启动它.
虽然有许多方法保存数据,最好使用 pfc_Save事件保存改动.
除了简单地调用w_master pfc_Save事件和检查返回值之外,你能通过定制和扩充被pfc_Save过程调用的事件来对更新过程进行完全控制.
你能:
为其它自更新对象保存改动(包括n_ds DataStore、u_tvs TreeView和u_lvs Listview)
为其它控件保存改动
控制哪个对象被更新和指定它们被更新的顺序
为其它窗口的对象保存改动
自更新对象 PFC将更新机能与某些对象结合,称作自更新对象 .
你当调用 w_master pfc_Save事件,它自动更新窗口中的所有自更新对象.
所有 DataWindows都是自更新的.
你必须为n_ds、u_lvs、u_tab和u_tvs明确地启动自更新功能.
并且你能为任何可视的或非可视的控件添加自更新功能.
参阅 有关自更新对象的详细信息,参见 "工作服务的逻辑部件" .
pfc_Save过程
本是 w_master pfc_Save过程:
Pfc_Save事件
这些是 pfc_Save过程中的事件:
事件 用途 注解
pfc_AcceptText 为窗口中的所有自更新对象执行 AcceptText功能 被w_master of_AcceptText函数调用
pfc_UpdatesPending 确定哪一个自更新对象有未决的更新 被w_master of_UpdatesPending函数调用
pfc_Validation 在所有包含未决更新的自更新对象上执行合法性检验 被of_Validation函数调用 为非PFC DataWindows,编写一个返回值类型为Integer或Long的用户事件ue_validation,大于或等于0表示成功
pfc_UpdatePrep 空的用户事件,你可以随意添加准备更新的处理代码 如果窗口本身是自更新对象则扩充本事件
pfc_PreUpdate 空的事件,你可以添加附加的合法性检验代码 返回 1为成功;
返回别的值则终止 pfc_Save过程
pfc_BeginTran 空的事件,如果你的 DBMS需要,你可以添加代码开始数据库事务。 返回 1为成功;
返回别的值则终止 pfc_Save过程
pfc_Update 为所有有改动的自更新对象执行数据库更新 你能扩充本事件更新非自更新控件
返回 1为成功;
返回 -1为失败.
如果返回 -1,同样通过调用 of_SetDBErrorMsg函数产生一个出错信息.
pfc_DBError事件将显示本信息
pfc_EndTran 空的事件,你用来添加提交或回滚数据库事务的代码 提交或回滚基于传递的参数 虽然你能在其它 地方使用COMMIT和ROLLBACK语句,但最好在此处使用它们
pfc_DBError 若有更新失败的话,本事件显示有关信息 如果Error服务被启动,本事件调用 of_Message函数;
否则,它调用 PowerScript MessageBox函数   PFC延迟显示出错信息 (相对于pfc_Update)以便你能在显示出错消息框前在 pfc_EndTran事件中回滚改动
pfc_PostUpdate 为所有已更新对象复位更新标志,如下 如果你扩充了pfc_Save处理以更新其它控件,扩充本事件复位更新标志
Pfc_Save返回值
Pfc_Save返回如下值 :
返回值含义注解
1成功
0没有未决的更新
-1 AcceptText错误 pfc_Save过程中断
-2错误在 pfc_UpdatesPending pfc_Save过程中断
-3合法性错误 pfc_Save过程中断
-4错误在 pfc_PreUpdate pfc_Save过程中断
-5错误在 pfc_BeginTran pfc_Save过程中断
-6错误在 pfc_Update  pfc_EndTran和 pfc_DBError事件完成;
pfc_PostUpdate未被执行
-7错误在 pfc_EndTran pfc_PostUpdate未被执行
-8错误在 pfc_PostUpdate
-9错误在 pfc_UpdatePrep pfc_Save过程中断
添加代码扩充 pfc_Save事件
你能定制和扩充 pfc_Save过程.
例如,你能:
添加代码到 pfc_EndTran事件以提交或回滚事务
创建ue_Validation用户事件并编写代码,以在非PFC DataWindows执行合法性检验
扩充 pfc_Save过程以包含其它类型的窗口控件
添加代码到 pfc_EndTran事件:
加代码到 pfc_EndTran事件,检验ai_update_results参数并按需要为每个可以被更新事务对象提交或回滚改动:
Integer li_return IF ai_update_results = 1 THEN
li_return = SQLCA.of_Commit()
ELSE
li_return = SQLCA.of_Rollback()
END IF
IF li_return = 0 THEN
Return 1
ELSE
Return -1
END IF
启动自更新对象
默认的, DataWindows是唯一可更新的自更新对象
所有其它 (n_ds、u_lvs、u_tvs、u_tab,以及任何用户自定义的可视用户对象)是不可更新的,必须被显式地启动.
启动自更新对象:
1调用自更新对象的 of_SetUpdatable函数:
ids_data.of_SetUpdateable(TRUE) lv_1.of_SetUpdateable(TRUE) tv_1.of_SetUpdateable(TRUE)
2 (仅DataStores)添加 n_ds-based DataStore到将被更新的控件的列表中:
PowerObject lpo_objs[] Integer li_count // this = window
lpo_objs = this.control
li_count = UpperBound(lpo_objs)
lpo_objs[li_count + 1] = ids_data
this.of_SetUpdateObjects(lpo_objs)
启动一个单次更新
PFC允许你指定一组控件并一次更新它们.
执行一个单次更新:
1指定被更新的控件:
PowerObject lpo_objs[ ]
Integer li_return
lpo_objs[1] = lv_1
lpo_objs[2] = dw_1
lv_1.of_SetUpdateable(TRUE)
2通过调用 pfc_SaveObjects事件执行单次保存:
// this = window
li_return = this.Event
pfc_SaveObjects(lpo_objs)
// Check for return codes 1 to -8 ...
使用PFC菜单
PFC通过函数、菜单项以及在m_master事件中的代码来实现菜单服务.
M_master包含:
调用消息路由器的函数
通过使用消息路由器执行所需功能的菜单项
从扩充层菜单继承 当使用菜单时,总是从m_前缀的菜单继承(不从pfc_前缀的菜单继承).
当你升级 PFC版本时Pfc_前缀对象受改动的影响.
两个菜单继承策略
你能使用PFC的菜单或写你自己的.
使用PFC菜单
你的应用程序能使用 PFC菜单作为它的菜单的基础.
在大多数情况下,你使用m_master作为你的应用程序工作表窗口菜单的祖先并使用m_frame作为框架菜单.
你添加所有应用程序的工具栏项和菜单项到 m_master.
让工作表菜从 m_master单继承,并且按需要的启动和禁止菜单项.
在 m_frame按需要禁止工具栏项和菜单项.
创建你的自己菜单
选择性的,你能实现和m_master分开的你自己的定制菜单.
如果你这样做,考虑使用菜单服务 of_SendMessage菜单函数实现 PFC消息路由器功能.
扩充 PFC菜单
如果你使用 PFC菜单,你将需要修改它们或它们的子孙提供应用程序特定的处理.
当你添加新工具栏项和菜单项, PFC使用 PowerBuilder Shift Over/Down归因于控件在哪里菜单项被地方:
在本菜单 PowerBuilder插入新项
菜单栏位于工具和窗口
文件菜单在删除上方
编辑菜单在更新上方连接
查看菜单在标尺上方
工具菜单在定制上方工具栏
窗口菜单在撤消下面
帮助菜单在关于上方
为信息为完成有关信息 Shift高于/往下特性,看见 PowerBuilder使用手册 .
创造你的自己菜单
PFC菜单提供菜单项覆盖最事件在 PFC控件.
你的应用程序可能更多专用的要求那辩护创造菜单从头做起为使用和你的 PFC窗口.
创造菜单
使用菜单画板创建你的菜单.
加仅仅项必需的为你的应用程序,定义快捷键,加速键,并且工具栏位图作为需要.
创造扩充级如果你是对象管理人创造菜单为使用通过多重的开发者和应用程序,考虑创造祖先菜单 (和 PowerScript和 PFC代码)并且空的扩充级菜单为使用通过 d
通话窗口
取决于你的需要,你能使用或者你的自己菜单-窗口通信方法或 PFC消息路由器.
当使用消息路由器,它最好到使用菜单服务 of_SendMessage函数到调用事件在窗口.
每个菜单选项调用 of_SendMessage,通过事件的名字到调用.
例如,单击事件为编辑>剪切菜单选项调用 of_SendMessage如下:
n_cst_menu lnv_menu
lnv_menu.of_SendMessage(this, "pfc_Cut")
有二菜单项那要求专用的注意:
文件>退出调用应用程序管理器 pfc_Exit事件:
gnv_app.Event pfc_Exit()
MRU菜单项 (文件菜单)在调用前复制菜单选项正文到 Message.StringParm of_SendMessage:
n_cst_menu lnv_menu
Message.StringParm = this.Text
lnv_menu.of_SendMessage(this, "pfc_MRUClicked")
复制和粘贴你能保存时间通过复制和粘贴菜单选项手写体从 pfc_m_master.
启动地址项在窗口菜单
当窗口工作表管理器服务被启动, PFC菜单自动启动和禁止窗口菜单项作为适当的.
如果你在使用工作表管理器服务和想要那机能在你的菜单,复制代码从 pfc_m_master窗口菜单项选定的事件.
使用标准的菜单选项
M_master包含菜单项那调用用户事件在对应窗口.
使用菜单项如下:
如果菜单选项不适用于窗口制作它看不见的.
如果菜单选项应用到窗口评论 PowerScript代码在对应用户事件为联合的窗口, DataWindow,或可视的控件.
每 m_master菜单项触发某一个事件.
某些这样的用户事件空的;
你必须加适当的 PowerScript代码执行应用程序-专用的处理.
为信息如需要更多信息在 PFC用户事件,看见 PFC对象引用 .
文件菜单
菜单选项事件触发对象(s)包含用户事件
新建 pfc_New w_master
打开 pfc_Open u_rte, w_master
结束 pfc_Close w_master
保存 pfc_Save u_rte, w_master
保存为 pfc_SaveAs u_rte, w_master
打印 pfc_Print u_dw, u_rte, w_master
打印预览 pfc_PrintPreview u_dw, u_rte
页面设置 pfc_PageSetup u_dw, w_master
打印立即 pfc_PrintImmediate u_dw, u_rte, w_master
删除空的菜单选项加你的拥有事件或函数
属性空的菜单选项加你的拥有事件或函数
退出 pfc_exit N_cst_appmanager
编辑菜单
菜单选项事件触发对象(s)包含用户事件
撤消 pfc_Undo U_dw, u_em, u_mle, u_rte,并且 u_sle
剪切 pfc_Cut U_ddlb, u_ddplb, u_dw, u_em, u_mle, u_oc, u_rte,并且 u_sle
复制 pfc_Copy U_ddlb, u_ddplb, u_dw, u_em, u_mle, u_oc, u_rte,并且 u_sle
粘贴 pfc_Paste U_ddlb, u_ddplb, u_dw, u_em, u_mle, u_oc, u_rte,并且 u_sle
选择性粘贴 pfc_PasteSpecial U_oc
清除 pfc_Clear U_ddlb, u_ddplb, u_dw, u_em, u_mle, u_oc, u_rte,并且 u_sle
全部选定 pfc_SelectAll U_ddlb, u_ddplb, u_dw, u_em, u_mle, u_rte,并且 u_sle
查找 pfc_Find DlgU_dw和 u_rte
替换 pfc_ReplaceDlg U_dw和 u_rte
更新连接 pfc_UpdateLinks U_oc
对象>编辑 pfc_EditObject U_oc
对象>打开 pfc_OpenObject U_oc
查看菜单
菜单选项动作对象包含用户事件
标尺 pfc_Ruler U_dw和 u_rte
大图标空的菜单选项.
加逻辑到 u_lvs切换到大图标查看
小图标空的菜单选项加逻辑到 u_lvs切换到小的图标查看;
调用从本菜单选项
表格空的菜单选项加逻辑到 u_lvs切换到表格查看;
调用从本菜单选项
详细空的菜单选项加逻辑到 u_lvs切换到详述查看;
调用从本菜单选项
重排图标>通过空的菜单选项加逻辑到 u_lvs重排图标通过一些公用属性;
调用从本菜单选项
重排图标>自动排列空的菜单选项加逻辑到 u_lvs重排图标;
调用从本菜单选项
第一 pfc_FirstPage U_dw和 u_rte
下一个 pfc_NextPage U_dw和 u_rte
在pfc_PreviousPage之前 U_dw和 u_rte
上一 pfc_LastPage U_dw和 u_rte
分类 pfc_SortDlg U_dw
过滤器 pfc_FilterDlg U_dw
缩放 pfc_Zoom U_dw
插入菜单
菜单选项事件触发对象(s)包含用户事件
文件 pfc_InsertFile U_rte
PICT格式标准 pfc_InsertPicture U_rte
对象 pfc_InsertObject U_oc
工具菜单
菜单选项事件触发对象(s)包含用户事件
定制工具栏 pfc_Toolbars W_frame
窗口菜单
菜单选项动作对象包含用户事件
串联 pfc_Cascade W_frame
水平平铺 pfc_TileHorizontal W_frame
垂直排列 pfc_TileVertical W_frame
层 pfc_Layer W_frame
全部最小化窗口 pfc_MinimizeAll W_frame
撤消 pfc_UndoArrange W_frame
帮助菜单
菜单选项事件触发对象(s)包含用户事件
帮助主题 pfc_Help W_master
关于 of_About N_cst_appmanager
使用弹出菜单
PFC也提供弹出菜单为使用通过你的应用程序和 PFC服务:
弹出菜单它当显示如何禁止扩充容量
M_edit显示你按当右翼-鼠标器按钮高于下列之一可编辑的可视的控件:
U_ddlb U_ddplb U_em U_mle U_rte U_sle禁止本机能,放 ib_rmbmenu例子变量错误在控件的构造函数 eventYou能扩充 m_edit加应用程序-专用的右鼠标器按钮机能
M_dw显示你按当右翼 u_dw的鼠标器按钮 -基本 DataWindow禁止本机能,放 ib_rmbmenu例子变量错误在 u_dw构造函数事件你能扩充 m_dw加应用程序-专用的右
M_oc显示你按当右翼 u_oc的鼠标器按钮 -基本 OLE容器禁止本机能,放 ib_rmbmenu例子变量错误在 u_oc构造函数事件你能扩充 m_oc加应用程序-专用的装备
M_lvs显示你按当右翼 u_lvs的鼠标器按钮 -基本 ListView禁止本机能,放 ib_rmbmenu例子变量错误在 u_lvs构造函数事件你能扩充 m_lvs加应用程序-专用的righ
M_tvs显示你按当右翼 u_tvs的鼠标器按钮 -基本 TreeView禁止本机能,放 ib_rmbmenu例子变量错误在 u_tvs构造函数事件你能扩充 m_tvs加应用程序-专用的righ
PFC工具

 

关于本章

本章描述PFC工具和如何使用它们。

 

DataWindow属性窗口

DataWindow属性窗口允许你:

l          l          选择允许和禁止 DataWindow服务

l          l          查看选定服务的PFC语法

l          l          交互式地访问和修改 DataWindow属性,包括:

DataWindow缓冲区

行和列状态

统计

DataWindow对象中所有对象的属性

 

DataWindow属性窗口属性页

DataWindow属性窗口有三个属性页:

l          l          Services 显示 DataWindow的服务列表。

选择一项服务并按需要点击Enable或Disable。点击Properties以显示当前选定服务的信息:


     

l         l         Buffers 点击鼠标器右键显示弹出菜单,允许你对行进行如下操作:


 

l          l          Status flags 按需要改变DataWindow状态标志。

单选框Assist Status Change允许你执行两状态变化成为一步:


 

服务对话框属性页

每个服务显示它拥有的一套属性页以显示它的属性。本例子显示排序服务的属性页:

l         l         General 显示选定服务的有关信息:


 

Syntax 显示用于选定服务的PFC语法:


 

用法

使用DataWindow属性窗口调试和测试你的应用程序和 DataWindow服务的用途。

显示DataWindow属性窗口:

1 由调用u_dw of_SetProperty函数允许DataWindow属性服务:

this.of_SetProperty(TRUE)

2 当显示DataWindow后,右击并选择 DataWindow Properties,以显示出DataWindow属性窗口。

SQL间谍

SQL间谍工具自动为DataWindows和EXEC IMMEDIATE语句捕获并保存SQL。

你能使用 SQL间谍显示和随意地修改 DataWindow的 SQL语句,并把本地SQL记入日志。

修改 SQL 如果你在使用 ODBC数据源,你必须将连接字符串中的DisableBind置为1。

SQL间谍将SQL语句记入日志文件,你能随意地在弹出窗口中显示。

用法

使用SQL间谍,你可以调用函数以启动间谍工具,指定日志文件,和控制 w_sqlspy窗口的显示。

你还能调用函数到将本地 SQL记入日志。

虽然你能从应用程序以内的任何地方调用SQL间谍功能,但一般说来,你应该在应用程序管理器的pfc_Open事件中初始化SQL间谍。

启动SQL间谍:

1 通过调用 n_cst_appmanager of_SetDebug函数启动调试服务:

this.of_SetDebug(TRUE)

2通过调用 n_cst_debug of_SetSQLSpy函数启动 SQL间谍:

this.inv_debug.of_SetSQLSpy(TRUE)

3 (可选项)通过调用 n_cst_sqlspy of_SetLogFile函数指定日志文件:

this.inv_debug.inv_sqlspy.of_SetLogFile &

("c:\PB6\adk\pfc\appdbug.log")

显示 w_sqlspy弹出窗口:

调用 n_cst_sqlspy of_OpenSQLSpy函数:

gnv_app.inv_debug.inv_sqlspy.of_OpenSQLSpy(TRUE)

w_sqlspy弹出窗口显示日志文件中最近记载的项目:


 

在DataWindow提交到数据库以前w_sqlspyinspect对话框允许你查看和随意地修改SQL语句。

显示 w_sqlspyinspect对话框:

调用 n_cst_sqlspy of_SetBatchMode(FALSE)函数:

gnv_app.inv_debug.inv_sqlspy.of_SetBatchMode &

(FALSE)

使用 对话框w_sqlspyinspect:

1更新数据库、插入、删除或修改行。对话框w_sqlinspect显示:


 

 

2检查SQL语句,随意修改数值。

3单击适当的命令按钮:

Step 更新当前的行并显示将被更新的下一行的信息

Resume 更新当前的行并更新所有剩余的行;

禁止SQL间谍检查功能

Cancel 不更新当前的行并显示将被更新的下一行

Cancel All 不更新所有剩余的行

手动地将SQL语句记入日志 :

使用n_cst_sqlspy of_SQLSyntax函数,把将被记入日志的 SQL语句传递给它:

String ls_sql ls_sql = "SELECT * FROM employee;"

gnv_app.inv_debug.inv_sqlspy.of_SQLSyntax &

("Native SQL", String(Now()) + ": " + &

String(Today()) + ": " + ls_sql)

安全性

PFC提供需要在应用程序中进行少量编码的数据库驱动的安全系统。

它允许你在安全数据库中记载如下信息:

窗口控制

DataWindow列

用户对象

菜单项

然后创建用户和组的真值表,控制这些项的访问权限。

在执行时,PFC按安全数据库中的记载选择允许、禁止或隐藏被保护的项。

PFC安全系统包括:

安全管理工具 允许你定义用户、组、被保护的项和用户访问权限。

安全扫描器 扫描用户自定义对象以搜所有集能被保护的项目的信息。

安全数据库包含有关用户、组、被保护的项目和用户对那些被保护项的访问权限的信息。

以本地数据库交付 PFC提供一个本地数据库以保存安全性信息。

无论如何,当你实施安全性时,你将想使用服务器数据库。

由异常提供安全性

PFC安全特性由异常提供。

默认地,安全系统使用对象的当前设置。

这意味着PFC仅修改安全数据库中明确指定的设置。

过程

安全管理工具是PowerBuilder应用程序,你用来:

定义用户和组

运行安全性扫描器

为对象和控件定义安全性

关联用户和组与对象和控件

在你的应用程序中,添加如下代码以实现安全性:

对象 添加代码

应用程序管理器 调用 n_cst_appmanager of_SetSecurity函数以启动安全性服务,n_cst_security

应用程序管理器或框架窗口 建立事务对象,连接到安全性数据库,并且调用 n_cst_security of_InitSecurity函数

of_InitSecurity函数允许你为用户设置缺省组。

如果用户没有设定为其它组,安全系统将使用缺省组。

要求安全性的窗口 在窗口Open事件中调用 of_SetSecurity函数

如需要有关在应用程序中实现安全性的更多信息,参看 "在应用程序中实现安全性" 。

定义用户和组

概述

要使用 PFC安全性,你必须定义用户和组。

用户可以是零个或多个组的成员;

用户设置总是优先于组设置。

用法

你使用安全管理工具定义用户和组,并关联用户和组。

运行安全管理工具

运行安全管理工具,启动 PowerBuilder,打开应用程序画板,在 pfc\security目录选择 PFCSECAD.PBL,将 PFC PBLs加到库列表,并运行应用程序。

如果连接到 PFC.DB数据库出现问题,检查 PFCSECAD.INI文件和你的工作站的 ODBC设置。

如果你已将PFC安全性表从PFC.DB移动到其它的数据库,你必须更新PFCSECAD.INI文件的Database段以使用正确的数据库连接参数。

定义用户:

1从菜单栏选择File>User/Groups。

User/Groups管理窗口显示:


 

 

2在Users列右击并选择Add Item。

Add User对话框显示:


 

3输入用户名和描述。

用户名必须符合应用程序在执行时能存取的用户ID。

4单击OK。

5按需要继续添加用户。

6从菜单栏File>Save。

定义组:

1在Groups列右击并选择Add Group。Add Group对话框显示:


 

2输入组名、描述和优先权。

零是最高的优先权;

无论如何,用户设置优先于组设置。

3单击OK。

4按需要继续添加组。

5从菜单栏选择File>Save。

关联用户和组:

拖放用户到组上。

从组中删除用户:

1在用户上右击并选择Delete Item。从组中删除用户对话框显示。

2单击OK。

3从菜单栏选择File>Save。

修改先前定义的用户或组:

1在项目上右击并选择Edit Item。编辑用户或编辑组对话框显示。

2按需要修改信息。

3单击OK。

4从菜单栏选择File>Save。

运行安全性扫描器

安全性扫描器在应用程序中检查所有窗口、数据窗口、菜单以及用户对象。

它保存如下信息到PFC数据库:

窗口

窗口控件

对于DataWindow控件,有关关联在DataWindow对象上的列信息

菜单项

用户对象和属性页控件;

收集有关定义在用户对象或属性页上所有控件的信息

用法

你能从PowerBuilder运行安全性扫描器或者创建安全性扫描器可执行版本并从安全管理工具中运行它。

从 PowerBuilder运行安全性扫描器:

1启动 PowerBuilder。

2打开应用程序画板。

3选择 PFCSECSC.PBL并选定pfcsecurity_scanner应用程序。

4运行应用程序。

如果在连接时遇到困难 如果连接到PFC.DB数据库出现问题,检查 PFCSECAD.INI文件和你的工作站的 ODBC设定。

创建安全性扫描器的可执行版本:

1复制 PFCAPSRV.PBL文件到安全性目录。

2打开应用程序画板。

3打开PFCSECSC.PBL并选择 pfcsecurity_scanner应用程序。

4关闭应用程序画板。

5打开 Project 画板。

6指定可执行文件名 (PFCSECSC.EXE)及资源文件名 (PFCSECSC.PBR)。

7从菜单栏选择 Design>Build Project。

单独的可执行文件 因为扫描器应用程序会复位它的库搜索路径,安全性扫描器必须被创建为没有PBDs的单独可执行文件。

8编译过程完成后,关闭Project画板。

9使可执行文件能被找到:

Windows 95和Windows NT 添加pfcsecsc.exe文件的目录 到AUTOEXEC.BAT的PATH语句中。

并确保路径中包含PowerBuilder执行时DLLs的目录 (如 PBVM60.DLL)

Windows 95和Windows NT 

为 pfcsecsc.exe在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Current Version\App Paths添加项目。

本项目必须包含关键字Path(字符串),值为包含 PowerBuilder运行时DLLs的目录

UNIX 将pfcsecsc.exe的目录添加到PATH环境变量中。

同时确保LD_LIBRARY_PATH环境变量包含 PowerBuilder执行时DLLs的目录。

从内部安全管理工具运行安全性扫描器:

1从菜单栏选择File>Scan Application。

选择应用程序对话框显示出定义在pb.ini文件Application段中的应用程序列表:


 

2选择被扫描的应用程序并单击Select。选择被扫描的对象对话框显示:


 

 

3按CTRL+单击或SHIFT+单击选择被扫描的对象。

选择对象 为了使安全性数据库最小,不要选择你不准备实施安全性的对象。

4单击Scan。

5当扫描完成,单击Exit。

定制启动了安全性的控件:

1从安全管理工具菜单栏中选择File>Templates。模板管理窗口显示出来:


 

2在你刚才扫描应用程序上双击。

一个窗口列表显示出来。

3在窗口之一上双击 。

一个控件列表显示出来:


 

4按需要修改描述。

在本窗口修改描述能在将用户和组与窗口、窗口控件以及菜单项关联起来时使一切显得更清楚明了。

5在你不准备实施安全性的项目上右击并选择Delete以删除该项。

删除没必要的项以减少安全性数据库的大小,从而提高性能。

6完成后,从菜单栏选择File>Save。

7在实施安全性的所有对象上继续本过程。

为用户和组定义安全性规则

运行扫描器记录了对象和控件并选择性地删除了不需要安全性的项目之后,你可以通过关联用户和组与对象和控件定义安全性规则。

用法

对于每个用户和组,你可以允许或禁止他们访问窗口控件、 DataWindow列、用户对象以及有关被保护的对象的菜单项。

用户可以属于零个或多个组。

用户设置总是优先于组设置。

如果没有用户设置,那么具有最高优先权的组设置将被使用 (0是最高优先权)。

为用户或组定义安全性规则:

1从菜单栏选择File>Users/Objects。

用户/对象管理窗口显示:


 

2点击用户下拉列表框并选择一个将要设置安全性的用户。

3双击包含被保护对象的应用程序。

4选择所有的单选按钮 (如果它尚未被选定)。

你现在已准备好去设置安全性项目了。


 

5对于被保护的项,使用状态下拉列表框指定Enable、Disabled、Invisible(不要设为不改变对象设置)。

6完成后,从菜单栏选择File>Save。

7继续设置该对象直到所有用户和组都设定完毕。

8继续设定其它对象。

在应用程序中实现安全性

一旦你定义了安全性数据库,那么在你的应用程序中启动安全性服务。

用法

在你的应用程序中启动安全性服务包括:

启动安全性服务

建立与包含安全性表的数据库的连接并与安全性服务进行通讯

在适当的窗口启动安全性服务

为应用程序启动安全性服务:

调用 n_cst_appmanager of_SetSecurity函数:

gnv_app.of_SetSecurity(TRUE)

建立与包含安全性表的数据库的连接并与安全性服务进行通讯:

1创建事务对象并连接到数据库 (本例子假定了一个自定义 n_cst_appmanager子孙的实例变量itr_security):

gnv_app.itr_security = CREATE n_tr

gnv_app.itr_security.of_Init &

(gnv_app.of_GetAppINIFile(), "Security")

gnv_app.itr_security.of_Connect()

安全性表布置 最小化你的应用程序与数据库的连接数目,把安全性表放置于应用程序数据库内。

2调用 n_cst_security of_InitSecurity函数:

Integer li_return

li_return = &

gnv_app.inv_security.of_InitSecurity &

(gnv_app.itr_security, "EISAPP", &

gnv_app.of_GetUserID(), "Default")

为窗口启动安全性:

在窗口的Open或 pfc_PreOpen事件中调用 n_cst_security of_SetSecurity函数:

gnv_app.inv_security.of_SetSecurity(this)

维护安全性数据库

PFC安全系统的表发布在本地数据库PFC.DB中。

PFC安全性表有:

Security_apps

Security_groups

Security_info

Security_template

Security_users

你能使用本地数据库 PFC.DB定义用户和组、扫描对象,并且定义存取权限。

无论如何,在发布应用程序前你将需要移动这些表到服务器数据库中。

PFC安全系统和安全性数据库为易于移动到服务器数据库作了设计:

所有数据库通过DataWindows与PFC安全性进行交互(没有嵌入SQL)

 PFC安全系统强迫使用手动的级联删除

用法

将PFC安全性表移动至服务器数据库,为应用程序的所有用户启动安全性。

移动PFC安全性表至服务器数据库:

1使用数据管道画板移动表定义和数据到服务器数据库。

尽可能地保留表和列名。

2使用 DataWindow画板访问 PFC安全性 DataWindow。

注意下列情况:

保留 DataWindow的列的顺序和 DataWindow列名。

如果必要的话,使用选择画板更改联合的数据库表或列的名字以匹配那些在服务器数据库上的表或列。

记得不要更改 DataWindow的列名。

3在你的应用程序中,正确地为包含安全性表的服务器数据库设定事务对象。

库扩展器

你可以使用PFC库扩展器自动创建和设定位于二个已有层次(PFC祖先层和PFC扩展层)的中间扩展层。

例如,你可以使用库扩展器给PFC创建包含所有你公司扩展库的中间扩展层:


 

加入公司和部们的中间扩展层使得应用程序程序员能充分利用扩展层。

用法

库扩展器安装在 PFC工具目录。

参阅 完整的用法,请参见“库扩展器在线帮助”。

移植助手

移植助手扫描 PowerBuilder库 (PBLs)并且突出显示废弃的函数和事件。

废弃的函数和事件仍然工作在 PowerBuilder的当前的版本但是不可以工作于今后的版本。

如果你打算保正应用程序将来的运行,最好使用当前的语法和事件。

用法

移植助手被安装在 PowerBuilder目录。

参阅 完整的用法,参见“移植助手在线帮助”。
发布PFC应用程序


关于本章
本段说明PFC应用程序发布的有关事项。
选择发布策略
你使用PFC建立产品化的应用程序。
和所有产品化的应用程序一样,发布PFC应用程序需要小心地规划和实施。
你的目标
你的发布策略必须提供用户工作站执行PFC应用程序所需要的全部文件:
应用程序可执行文件(EXE)
应用程序 PBDs或 DLLs (如果不使用单个EXE文件)
PFC PBDs或 DLLs (如果不使用单个 EXE文件)
PFC DLLs
你的应用程序使用的其它文件和项目(ActiveX控件、注册表项、INI文件、位图等等)
PowerBuilder执行模块(可能已经被安装在用户工作站上)

数据库客户端软件(可能已经被安装在用户工作站上)


四个发布选项


PFC应用程序与其它PowerBuilder应用程序一样具有四个发布选项。
在选择发布策略前你需要考虑每个选项的优缺点在哪儿:
实际文件发行
如果你的应用程序应用Pcode PBDs或已编译的DLLs,它们通常需要为每份发布的PFC应用程序做成一个文件集。
这是因为内部存在从高级扩充对象往下延伸的相互依赖关系,比如 w_master、n_cst_dwsrv、n_cst_winsrv和n_cst_dssrv。
参阅 “设置应用程序管理器”。.
使用公用的实际文件集
如果发布的应用程序没有改变PFC祖先层或PFC扩充层,应用程序能共享PBD或DLL文件。
所以为了便于维护和升级,最好为发布的应用程序提供提供一套PBD和DLL文件集。
使用PFC DLLs
如果你的应用程序提供打印能力或明确地使用文件或系统服务,你将需要发布一个或多个PFC DLLs:
每个平台专用模块:
平台模块(s)使用 32-位 Windows PFCCOM32.DLL 16-位 Windows PFCCOMM.DLL PFCFILSRV.DLL Macintosh PFCMACPLATFORMSRV.LIB UNIX不平台-专用的模块用 PBR文件 PFC运和六 PBR文件:
使用PBR文件
PFC包括六个PBR文件:
一个当位图放置于EXE文件内时被使用
另五个当发布PBDs或DLLs被使用,这些文件如下:
Deployment方法 PBR文件(s)使用什么发生你展开当和 PBR什么发生你展开当      没有 PBR把位图放置于单 EXE内 Pfc.pbr(This PBR包含动态的 conversion数据变换窗户参考)位图和 dynamically referen
发布数据库表
PFC包括数据库PFC.DB。
表引用
虽然没有PFC服务直接引用PFC.DB,但有几个最初包括在PFC.DB中的服务需要引用表:
PFC服务表参考出错信息服务 (n_cst_error)消息安全性服务 (n_cst_security) Security_appsSecurity_groupingsSecurity_infoSecurity_templateSecurity_users做什么最小化数据库的数 connectio
做什么
为了使你的应用程序与数据库PFC.DB的连接数最少,通常最好将这些表移动到应用程序数据库.
无论如何,你的应用程序发布策略必须为用户使用者提供应用程序必需的对所有数据库表的访问。
这包含安装客户软件、更新INI文件、更新注册表项等等,以及其它在应用程序技术中讨论数据库发布数据库发布考虑概要在。
发布 PFC对话框帮助 PFC包含 PFCDLG.HLP文件,哪一个包含在线帮助为 PFC对话箱.
如果你的应用程序使用 PFC对话箱 (比如 w_find, w_replace,并且 w_sortdragdrop)你应该展开 PFCDLG.HLP如此用户使用者将有对话框帮助.
PFC也包含 PFCDLG.RTF,哪一个包含原文为 PFC对话框帮助.
如果你的应用程序制作 PFC的专用的使用对话箱,你能修改这文件和 recompile帮助文件.
16-位 Windows deployment如果你是发布应用程序在 16-位 Windows,重命令 PFCDLG16.HLP到 PFCDLG.HLP和展开这文件.

猜你喜欢

转载自blog.csdn.net/tlammon/article/details/108181244
今日推荐