刘荣刚
摘要:在Powerbuilder可视化编程设计的基础上,利用PowerBuilder的高级编程功能,在程序运行过程中对数据窗口进行动态调整,使得数据窗口展示的数据及形式不再是一成不变的,而是随着程序运行形成的各种条件及用户的选择动态变化的。
关键词:PowerBuilder;数据窗口;可视化开发
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2015)05-0010-03
1 引言
PowerBuilder(简称PB)是一个图形化的应用程序开发环境。使用PB可以很容易地开发和数据库打交道的商业化应用软件。PB开发的应用软件由窗口构成,窗口中不仅可以包含按钮、下拉列表框及单选按钮等标准的Windows控件,还可以有PB提供的特殊的控件。这些特殊控件可以使应用软件更容易使用,使应用软件的开发效率更高。数据窗口控件就是PB提供的一个集成度很高的控件,使用该控件可以很方便地从数据库中提取数据。PB提供了可视化的数据窗口设计和编程模式,但是,可视化设计界面设计的数据窗口在程序运行过程中是固定不变的。很多时候,我们需要依据程序运行的情况及用户的选择对数据窗口进行动态调整,使数据窗口以不同的形式呈现数据,这就需要在程序运行过程中对数据窗口进行动态设置。
2 建立数据窗口控件和数据窗口
PB的可视化编程环境仍然是PB程序设计的基础,我们在PB可视化设计阶段建立了一个数据窗口控件DWmain,该数据窗口控件包含一个Grid类型的数据窗口DWdata,数据窗口控件DWmain实现数据窗口DWdata与用户的人机交互,用户通过操作数据窗口控件DWmain对数据窗口DWdata的数据进行检索、新增、删除和修改等操作。可视化部分设计的原则是,固定不变的内容就在可视化部分设计,需要动态调整的内容则在程序中完成。
数据窗口对象DWdata的数据源是数据库表h_hy,h_hy的结构如下:
表1 数据库表结构定义
[列名\&类型\&长度\&小数位\&Ph\&Char\&20\&\&Rq\&DateTime\&8\&\&Csn\&Decimal\&9\&5\&Cpb\&Decimal\&9\&5\&Cas\&Decimal\&9\&5\&Cfe\&Decimal\&9\&5\&]
唯一索引:Ph
数据窗口对象DWdata的SQL语句定义如下:
SELECT ph ,rq,csn,cpb,cas,cfe FROM h_hy ;
3 在程序中对数据窗口进行动态编程的技术
1)禁止对rq进行修改
要禁止用户对rq列进行修改,可以将rq列的TabSequence属性值设置为0。
dwmain.object.rq. TabSequence=0
2)屏蔽rq的显示
屏蔽rq列的显示,可以将rq列的visible属性值设置为false。
dwmain.object.rq. visible=false
3)调整列显示顺序
数据窗口默认列显示顺序是在可视化编程时确定的,调整列显示顺序,要先将所有列的属性值visible设置为false,再依据新的显示顺序,依次将各列的visible属性值设置为true。例如,将rq调整到最后一列显示,可以使用以下代码。
long l_col, l_column_count,l_i
string ls_column
//获取数据窗口字段总列数
l_column_count = long(dwmain.Describe("DataWindow.Column.Count"))
//先将所有列的属性值visible设置为false
for l_i = 1 to l_column_count
//获取列名并转换为小写字符
ls_column = dwmain.Describe("#"+string(ll_i)+".Name")
ls_column=lower(ls_column)
//设置属性值visible
dwmain.modify("#"+string(l_i)+".visible=false")
next
//将rq以外的所有列的visible的属性值设置为true
for l_i = 1 to l_column_count
//顺序获取列名并转换为小写字符
ls_column = dwmain.Describe("#"+string(l_i)+".Name")
ls_column=lower(ls_column)
choose case ls_column
case 'rq'
l_col=l_i
continue
case else
//顺序设置rq以外的列的属性值visible=true
dwmain.modify("#"+string(l_i)+".visible=true")
end choose
next
//最后将rq的visible属性值设置为true
dwmain.modify("#"+string(l_col)+".visible=true")
return 0
4)用回车键取代Tab键
PB数据窗口控件默认使用Tab键依据各列的Taborder值在列之间移动光标,这很不符合常规的操作习惯,我们可以通过编程利用回车键替代Tab键,实现传统的光标移动方式。
图1 自定义事件
针对数据窗口控件dwmain新建一个自定义事件,命名为enter,事件ID选择pbm_dwnprocessenter,并对该事件编写如下代码,当数据窗口控件接收到回车键之后,会自动转换成一个TAB键,实现光标顺序移动到下一列。
//用回车键替代TAB键
if this.AcceptText() < 0 then
Return 1
end if
Send(Handle(this),256,9,Long(0,0))
return 1
5)数据窗口通用排序设计
PB的可视化设计环境虽然可以很方便的定义数据的排序模式,但是,在实际应用中,任何单一的数据排序模式都很难满足应用要求。设计一个可以让用户在程序运行过程中自定义排序的通用排序功能很有必要。通用排序窗口的关键就在于提供一个通用的构造排序模式的窗口,该窗口可以列出所有待排序数据窗口的数据列,供用户选择。
(1) 通用排序数据窗口对象
通用排序窗口利用PowerBuilder的External方式设计的数据窗口对象实现,名称为dw_sort,该数据窗口对象包含如下列名:
表2 通用排序数据窗口定义
[列名\&类型\&长度\&小数\&备注\&Idx\&Number\&\&\&关键字\&Ys\&String\&10\&\&数据库表列名\&Ysmc\&String\&20\&\&列对应的Label\&Xh\&Number\&\&\&升降法则\&]
(2) 通用排序窗口
图2 通用排序窗口
在该窗口的左右两边各有一个包含数据窗口dw_sort的数据窗口控件,分别命名为dw_s和dw_d,dw_s列出待排序数据窗口对象的所有数据列,dw_d列出用户选择的排序关键字,并定义升降法则。左边窗口按idx排序,主要是为了保持原始数据列的顺序不变。
Dw_s是在排序窗口打开时,根据传递给排序窗口的待排序数据窗口控件进行初始化的,初始化代码放在排序窗口的OPEN事件中执行,代码如下:
datawindow dw_data
long l_column_count,l_row,l_source_row,l_xh
string ls_column,ls_column_name
string ls_ys,ls_ysmc
//获取传递过来的待排序数据窗口控件
dw_data=message.powerobjectparm
//获取待排序数据窗口的总列数
l_column_count= long(dw_data.Describe("DataWindow.Column.Count"))
l_xh=0
//循环处理所有列
for l_row = 1 to l_column_count
//如果列显示属性为真(可见),则进行处理
if dw_data.Describe("#"+string(l_row)+".Visible") = '1' then
//获取列名
ls_column=w_data.Describe("#"+string(l_row)+".Name")
//获取列名对应文本
ls_column_name=dw_data.Describe(ls_column+"_t.text")
//在左边数据窗口插入列名及其对应的文本
l_source_row=dw_s.insertrow(0)
dw_s.setitem(l_source_row,"ys",ls_column)
dw_s.setitem(l_source_row,"ysmc",ls_column_name)
l_xh=l_xh+1
dw_s.setitem(l_source_row,"idx",l_xh)
dw_s.setitem(l_source_row,"xh",0)
end if
next
//排序窗口dw_s
dw_s.setsort("idx A")
dw_s.sort()
//不显示XH列
dw_s.object.xh.visible=false
//清空保存排序模式的全局变量gs_str
gs_str=""
(3) 构造排序模式
用户通过操纵通用排序窗口,在窗口右边dw_d数据窗口对象中形成排序关键字及其组合排序顺序、升降法则等,就可以构造出期望的排序模式。排序模式的构造在通用排序窗口按钮“排序”的CLICK事件中执行,代码如下:
long l_row,l_xh,l_mode
string s_sort,s_ys
s_sort=""
l_mode=0
for l_row=1 to dw_d.rowcount() //处理dw_d所有列
l_xh=dw_d.getitemnumber(l_row,"xh") //取升降法则
s_ys=dw_d.getitemstring(l_row,"ys") //取排序关键字
if l_xh=0 then //xh=0,升序
if l_mode=0 then //第一关键字
s_sort=s_ys+" A"
l_mode=1
else //非第一关键字,用逗号分隔
s_sort=s_sort+","+s_ys+" A"
end if
else //xh<>0,降序
if l_mode=0 then //第一关键字
l_mode=1
s_sort=s_ys+" D"
else //非第一关键字,用逗号分隔
s_sort=s_sort+","+s_ys+" D"
end if
end if
next
//保存排序模式在全局变量gs_str中,关闭通用排序窗口
gs_str=s_sort
close(parent)
(4) 通用排序窗口的调用机制
通用排序窗口的调用,直接打开通用排序窗口,并将待排序数据窗口控件传递给通用排序窗口,然后根据通用排序窗口返回的排序模式(保存在全局变量gs_str中),对待排序数据窗口控件进行排序。调用代码如下:
//设待排序数据窗口控件为dwmain
//打开通用排序窗口并将待排序数据窗口控件作为参数传递
OPENWITHPARM(W_SORT,dwmain)
//根据返回的全局变量设置数据窗口排序模式,启动排序 dwmain.setsort(gs_str)
dwmain.sort()
6)共享数据窗口的数据
某些时候,我们需要同时处理几个具有相同原始数据的数据窗口。这种情况下只需要其中一个数据窗口从数据库获取数据,并将数据共享给其他数据窗口即可,避免重复读取数据库,即提高运行速度,也降低内存占用。假定有2个数据窗口控件dw1和dw2,它们拥有相同的数据窗口dwdata,其中dw1已从数据库获取到数据,可以通过以下代码将dw1的数据共享给dw2,使dw2具有和dw1完全相同的数据。
dw1. ShareData(dw2)
7)在windows窗口之间传递数据窗口对象
在打开一个新的windows窗口的时候,我们可以把当前windows窗口中的数据窗口控件及其所有数据作为参数传递到新打开的windows窗口中进行处理。
//当前windows窗口为w_1,拥有数据窗口控件dwdata
//打开windows窗口w_2,并将数据窗口控件dwdata作为参数传递给w_1
openwithparm(w_2,dwdata)
//在w_2的open事件中,接收传递过来的数据窗口
datawindow dw_data
dw_data=message.powerobjectparm
// dw_source为w_2在可视化设计时定义的数据窗口控件
//将dw_data的数据窗口赋予dw_source
dw_source.dataobject=dw_data.dataobject
//将dw_data的数据赋予dw_source,使得dw_source拥有与dw_data完全相同的数据
dw_source.object.data=dw_data.object.data
4 结语
本文应用了许多适用的技巧,充分展示了动态控制PB数据窗口的方法。PB的各种对象都有很多属性值可以在程序中进行控制,利用本文论述的方法,可以优化程序结构,提高可视化设计部分的程序的通用性,减少内存占用,提升人机交互设计水平,确保程序好用、易用,获得更佳的用户体验。
参考文献:
[1](美)《PowerBuilder5.0 PwerScript Reference》 Sybase ,Inc.
[2] (美)《PowerBuilder5.0 Datawindow Reference》 Sybase ,Inc.