数据库快速开发工具 PowerBuilder 从5.0版本开始提供了一套基础类库PFC(PowerBuilder Foundation Class),使得应用程序的开发速度又提高了一大步。由于PFC使用的不是很广泛,许多开发者对此还不是很了解。下面就我使用的过程中所得到的心得与遇到的问题,整理出来与大家共享与探讨。各位觉得有不合适的地方,希望批评指正。

PFC的帮助对各个独立服务、事件或者函数有一些实例代码,但是对于整体的使用几乎没有很全面地介绍。因此,我写这些东西,作为PFC帮助的一个辅助材料,大部分是在PFC帮助上没有的内容,是我使用PFC的过程中的总结与归纳。

PFC入门

首先,介绍一下如何创建一个简单的PFC应用程序。

构造一个简单的PFC程序框架

使用PFC,我们得先学会使用PFC构造一个简单的应用程序。我们可以根据PFC帮助提供的模式来构造我们的应用程序框架(参见PFC帮助的Overview 中的 For a quick start项),也可以查看PFC例程(Peat、Example等)仿造构造我们的应用程序。下面简单的陈述一下我通常使用PFC构造应用程序的步骤:

  1. 首先,创建一个空的应用程序,从对象n_cst_appmanager继承一个新的用户对象,命名为n_mdl_app;
  2. 其次,根据PFC帮助快速模型实例创建简单的应用程序框架,有所不同的是:应用程序服务,我使用刚才创建的用户对象n_mdl_app代替了n_cst_appmanager,
    设置n_mdl_app的相关事件的代码,可参见PFC例程的程序代码;
  3. 打开应用(Application)对象,更改部分属性及代码:
    • 在Additional Properties中,更改Variable Types 页中的3个变量(SQLCA->n_tr; Error->n_err; Message->n_msg)(参考PFC例程Peat)
    • 根据需要更改默认字体的类型及大小(由于我们开发的都是中文界面的应用程序,所有字体更改为“宋体 9pt”),根据需要更改应用程序的图标;
    • 根据需要更改其他的属性,比如:DisplayName, MicroHelpDefault, 等等;
    • 另外,我还需要更改应用对象的SystemError事件的代码,我使用的是逄新利编写的一个错误陷阱模块。
       
  4. 根据需要编写.Ini文件或者更改注册表项值。

好了,到此为止,一个PFC应用程序框架就完成了。试着运行一下,可以看到框架窗口的运行状态。

添加一个工作区窗口

应用程序框架窗口实现出来了,为了能够工作,我们还得有工作区窗口(Sheet)。

首相,随便创建一个Grid型的数据窗口对象,保存为d_demo1。然后从w_sheet窗口继承出来一个窗口对象,然后在这个窗口中放置一个用户对象u_dw(数据窗口的基础祖先对象)。该数据窗口控件的数据对象为刚才创建的数据窗口对象d_demo1。

在窗口的Open事件中编写如下代码:

  

// 开启Resize服务 this.of_SetResize(True) //设置Resize服务的原始大小 this.inv_Resize.of_SetOrigsize( dw_Demo.Width + dw_Demo.X * 2, dw_Demo.Height + dw_Demo.Y * 2 ) //注册要实施Resize服务的控件及方法 this.inv_Resize.of_Register(dw_Demo,this.inv_Resize.SCALERIGHTBOTTOM) //异步触发事件,利用消息路由发送消息。该消息是要检索数据 this.Event Post pfc_MessageRouter('pfc_Retrieve')

在数据窗口控件的Constructor事件中编写如下代码:

  

this.of_SetTransObject(SQLCA) // 设置事物对象 this.of_SetBase(True) // 开启数据窗口基本服务 this.of_SetPrintPreView(True) // 打印预览服务 this.of_SetRowManager(True) // 行管理服务 this.of_SetRowSelect(True) // 行选择服务 this.of_SetFind(True) // 查找服务 this.of_SetSort(True) // 排序服务 this.of_SetFilter(True) // 筛选服务 this.inv_RowSelect.of_SetStyle(this.inv_RowSelect.EXTENDED) // 设置行选择服务为高级选择模式,支持Ctrl & Shift键 this.inv_Sort.of_SetStyle(this.inv_Sort.DROPDOWNLISTBOX) // 设置排序服务的对话框样式 this.inv_Filter.of_SetStyle(this.inv_Filter.SIMPLE) // 设置筛选服务的对话框样式 this.inv_Sort.of_SetColumnDisplayNameStyle(this.inv_Sort.HEADER) // 设置排序服务的显示内容 this.inv_Filter.of_SetColumnDisplayNameStyle(this.inv_Filter.HEADER) // 设置筛选服务的显示内容

