PowerBuilder动态创建菜单条.docx

上传人:b****6 文档编号:3081611 上传时间:2022-11-17 格式:DOCX 页数:7 大小:124.33KB
下载 相关 举报
PowerBuilder动态创建菜单条.docx_第1页
第1页 / 共7页
PowerBuilder动态创建菜单条.docx_第2页
第2页 / 共7页
PowerBuilder动态创建菜单条.docx_第3页
第3页 / 共7页
PowerBuilder动态创建菜单条.docx_第4页
第4页 / 共7页
PowerBuilder动态创建菜单条.docx_第5页
第5页 / 共7页
点击查看更多>>
下载资源
资源描述

PowerBuilder动态创建菜单条.docx

《PowerBuilder动态创建菜单条.docx》由会员分享,可在线阅读,更多相关《PowerBuilder动态创建菜单条.docx(7页珍藏版)》请在冰豆网上搜索。

PowerBuilder动态创建菜单条.docx

PowerBuilder动态创建菜单条

 

PowerBuilder动态创建菜单条(总7页)

动态创建菜单条2008年12月13日星期六1:

41本文拟结合powerbuilder语言,简述如何实现动态添加菜单效果。

在实际开发过程当中很多时候会因为权限控制的需要,根据用户的不同权限来动态添加菜单项目,如何避免使用繁琐的api函数(如:

createmenu、insertmenu、insertmenuitem、appendmenu等),利用powerbuilder语言自身功能达到这一目的呢本文将就此问题简单予以论述。

一、基本思路

在pb帮助的menuobject一节当中,关于其properties描述当中有一项:

item[]menuspecifiesthemenuobjectsunderamenuobject.

这看似简单的一句话其实包含了三层含义:

1、这句话说明menu对象有一个属性为数组类型,它其中的各个元素记录了其所有的具体子item项目,可以借助这个数组中各元素来访问底层的各子菜单;

2、这些子item项目仍是menu类型,因此可以按照第一点的逻辑继续向下层推广,借助该子item的item[]属性可以进而访问其所属下层的第二层子菜单,推而广之,即可全面遍历整个菜单体系的所有子菜单项目;

3、既然该属性是一个数组类型,那么就可以按照数组类型变量来处理,我们可以对其进行upperbound()、lowerbound()等函数操作,还可以进行数组的扩展,即添加新项目,这一点很重要,它是我们整篇文章的核心,如何利用pb实现动态添加菜单,说白了就是添加这个数组元素(读者必须对此有一个清晰的认识),同时期间有一些配套具体的实现技巧,详见下文。

二、具体实现

(一)基本工作

创建一个window窗口和二个menu菜单,其中一个菜单命名为m_main,用作窗口的基本主菜单,新增菜单将在其上添加,该菜单初始可以包含一些基本菜单,如:

文件、添加、删除、保存、退出等;另外一个菜单命名为m_new,该菜单只有主菜单一个item,其下没有进一步的子菜单,因此该菜单其实就是一个菜单item。

在主窗口中声明实例变量(instancevariables):

menuim_new[]2003-6-1tem[1]

 

ext="新增一级-"+string(li_itemcount+1)

 

ag="xxxxxxxxx"

 

ide()

[1].show()

2、添加二级菜单功能的实现:

2003-6-1tem[])

[li_precount].item[li_itemcount+1]=im_new[ii_count].item[1]

 

tem[li_itemcount+1].text="新增二级-"+string(li_precount)+"-"+string(li_itemcount+1)

 

tem[li_itemcount+1].tag="xxxxxxxxx"

 

ide()

[1].show()

3、添加三级菜单功能的实现:

2003-6-1tem[])

ifli_precount=0then

messagebox("提示","请先点击-添加二级菜单-按钮创建一个二级菜单,:

)")

return

endif

li_itemcount=upperbound[li_fircount].item[li_precount].item[])

[li_fircount].item[li_precount].item[li_itemcount+1]=im_new[ii_count].item[1]

 

tem[li_precount].item[li_itemcount+1].text="新增三级-"+string(li_fircount)&

+"-"+string(li_precount)+"-"+string(li_itemcount+1)

 

tem[li_itemcount+1].tag="xxxxxxxxx"

 

ide()

[1].show()

4、处理动态生成菜单的clicked事件:

总体思想是采用参数化思想,借助统一的函数,根据函数参数不同来予以不同处理。

(1)处理m_new对象的clicked事件:

2003-6-12003-6-1....比如1代表入库管理,则去调用入库管理函数gf_rk()等等

case"2"

...比如1代表出库管理,则去调用出库管理函数gf_ck()等等

...

caseelse

return-1

endchoose

 

return1

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////

曾经在一些书上看到用C语言实现动态菜单的方法,需要调用大量的API函数,但是这里我想换一种方法,借助PowerBuilder提供的属性和递归算法实现动态菜单的创建过程。

需要指出的是,这里讨论的动态菜单是已经在外部数据源中定义好菜单结构,而菜单对象没有有任何菜单项,需要由程序生成各个定义好的菜单项。

一、定义菜单数据结构

  实现动态菜单,首先设计合理的菜单数据结构,其数据源可以是任何DBMS,甚至可以是TXT文本文件(只要能建立好合理的分层结构)。

  菜单如同一个树形控件,有着分层的顺序结构,所以在定义数据结构时,应当选择一种能够形象地表示父子、兄弟关系的模型。

而能够最好反映菜单结构的控件就是树形控件:

treeview,并且定义按照二位递进的数据结构形式,即:

以级别确定层数,以序号确定兄弟关系,以二位递进确定父子关系。

