劉榮剛
摘要:在Powerbuilder可視化編程設(shè)計(jì)的基礎(chǔ)上,利用PowerBuilder的高級(jí)編程功能,在程序運(yùn)行過程中對數(shù)據(jù)窗口進(jìn)行動(dòng)態(tài)調(diào)整,使得數(shù)據(jù)窗口展示的數(shù)據(jù)及形式不再是一成不變的,而是隨著程序運(yùn)行形成的各種條件及用戶的選擇動(dòng)態(tài)變化的。
關(guān)鍵詞:PowerBuilder;數(shù)據(jù)窗口;可視化開發(fā)
中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2015)05-0010-03
1 引言
PowerBuilder(簡稱PB)是一個(gè)圖形化的應(yīng)用程序開發(fā)環(huán)境。使用PB可以很容易地開發(fā)和數(shù)據(jù)庫打交道的商業(yè)化應(yīng)用軟件。PB開發(fā)的應(yīng)用軟件由窗口構(gòu)成,窗口中不僅可以包含按鈕、下拉列表框及單選按鈕等標(biāo)準(zhǔn)的Windows控件,還可以有PB提供的特殊的控件。這些特殊控件可以使應(yīng)用軟件更容易使用,使應(yīng)用軟件的開發(fā)效率更高。數(shù)據(jù)窗口控件就是PB提供的一個(gè)集成度很高的控件,使用該控件可以很方便地從數(shù)據(jù)庫中提取數(shù)據(jù)。PB提供了可視化的數(shù)據(jù)窗口設(shè)計(jì)和編程模式,但是,可視化設(shè)計(jì)界面設(shè)計(jì)的數(shù)據(jù)窗口在程序運(yùn)行過程中是固定不變的。很多時(shí)候,我們需要依據(jù)程序運(yùn)行的情況及用戶的選擇對數(shù)據(jù)窗口進(jìn)行動(dòng)態(tài)調(diào)整,使數(shù)據(jù)窗口以不同的形式呈現(xiàn)數(shù)據(jù),這就需要在程序運(yùn)行過程中對數(shù)據(jù)窗口進(jìn)行動(dòng)態(tài)設(shè)置。
2 建立數(shù)據(jù)窗口控件和數(shù)據(jù)窗口
PB的可視化編程環(huán)境仍然是PB程序設(shè)計(jì)的基礎(chǔ),我們在PB可視化設(shè)計(jì)階段建立了一個(gè)數(shù)據(jù)窗口控件DWmain,該數(shù)據(jù)窗口控件包含一個(gè)Grid類型的數(shù)據(jù)窗口DWdata,數(shù)據(jù)窗口控件DWmain實(shí)現(xiàn)數(shù)據(jù)窗口DWdata與用戶的人機(jī)交互,用戶通過操作數(shù)據(jù)窗口控件DWmain對數(shù)據(jù)窗口DWdata的數(shù)據(jù)進(jìn)行檢索、新增、刪除和修改等操作??梢暬糠衷O(shè)計(jì)的原則是,固定不變的內(nèi)容就在可視化部分設(shè)計(jì),需要?jiǎng)討B(tài)調(diào)整的內(nèi)容則在程序中完成。
數(shù)據(jù)窗口對象DWdata的數(shù)據(jù)源是數(shù)據(jù)庫表h_hy,h_hy的結(jié)構(gòu)如下:
表1 數(shù)據(jù)庫表結(jié)構(gòu)定義
[列名\&類型\&長度\&小數(shù)位\&Ph\&Char\&20\&\&Rq\&DateTime\&8\&\&Csn\&Decimal\&9\&5\&Cpb\&Decimal\&9\&5\&Cas\&Decimal\&9\&5\&Cfe\&Decimal\&9\&5\&]
唯一索引:Ph
數(shù)據(jù)窗口對象DWdata的SQL語句定義如下:
SELECT ph ,rq,csn,cpb,cas,cfe FROM h_hy ;
3 在程序中對數(shù)據(jù)窗口進(jìn)行動(dòng)態(tài)編程的技術(shù)
1)禁止對rq進(jìn)行修改
要禁止用戶對rq列進(jìn)行修改,可以將rq列的TabSequence屬性值設(shè)置為0。
dwmain.object.rq. TabSequence=0
2)屏蔽rq的顯示
屏蔽rq列的顯示,可以將rq列的visible屬性值設(shè)置為false。
dwmain.object.rq. visible=false
3)調(diào)整列顯示順序
數(shù)據(jù)窗口默認(rèn)列顯示順序是在可視化編程時(shí)確定的,調(diào)整列顯示順序,要先將所有列的屬性值visible設(shè)置為false,再依據(jù)新的顯示順序,依次將各列的visible屬性值設(shè)置為true。例如,將rq調(diào)整到最后一列顯示,可以使用以下代碼。
long l_col, l_column_count,l_i
string ls_column
//獲取數(shù)據(jù)窗口字段總列數(shù)
l_column_count = long(dwmain.Describe("DataWindow.Column.Count"))
//先將所有列的屬性值visible設(shè)置為false
for l_i = 1 to l_column_count
//獲取列名并轉(zhuǎn)換為小寫字符
ls_column = dwmain.Describe("#"+string(ll_i)+".Name")
ls_column=lower(ls_column)
//設(shè)置屬性值visible
dwmain.modify("#"+string(l_i)+".visible=false")
next
//將rq以外的所有列的visible的屬性值設(shè)置為true
for l_i = 1 to l_column_count
//順序獲取列名并轉(zhuǎn)換為小寫字符
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
//順序設(shè)置rq以外的列的屬性值visible=true
dwmain.modify("#"+string(l_i)+".visible=true")
end choose
next
//最后將rq的visible屬性值設(shè)置為true
dwmain.modify("#"+string(l_col)+".visible=true")
return 0
4)用回車鍵取代Tab鍵
PB數(shù)據(jù)窗口控件默認(rèn)使用Tab鍵依據(jù)各列的Taborder值在列之間移動(dòng)光標(biāo),這很不符合常規(guī)的操作習(xí)慣,我們可以通過編程利用回車鍵替代Tab鍵,實(shí)現(xiàn)傳統(tǒng)的光標(biāo)移動(dòng)方式。
圖1 自定義事件
針對數(shù)據(jù)窗口控件dwmain新建一個(gè)自定義事件,命名為enter,事件ID選擇pbm_dwnprocessenter,并對該事件編寫如下代碼,當(dāng)數(shù)據(jù)窗口控件接收到回車鍵之后,會(huì)自動(dòng)轉(zhuǎn)換成一個(gè)TAB鍵,實(shí)現(xiàn)光標(biāo)順序移動(dòng)到下一列。
//用回車鍵替代TAB鍵
if this.AcceptText() < 0 then
Return 1
end if
Send(Handle(this),256,9,Long(0,0))
return 1
5)數(shù)據(jù)窗口通用排序設(shè)計(jì)
PB的可視化設(shè)計(jì)環(huán)境雖然可以很方便的定義數(shù)據(jù)的排序模式,但是,在實(shí)際應(yīng)用中,任何單一的數(shù)據(jù)排序模式都很難滿足應(yīng)用要求。設(shè)計(jì)一個(gè)可以讓用戶在程序運(yùn)行過程中自定義排序的通用排序功能很有必要。通用排序窗口的關(guān)鍵就在于提供一個(gè)通用的構(gòu)造排序模式的窗口,該窗口可以列出所有待排序數(shù)據(jù)窗口的數(shù)據(jù)列,供用戶選擇。
(1) 通用排序數(shù)據(jù)窗口對象
通用排序窗口利用PowerBuilder的External方式設(shè)計(jì)的數(shù)據(jù)窗口對象實(shí)現(xiàn),名稱為dw_sort,該數(shù)據(jù)窗口對象包含如下列名:
表2 通用排序數(shù)據(jù)窗口定義
[列名\&類型\&長度\&小數(shù)\&備注\&Idx\&Number\&\&\&關(guān)鍵字\&Ys\&String\&10\&\&數(shù)據(jù)庫表列名\&Ysmc\&String\&20\&\&列對應(yīng)的Label\&Xh\&Number\&\&\&升降法則\&]
(2) 通用排序窗口
圖2 通用排序窗口
在該窗口的左右兩邊各有一個(gè)包含數(shù)據(jù)窗口dw_sort的數(shù)據(jù)窗口控件,分別命名為dw_s和dw_d,dw_s列出待排序數(shù)據(jù)窗口對象的所有數(shù)據(jù)列,dw_d列出用戶選擇的排序關(guān)鍵字,并定義升降法則。左邊窗口按idx排序,主要是為了保持原始數(shù)據(jù)列的順序不變。
Dw_s是在排序窗口打開時(shí),根據(jù)傳遞給排序窗口的待排序數(shù)據(jù)窗口控件進(jìn)行初始化的,初始化代碼放在排序窗口的OPEN事件中執(zhí)行,代碼如下:
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
//獲取傳遞過來的待排序數(shù)據(jù)窗口控件
dw_data=message.powerobjectparm
//獲取待排序數(shù)據(jù)窗口的總列數(shù)
l_column_count= long(dw_data.Describe("DataWindow.Column.Count"))
l_xh=0
//循環(huán)處理所有列
for l_row = 1 to l_column_count
//如果列顯示屬性為真(可見),則進(jìn)行處理
if dw_data.Describe("#"+string(l_row)+".Visible") = '1' then
//獲取列名
ls_column=w_data.Describe("#"+string(l_row)+".Name")
//獲取列名對應(yīng)文本
ls_column_name=dw_data.Describe(ls_column+"_t.text")
//在左邊數(shù)據(jù)窗口插入列名及其對應(yīng)的文本
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) 構(gòu)造排序模式
用戶通過操縱通用排序窗口,在窗口右邊dw_d數(shù)據(jù)窗口對象中形成排序關(guān)鍵字及其組合排序順序、升降法則等,就可以構(gòu)造出期望的排序模式。排序模式的構(gòu)造在通用排序窗口按鈕“排序”的CLICK事件中執(zhí)行,代碼如下:
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") //取排序關(guān)鍵字
if l_xh=0 then //xh=0,升序
if l_mode=0 then //第一關(guān)鍵字
s_sort=s_ys+" A"
l_mode=1
else //非第一關(guān)鍵字,用逗號(hào)分隔
s_sort=s_sort+","+s_ys+" A"
end if
else //xh<>0,降序
if l_mode=0 then //第一關(guān)鍵字
l_mode=1
s_sort=s_ys+" D"
else //非第一關(guān)鍵字,用逗號(hào)分隔
s_sort=s_sort+","+s_ys+" D"
end if
end if
next
//保存排序模式在全局變量gs_str中,關(guān)閉通用排序窗口
gs_str=s_sort
close(parent)
(4) 通用排序窗口的調(diào)用機(jī)制
通用排序窗口的調(diào)用,直接打開通用排序窗口,并將待排序數(shù)據(jù)窗口控件傳遞給通用排序窗口,然后根據(jù)通用排序窗口返回的排序模式(保存在全局變量gs_str中),對待排序數(shù)據(jù)窗口控件進(jìn)行排序。調(diào)用代碼如下:
//設(shè)待排序數(shù)據(jù)窗口控件為dwmain
//打開通用排序窗口并將待排序數(shù)據(jù)窗口控件作為參數(shù)傳遞
OPENWITHPARM(W_SORT,dwmain)
//根據(jù)返回的全局變量設(shè)置數(shù)據(jù)窗口排序模式,啟動(dòng)排序 dwmain.setsort(gs_str)
dwmain.sort()
6)共享數(shù)據(jù)窗口的數(shù)據(jù)
某些時(shí)候,我們需要同時(shí)處理幾個(gè)具有相同原始數(shù)據(jù)的數(shù)據(jù)窗口。這種情況下只需要其中一個(gè)數(shù)據(jù)窗口從數(shù)據(jù)庫獲取數(shù)據(jù),并將數(shù)據(jù)共享給其他數(shù)據(jù)窗口即可,避免重復(fù)讀取數(shù)據(jù)庫,即提高運(yùn)行速度,也降低內(nèi)存占用。假定有2個(gè)數(shù)據(jù)窗口控件dw1和dw2,它們擁有相同的數(shù)據(jù)窗口dwdata,其中dw1已從數(shù)據(jù)庫獲取到數(shù)據(jù),可以通過以下代碼將dw1的數(shù)據(jù)共享給dw2,使dw2具有和dw1完全相同的數(shù)據(jù)。
dw1. ShareData(dw2)
7)在windows窗口之間傳遞數(shù)據(jù)窗口對象
在打開一個(gè)新的windows窗口的時(shí)候,我們可以把當(dāng)前windows窗口中的數(shù)據(jù)窗口控件及其所有數(shù)據(jù)作為參數(shù)傳遞到新打開的windows窗口中進(jìn)行處理。
//當(dāng)前windows窗口為w_1,擁有數(shù)據(jù)窗口控件dwdata
//打開windows窗口w_2,并將數(shù)據(jù)窗口控件dwdata作為參數(shù)傳遞給w_1
openwithparm(w_2,dwdata)
//在w_2的open事件中,接收傳遞過來的數(shù)據(jù)窗口
datawindow dw_data
dw_data=message.powerobjectparm
// dw_source為w_2在可視化設(shè)計(jì)時(shí)定義的數(shù)據(jù)窗口控件
//將dw_data的數(shù)據(jù)窗口賦予dw_source
dw_source.dataobject=dw_data.dataobject
//將dw_data的數(shù)據(jù)賦予dw_source,使得dw_source擁有與dw_data完全相同的數(shù)據(jù)
dw_source.object.data=dw_data.object.data
4 結(jié)語
本文應(yīng)用了許多適用的技巧,充分展示了動(dòng)態(tài)控制PB數(shù)據(jù)窗口的方法。PB的各種對象都有很多屬性值可以在程序中進(jìn)行控制,利用本文論述的方法,可以優(yōu)化程序結(jié)構(gòu),提高可視化設(shè)計(jì)部分的程序的通用性,減少內(nèi)存占用,提升人機(jī)交互設(shè)計(jì)水平,確保程序好用、易用,獲得更佳的用戶體驗(yàn)。
參考文獻(xiàn):
[1](美)《PowerBuilder5.0 PwerScript Reference》 Sybase ,Inc.
[2] (美)《PowerBuilder5.0 Datawindow Reference》 Sybase ,Inc.