在数据窗口控件的pfc_Retrieve事件中编写如下代码:

  

Return this.Retrieve()

如果该窗口需要保存数据,在窗口的pfc_EndTrans事件中编写如下代码:

  

Integer li_TransRtn
If ai_Update_Results = 1 Then // 如果更新数据库成功, 则提交事务 li_TransRtn = SQLCA.Of_Commit() Else // 否则, 回滚事务,并提示信息 li_TransRtn = SQLCA.Of_Rollback() of_Messagebox('Update DB Failed','提示','数据保存失败。',Exclamation!,OK!,1) End If // 返回该事件发生的情况 SUCCESS & FAILURE 是w_master的实例变量 If li_TransRtn = 0 Then Return SUCCESS Else Return FAILURE End If

如果该窗口的数据不需要保存,则要将数据窗口控件的ib_UpdateAble属性选择为False,这样在更改了数据以后,关闭窗口是不会提示类似于“数据以更改,是否保存”等的信息了。

将该窗口命名保存为w_Demo1。

在应用程序的主菜单上添加一个项目,编写该项目的Clicked事件代码为:

  

Message.StringParm = 'w_demo' of_SendMessage('pfc_open')

好了,运行应用程序,看一下运行的效果吧。你可以查看以下的效果:

  • 使用鼠标右键单击数据窗口,查看数据窗口的右键菜单;
  • 删除一条数据,然后右键单击数据窗口,选择“Restore”项,看一看恢复删除的功能;
  • 点击窗口菜单上的“Sort”、“Filter”、“Print Preview”,“Find”,“Replace”等菜单项,查看数据窗口的“排序”、“筛选”、“打印预览”,“查找”,“替换”等的功能;
  • 点击菜单[View]的[First/Prior/Next/Last]等菜单项,查看数据窗口的翻页功能;
  • 修改部分数据,关闭窗口,查看提示保存的对话框

以上的这些功能,使用PFC的时候,简单到只需设置某项属性或者编写一句开启某项服务的语句即可实现。如果你想对某项服务提出更高的要求,比如排序服务,你想更改服务的模式由默认的PB拖放排序方式改为下拉列表框方式,还需要一行命令来更改服务的方式。

完善并增加更多的功能

如果您想增加更多的更强大的功能,比如闪屏,登录窗口等等。下面就简单的介绍一下增加这些功能的简单的方法。顺便介绍一下我们可也在这些事件中添加的代码和开启的服务。涉及到的有关的具体问题会在以后慢慢的了解到。

通过查看PFC例程Peat的代码,我们知道可以在“应用程序管理器”对象(gnv_App的对象)的Contructor事件中初始化版本、公司、INI文件等的信息(实例变量值,这些值大多可以在属性窗口中设置),可以在“应用程序管理器”对象的pfc_Open事件中开启需要的应用程序服务,这些服务包括:应用程序选项服务、数据窗口缓存服务、错误信息服务、调试服务、安全服务、事务注册服务、最近使用对象服务等等。

其次,我们可以在该对象的pfc_PreAbout,pfc_PreSplash,pfc_PreLogonDlg事件中添加代码来定制“关于”、“登录”以及闪屏对话框的显示。在这三个事件中各有一个参考型的参数,这些参数是相应的属性对象实例,开发人员可以改变这些对象的属性,来达到控制对话框显示信息目的。如果不更改,将按照默认的样式现实。

如果需要,“应用程序管理器”对象的pfc_Idle,pfc_ConnectionBegin、pfc_ConnectionEnd事件中编写代码,并在应用的相应事件中触发这些事件。