例如,如图所示的菜单的对应数据结构如下。

 

  这样的菜单结构,在建立菜单结构时,非常适合用递归的算法,那么我们可以按照树的遍历算法建立一个树形结构的菜单对象。

  接下来,定义菜单数据结构。

菜单数据结构应当包含以下基本元素:

菜单名、菜单类型、菜单序号、菜单项文本、菜单项id、菜单项的执行代码、菜单显示风格。

如下表说明:

 

二、动态创建菜单

  1、流程图

 

  2、流程说明:

  如上图,整个建立菜单的过程分成两部分:

初始化菜单和设置菜单属性。

初始化菜单即是以递归的算法从数据源中读取菜单数据,每读一个菜单项建立一个菜单项对象,利用powerbuilder中create方法一级一级建立菜单。

首先定义一个菜单实例对象,这里的菜单是指主菜单,而不是弹出菜单,由于而者的区别,对于弹出菜单的处理在后面介绍。

菜单建立的核心原理很简单,只有四句:

创建菜单对象、挂接菜单项目、先隐藏后显示菜单对象。

如下:

 integerai_item_serial_no//序号,作为递归的函数传入参数

 menuam_obj//菜单对象,作为递归的函数传入参数

 m_menu_itemlam_root//菜单对象,m_menu_item是预先定义的一

              //个菜单对象,该对象没有一个菜单项

 //创建菜单对象

 [ai_item_serial_no]=createm_menu_item

 //将新建的菜单对象,挂接到已有菜单对象上。

 am_obj=[ai_item_serial_no]

 //下面两句用于显示建立好的菜单

 ()//隐藏菜单对象

 ()//显示菜单对象

  将上面的语句放在一个递归过程中,就可以建立起整个的菜单结构。

  在建立菜单的过程中需要得到菜单的itemid,该属性是用来捕获菜单响应动作的唯一标示,只有知道的菜单的itemid,才知道是触发了哪个菜单项的事件。

  得到菜单项itemid的方法,在不同系统经过反复测试之后,发现一个规律:

父项菜单的itemid是从0开始依次递增1,子项菜单的itemid是从10000开始依次递增1。

由此按照递归算法,生成每层每个菜单项的itemid,并存入数据库中。

  设置菜单显示风格,是在菜单建立后设置三种显示风格:

文字风格、图片风格、文字图片混合的显示方式。

为了提高效率,在设置每个菜单风格时,不对所有父项菜单、不可视菜单项和没有定义显示图片的菜单项进行设置,因为文字风格是默认风格不必更改。

这部分程序员主要用到三个API函数:

  Getsubmenu:

用于得到指定菜单项的句柄。

  SetMenuItemBitmaps:

用于设置文字显示风格或设置图片风格,两种情况的区别在于该函数的最后两位若为0,则是去掉菜单项上的位图;最后两位若是图片句柄,则是在菜单项上添加位图。

  ModifyMenu:

用于设置图片显示风格。

  经过反复测试,发现如果指定的显示图片名为“***bmp”等不合法名称,则显示出的效果是一个分割符。

  3、在整个菜单建立过程,需要重点设计的是程序算法、数据存取的方式和出错控制。

  1)、程序算法主要指递归算法,一般递归有两种算法,即FOR循环的方法和DO…while循环方法。

两者都是循环算法,但是效率不同。

建议用户根据自己的能力选择方法,切忌不能写成死循环。

For循环的方式比较简单直观,循环控制遍历的次数,循环内再调用本身,实现递归调用。

DO…while循环方法主要在循环内判断叶子或枝子(即父亲节点),对叶子和枝子进行分别处理,内部也要调用本身,实现递归调用。

  2)、选择合理安全的数据存取方式,对于稳定建立菜单也很重要。

定义一个datastore(数据存储)对象,在初始化菜单时候,将从数据库中提取的所有数据存入该datastore对象,然后不再对数据库进行任何操作,直到需要结束时将变更的菜单数据(如,itemid)以datastore的update形式提交数据库。

在此之前所有需要从datastore得到的数据,用过滤的方式得到,即用setfilter()和filter()函数,一定要注意的是:

按照结对编程的规则,在过滤并使用完datastore中数据后,一定再写一对过滤条件为空字符串的过滤,如下:

  setfilter(“条件1”)

  filter()

  ……处理过程……

  setfilter(“”)

  filter()

  这样也可以将数据及时还原到初始状态,以便下一个模块调用。

  利用datastore,既可以保持在菜单建立期间的数据安全,不受数据库影响;又可以提高效率,省去对数据库的反复读写操作。

  3)、因为菜单的重要性,使得出错控制在菜单建立尤为重要。

我们在递归建立菜单时,要考虑尽可能多的潜在错误,谁也不能保证数据库中的菜单结构数据不出错,虽然正确定义不是建立模块的事。

尤其菜单的二位递进的分层数据结构,若有一处错误,可能导致整个建立过程失败,更糟糕的会发生程序异常退出。

所以程序在设计出错处理时,应当考虑是终止进程,还是跳过错误的环节继续进行。

我建议,在设计程序时应但兼具一定的冗余度和纠错能力。

即遇到错误的数据能够根据环境修正为正确的值,对于可以忽略的一些小问题,为提高效率不作处理。

  需要指出的是,经过反复测试,发现对于菜单的属性,如果是字符类型则不能赋空值,如果没有应当是空字符串,如果是整数类型也不能赋空值,如果没有应当是某个缺省整数。

否则程序会报异常错误,然后退出。

  由此可见,反复测试是非常重要的,不仅能发现语法错误和确保算法的正确,更能找出许多我们难以推断的错误。

三、对弹出菜单的特殊处理

  由于弹出菜单的对象定义和调用方式与主菜单的不同,需要进行一些特殊处理。

首先定义一个菜单实例对象,该对象需有且只有一

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1