西安海星系统集成中心 田俊国
---- 对象被右键单击就弹出一个功能菜单是Windows应用程序一项不可缺少的功能。在PowerBuilder应用开发中,可在需弹出右键菜单对象的rbuttondown事件中调用该菜单的Popmenu( )方法实现这一功能。但多数情况下,应用中有多处要用到不同的弹出式菜单,如一一用这种方法就需要做大量的工作。能不能做一个通用的菜单,可以用任何对象的rbuttondown事件激发弹出,并在弹出前动态改变弹出菜单项的内容,当点击菜单项时又可执行被右击对象的相应用户事件?由于这一技术最大的特点是当函数创建成功后,可在任何应用的任何对象中随心所欲的使用,随时随地弹出自己想要显示的菜单项,并执行相应的自己需要的功能脚本,但目前各种资料上鲜有系统、成型的介绍。笔者抱着一种探索的态度,作了一番仔细深入的研究,并小有收获,愿和大家共同探讨。
一、 创建弹出菜单m_popup
创建一个菜单m_popup,定义菜单条m_main,其下有十五个菜单项,分别命名为m_item1,m_item2,……m_item15,各项的显示文本(text)分别为item1,item2,… …item15;
为m_popup菜单定义一个Powerobject类型的Instance变量:Anyobject
脚本为:
Powerobject Anyobject
给m_item1,m_item2,… …m_item15各菜单项的Clicked事件下分别输入脚本:
Anyobject.triggerevent("ue_item1")
//m_item1的clicked事件
Anyobject.triggerevent("ue_item2")
… …
Anyobject.triggerevent("ue_item15")
---- 4、 定义几个菜单函数:
---- 1) setmenuitem(string itemstring),返回值为Null。
---- 参数Itemstring是由多个子串组成的。各个子串间用“(专业提供视频软件下载)
”间隔,每个子串为一个菜单项的显示文本(text)。
---- 该函数功能是把itemstring分解为多个子串,并把子串赋给相应菜单项的text。脚本如下:
int itempos,itemorder=1,i
string currentitem
if len(itemstring)=0 then return
itempos=pos(itemstring,"(专业提供视频软件下载)
")
DO WHILE itempos<>0
// itempos为间隔符"(专业提供视频软件下载)
"的位置
currentitem=left(itemstring,itempos -1)
//取出子串
itemstring=mid(itemstring, itempos+1)
this.m_main.item[itemorder].text=currentitem
itempos=pos(itemstring,"(专业提供视频软件下载)
")
itemorder++
LOOP
this.m_main.item[itemorder].text=itemstring
for i=1 to itemorder
this.m_main.item[i].visible=true
this.m_main.item[i].enabled=true
end if
for i=itemorder+1 to 15
this.m_main.item[i].visible=false
next
2)setitemdisable(integer itemorder) 返回值Null。
该函数把第itemorder菜单项置灰(disable)。
脚本如下:
if itemorder<1 or itemorder>15 then return
this.m_main.item[itemorder].enabled=false
3)popupmenu(integer x, integer y) 返回值Null。
该函数弹出菜单条m_main。
脚本如下:
this.m_main.popmenu(x,y)
二、 rbuttondown事件激发弹出菜单m_popup
---- 至此,我们就可以在窗口中任意对象如DataWindow、 Picture、 SingleLineEdit、 ListBox、 PictureListBox、 DropDownPictureListBox、 MultiLineEdit、 ListView、 TreeView等的rbuttondown事件中写脚本调用m_popup的函数来实现右键单击弹出一个菜单。下面以数据窗口dw_1为例,在其rbuttondown事件下写入脚本,使得右击dw_1 可弹出菜单:刷新/插入/删除/修改。步骤如下:
1、事先给窗口定义一个m_popup 型instance变量om_1:
m_popup om_1
2、dw_1的rbuttondown事件脚本:
if not isvalid(om_1) then
om_1= CREATE m_popup
end if
//把菜单的anyobject指向被右击的对象(dw_1)
om_1.anyobject=this
om_1.setmenuitem("刷新(专业提供视频软件下载)
插入(专业提供视频软件下载)
删除(专业提供视频软件下载)
修改")
//可在此调用om_1.setitemdisable(itemorder)函数disable某
菜单项。
om_1.popupmenu(this.x+this.pointerx(),
this.y+this.pointery())
3、 给dw_1定义用户事件ue_item1、ue_item2、ue_item3
及 ue_item4。
事件ue_item1脚本:
dw_1.retrieve()
事件ue_item2脚本:
long newrow
newrow=dw_1.insertrow(0)
dw_1.scrolltorow(newrow)
事件ue_item3脚本:
dw_1.deleterow(0)
事件ue_item4脚本:
dw_1.update()
---- 这样,只要用户单击dw_1弹出的右键菜单,就可完成对dw_1的插入、删除、修改等功能。
三、 推广为全程函数
---- 如果应用中有许多地方要用此功能,我们可以把dw_1的rbuttondown事件脚本改造成一个全程函数。
---- 1、将变量om_1定义为global变量:
---- m_popup om_1
---- 2、定义一个全程函数
---- pupmenu(powerobject sender,string itemstring,integer x,integer y) 返回值Null。其中参数sender为被右击的对象,itemstring为弹出菜单的菜单项字符串,x、y为菜单弹出的坐标位置。
脚本如下:
if not isvalid(om_1) then
om_1= CREATE m_popup
end if
om_1.anyobject=sender
om_1.setmenuitem(itemstring)
sender.triggerevent("ue_beforepop")
//激活sender用户事件。
om_1.popupmenu(x,y)
这样,上述dw_1的rbuttondown事件脚本就可改写为:
string items="刷新(专业提供视频软件下载)
插入(专业提供视频软件下载)
删除(专业提供视频软件下载)
修改"
popmenu(this, items ,this.x+this.pointerx(),
this.y+this.pointery())
注意:在MDI 应用中,popmenu()函数需要改为:
popmenu(this, items ,w_frame.pointerx(),w_frame.pointery())
其中w_frame为MDI主窗口名。
---- 在函数popmenu中,又激活了被右击对象的ue_beforepop用户事件。如有必要,你可以给被右击对象定义一个ue_beforepop事件,在该事件中可调用om_1.setitemdisable()函数来屏蔽某个菜单项。
---- 最后,别忘了在应用的close事件里加上下列语句,及时释放系统内存。
---- if isvalid(om_1) then destroy om_1
---- 以上代码在Windows98 和Powerbuilder6.5平台上开发,并在多个大型系统中应用,效果很好。
……