如果需要显示登录窗口,需要完成以下步骤:

  • 在框架窗口的Open事件中调用of_LogonDlg()函数:

         

    Integer li_Rtn //调用函数打开登录对话框 li_Rtn = gnv_App.of_LogonDlg() If li_Rtn = 1 Then this.SetMicroHelp('Logon Successful') Else If li_Rtn = -1 Then MessageBox('Logon','Logon Failure' + String(li_Rtn)) End If //Close(this) Halt Close End If

  • 在“应用程序管理器”对象的pfc_Logon事件中添加代码来处理用户的登录。例如可以是如下的代码:
         

    Integer li_Rtn String ls_IniFile ls_IniFile = this.of_GetAppIniFile() If SQLCA.of_Init(ls_IniFile,"DataBase") = -1 Then li_Rtn = FAILURE End If //as_UserID & as_Password为传递给事件的参数 SQLCA.of_SetUser(as_UserID,as_Password) If SQLCA.of_Connect() = -1 Then li_Rtn = FAILURE Else gnv_App.of_SetUserID(as_UserID) li_Rtn = SUCCESS End If Return li_Rtn

其实,在我们大多开发的应用程序中,登录窗口检验的是我们存放在数据库中的用户列表,而不是登录数据库的用户身份验证。开发人员可根据需要自行更改。

另外,我们可以开启框架窗口的状态条服务和工作区窗口(Sheet)管理服务。要开启这两个服务,我们只需在框架窗口的Open事件中编写相应的代码。不过,PFC的状态条实在是差强人意。

消息路由器

CSDN上曾有网友提问要知道PFC消息路由器的机制问题,下面我从《PowerBuilder 基础类库技术详解》一书摘抄一节介绍消息路由器的部分。

PFC使用消息路由器来处理菜单和窗口之间的通信。这种定制的消息传送机制内至于所有PFC菜单和窗口中。

虽然消息路由器可以用于任何对象与一个窗口的通信,但是他通常用来将消息从菜单传递给窗口。消息路由器根据一种定制的搜索算法来决定接受该消息的对象。

使用消息路由器有以下优点:

  • 菜单的脚本只需要知道要调用的用户事件,而不必知道当前窗口或相关控件的名称;
  • 窗口不必保留那些只是简单地调用数据窗口的用户事件。这样,窗口所保留的用户事件的数目就减少了。

消息路由器函数传递的消息实际上就是一个字符串,该字符串包含窗口或窗口的控件要激活的用户事件的名称。消息路由器包括内置的调试信息,从而可以提供错误信息。

当用户选中一个菜单项时,该菜单项的Clicked事件调用该菜单的of_SendMessage函数,并传递要调用的用户事件的名称。 of_SendMessage函数调用n_cst_menu的of_SendMessage函数,该函数调用窗口的pfc_MessageRouter事件,该事件再调用制定的用户事件。

根据应用程序是MDI程序还是SDI程序,of_SendMessage调用的pfc_MessageRouter用户事件的方式有所不同,如图:

 

pfc_MessageRouter用户事件调用窗口、当前控件以及最近即获得数据窗口中传递的用户事件,如图:

 

消息路由器提供一种菜单和窗口之间的通信机制。除了数据窗口中的命令按钮之外,没有按钮能够调用pfc_MwssageRouter事件。这是因为详细函数调用GetFocus事件来的到当前的控件,而实际上点中一个命令按钮之后,当前的控件就是该命令按钮本身。


以上内容摘自《PowerBuilder 基础类库技术详解》,电子工业出版社出版,王梅君 等编著。

该书是 刘红岩 主编的《PowerBuilder 7.0 与 Sybase Internet 技术丛书》系列中的一员。  

PFC的使用与探索(一)相关推荐

  1. Science:内侧前额叶皮层解决利用-探索困境的神经机制

    在日常生活中,我们经常需要选择调整现有的解决方案或者探索新的方案,被称为利用-探索困境(exploitation-exploration dilemmas),这涉及到内侧前额叶皮层(mPFC)的功能. ...

  2. 探索 TVM 进行量化方法

    探索 TVM 进行量化方法 Relay框架 如上图所示,有两种不同的并行工作正在进行中 • 自动整数量化 - 采用 FP32 框架图,在 Relay 中自动转换为 Int8. • 接受预量化整数模型 ...

  3. 自主数据类型:在TVM中启用自定义数据类型探索

    自主数据类型:在TVM中启用自定义数据类型探索 介绍 在设计加速器时,一个重要的决定是如何在硬件中近似地表示实数.这个问题有一个长期的行业标准解决方案:IEEE 754浮点标准.1.然而,当试图通过构 ...

  4. 2021年大数据ELK(二十六):探索数据(Discovery)

    全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 探索数据(Discovery) 一.使用探索数据功能 二.导入更多的Apach ...

  5. Python数据挖掘:数据探索,数据清洗,异常值处理

    来源:天善智能韦玮老师 课堂笔记 作者:Dust 探索性数据分析Exploratory Data Analysis,EDA 数据探索的核心是︰ 1.数据质量分析(跟数据清洗密切联系) 2.数据特征分析 ...

  6. oracle无创建directory权限,【DIRECTORY】普通用户创建Oracle DIRECTORY数据库对象的权限需求及探索...

    可能遇到的报错信息如若在创建DIRECTORY之前普通用户sec未获得相应权限,将会收到最为常见的"ORA-01031: insufficient privileges"错误.模拟 ...

  7. sources root pycharm 怎么设置_使用python语言开发ROOT之搭建环境方法探索

    这里指的是使用python调用ROOT的模块,编写程序用来处理数据的环境搭建方法. 经过研究,一般有四种方案 环境变量法,主要依靠ROOT本身,环境变量是关键 预编译包,但是该方法没有证实成功搭建py ...

  8. 论计算机的创新性,论计算机专业教学创新探索

    1/4论计算机专业教学创新探索改革高校计算机专业实训课程教学方法的重要意义高校计算机专业实训课程是计算机专业的实践课程,在计算机专业课程体系中处于非常重要的位置,主要用于培养计算机专业学生实践应用能力 ...

  9. mysql 集群实践_MySQL Cluster集群探索与实践

    MySQL集群是一种在无共享架构(SNA,Share Nothing Architecture)系统里应用内存数据库集群的技术.这种无共享的架构可以使得系统使用低廉的硬件获取高的可扩展性. MySQL ...

最新文章

  1. #我要10000+# 计划启动啦!让文章拥有更多曝光~
  2. 通过IDEA查看某个类的继承关系
  3. 厦门大学林子雨教授大数据技术原理及应用课程问题处理集锦
  4. (翻译) MongoDB(10) 在 Red Hat 企业版或者 Centos Linux 上安装MongoDB社区版
  5. [buaa-SE-2017]个人作业-Week1
  6. 书单 | 读了这10本书,再也不怕黑客攻击了
  7. Linux C - symlink 和 readlink - 符号链接
  8. Android7.1 Offload模式下的音频数据抽取过程
  9. php随机获取数组的值
  10. Android开发之自定义UI组件和属性
  11. 云计算之云计算和虚拟化的区别
  12. 设计模式入门--发布订阅模式
  13. NX二次开发 UFUN创建倒角特征 UF_MODL_create_chamfer
  14. 越专业的人,在下一个时代死得越惨烈!
  15. 卡西欧学生用计算机怎么玩,你真的会用计算器么?来玩转卡西欧计算器吧
  16. Staubli HCB08.7202/IC/JS3
  17. linux的垃圾箱是哪个文件夹,Ubuntu命令行的垃圾箱Trash CLI,远离 rm 命令误删除重要文件的阴影...
  18. 数学速算法_博士老妈整理:吃透这份小学数学“速算法”,孩子6年回回考98
  19. 从Δημόκριτος到Schrödinger:人类与原子
  20. 镁客网每周硬科技领域投融资汇总(1.20-1.26),微软出手再收购开源服务商...

热门文章

  1. 开水果店的风险,开水果店有什么风险
  2. Hexo-yilia主题个性化美化及功能添加
  3. 微软正打造全新 Edge“Phoenix”浏览器?网友:画蛇添足?
  4. ASP.NET Core与ASP.NET区别
  5. 【代码】代码管理平台推荐
  6. MySQL: 备份 导入备份
  7. BLAKE2 hash函数
  8. 使用cookie进行模拟登陆
  9. Sugar BI 增强分析能力全场景解析与分享
  10. 科技感海报大合集,分分钟做出高端海报