PowerBuilder动态创建菜单条
- 格式:doc
- 大小:39.00 KB
- 文档页数:12
动态创建菜单条2008年12月13日星期六1:41本文拟结合powerbuilder语言,简述如何实现动态添加菜单效果。
在实际开发过程当中很多时候会因为权限控制的需要,根据用户的不同权限来动态添加菜单项目,如何避免使用繁琐的api函数(如:createmenu、insertmenu、insertmenuitem、appendmenu等),利用powerbuilder语言自身功能达到这一目的呢?本文将就此问题简单予以论述。
一、基本思路在pb帮助的menu object一节当中,关于其properties描述当中有一项:item[ ] menu specifies the menu objects under a menu object.这看似简单的一句话其实包含了三层含义:1、这句话说明menu对象有一个属性为数组类型,它其中的各个元素记录了其所有的具体子item项目,可以借助这个数组中各元素来访问底层的各子菜单;2、这些子item项目仍是menu类型,因此可以按照第一点的逻辑继续向下层推广,借助该子item的item[]属性可以进而访问其所属下层的第二层子菜单,推而广之,即可全面遍历整个菜单体系的所有子菜单项目;3、既然该属性是一个数组类型,那么就可以按照数组类型变量来处理,我们可以对其进行upperbound()、lowerbound()等函数操作,还可以进行数组的扩展,即添加新项目,这一点很重要,它是我们整篇文章的核心,如何利用pb实现动态添加菜单,说白了就是添加这个数组元素(读者必须对此有一个清晰的认识),同时期间有一些配套具体的实现技巧,详见下文。
二、具体实现(一)基本工作创建一个window窗口和二个menu菜单,其中一个菜单命名为m_main,用作窗口的基本主菜单,新增菜单将在其上添加,该菜单初始可以包含一些基本菜单,如:文件、添加、删除、保存、退出等;另外一个菜单命名为m_new,该菜单只有主菜单一个item,其下没有进一步的子菜单,因此该菜单其实就是一个菜单item。
一、PowerBuilder 9.0开发环境简介1. 主窗口主窗口中有一行菜单栏和一行工具栏。
工具栏上的图标与某一个菜单条相对应,主要的菜单项有:File菜单项、Run菜单项、Tools菜单项等。
2. 画板画板实际上就是完成一定功能的工具窗口。
其中主要的画板及其功能介绍如下:Application painter应用画板:指定应用级的属性和编写应用级的脚本Database painter数据库画板:管理数据库,设置数据库的访问控制,维护数据以及创建新表DataWindow painter数据窗口画板:创建数据窗口对象Data pipeline painter数据管道画板:创建数据管道对象,从一个数据源向另一个数据源传输数据Function painter函数画板:创建全局函数Library painter库管理画板:创建和管理PowerBuilder的应用库Menu painter菜单画板:创建菜单对象Project painter工程画板:创建可执行文件、动态库、组件和代理对象Query painter查询画板:图形化方式定义SQL Select语句,并保存为Query 对象,供数据窗口或数据管道使用Select painter Select语句画板:为数据窗口或数据管道设置SQL Select 语句Structure painter结构画板:创建全局结构User Object painter用户对象画板:创建用户对象Window painter窗口画板:创建窗口对象3. 工具栏工具栏显示在窗口顶部。
如图所示。
其中各图表的含义如下:New…创建…Inherit…继承…1Open…打开…Run/Preview…运行或预览对象Exit 退出PB系统Incremental Build Workspace 对增加的工作空间编译联接Full Build Workspace 对全部工作空间编译联接Deploy Workspace 配置工作空间Debug 跟踪当前的应用Select and Debug 选择跟踪Run 运行当前的应用Select and Run 选择运行Skip Operation 越过操作Stop Operation 停止操作Library Painter…打开应用库管理画板Database Profile…定义数据库连接EA Server Profile…定义一个特定数据库的连接参数Database Painter…打开数据库管理画板File Editor…在文件编辑器中编辑文本文件System Tree 系统树型窗Output 输出窗口二、PowerBuilder应用程序开发步骤下面以“计算圆面积”应用程序的开发过程为例进行说明。
在PowerBuilder中实现菜单条级权限的设置在一个网络应用程序中,对不同的使用人员授与不同的程序使用权是非常重要的。
一般的应用程序都分:录入权,查询权,修改权,审核权等等,很多功能可细分到菜单条级,才能方便管理,不同的功能应用应该授与不同工作性质的人员,才能使一个公司或团体分工明确,责任清晰,实现规范化管理。
对系统管理人员来说灵活方便地设置不同人员的对程序的不同权限,并能够不以用户身份进入程序也能查看到用户所拥有的权限,这是后台管理程序最基本的要求。
本人通过实践摸索在PB中实现了用户程序到菜单条级权限的设置和查看。
此模块方便之处是管理员在设置用户权限时所见的菜单与用户所用的菜单一致,用户有哪些权限一目了然。
我们先来看PB与此相关的两个函数:Mid and Replace1.函数Mid ( string, start {, length} )取string字串中第start项后的length位字串。
例:Mid("ABCDEFG",3,2)返回值:"DE"2.函数Replace ( string1, start, n, string2 ) 替换string1中第start 项后n位,用string2 串。
例:Replace ( "ABCDEFGH",3,2,"abc" ) 返回值:"ABCabcFGH"到此可能用过PB的朋友已能猜出这两个函数就是在PB中实现菜单条权限定义的基础。
我们先假设我们应用程序的菜单如下图:M_1 M_2 M_3 ......M1_1 M2_1 M3_1M1_2 M2_2 M3_2M1_3 M2_3 M3_3M1_4 M2_4 M2_5 要求菜单条变量名的定义严格按照矩阵方式定义。
然后复制一份与应用程序菜单一样的菜单模式,用于系统授权模块使用,包括菜单条变量名也一样,只不过菜单条下无调用程序代码,而是菜单状态设置函数。
VBA中的菜单与工具栏的自定义自定义菜单和工具栏是VBA编程中非常有用的功能。
通过自定义菜单和工具栏,我们可以为VBA应用程序增加更多的功能和交互性,以提高用户体验和效率。
本文将介绍如何在VBA中进行菜单和工具栏的自定义,以及一些常用的技巧和注意事项。
一、自定义菜单在VBA中,可以通过代码来自定义菜单条目、快捷键和相应的事件。
下面是一个简单的示例,展示了如何创建一个自定义菜单:Sub CustomizeMenu()'创建一个弹出菜单并添加菜单条目Dim menuBar As CommandBarSet menuBar = mandBars.Add("Custom Menu", msoBarPopup)Dim menuItem As CommandBarControlSet menuItem = menuBar.Controls.Add(Type:=msoControlButton)With menuItem.Caption = "菜单项1".OnAction = "MenuItem1_Click"End With'显示菜单menuBar.ShowPopupEnd SubSub MenuItem1_Click()'在此处编写菜单项1的点击事件处理代码End Sub以上代码通过创建一个弹出菜单“Custom Menu”,并在菜单中添加了一个菜单项“菜单项1”。
点击菜单项时,会触发“MenuItem1_Click”事件处理过程。
需要注意的是,菜单项的点击事件应该单独编写,用于处理菜单项的具体操作。
二、自定义工具栏除了自定义菜单,我们还可以在VBA中自定义工具栏,以方便用户进行常用操作的快速访问。
下面是一个简单的示例,展示了如何创建一个自定义工具栏:Sub CustomizeToolbar()'创建一个新的工具栏,并指定位置和名称Dim toolbar As CommandBarSet toolbar = mandBars.Add(Name:="Custom Toolbar", Position:=msoBarTop)'添加工具栏按钮Dim toolbarButton As CommandBarButtonSet toolbarButton = toolbar.Controls.Add(Type:=msoControlButton) With toolbarButton.Caption = "按钮1".OnAction = "ToolbarButton1_Click".Style = msoButtonIconAndCaption.FaceId = 3End With'显示工具栏toolbar.Visible = TrueEnd SubSub ToolbarButton1_Click()'在此处编写工具栏按钮1的点击事件处理代码End Sub以上代码创建了一个新的工具栏“Custom Toolbar”,并在工具栏中添加了一个按钮“按钮1”。
PB控件使用介绍一、PB中使用Microsoft Web Browser控件步骤:在pb的某窗口中加入OLE对象,选择Insert control(插入控件),然后选中"Microsoft WEB 浏览器",(随系统而定的版本),就可以在这个窗口直接使用IE浏览器控件了。
常用函数:(对这个ole控件取名叫ole_web)ole_web.object.navigate(string ls_url) file://浏览某url,譬如:ole_web.object.navigate('') 就是浏览 页面,当然支持本地文件,也支持本地图片文件的浏览,如jpeg,jpg,gif,png等等,如果是不支持的文件,则直接弹出选择打开文件对话框,和ie一模一样。
ole_web.object.goback() file://回退(如果没有内容可退,则会弹出错误,可以屏蔽该错误)ole_web.object.goforward() file://前进,同上常用事件:documentcomplete : url请求的页面完成;downloadcomplete:url中请求的下载完成;常用属性:ole_web.object.width :pixel高度,需要转换为pbunit高度才可以调整ole_web.object.height:同上ole_web.object.offline:离线方式,true,false两者之一你甚至可以用pb写出一个和ie类似的界面用来进行浏览网页或图片。
二、在程序中打印在程序中如何提供打印功能呢?这里有三种调用打印函数的格式可供选择。
1. 对数据窗口控制或者数据窗口可以使用这种打印格式。
DATAWINDOWNAME.Print(cancel_window)这里cancel_window 是一个布尔值,它指出是否要显示一个用户可以用来中止打印动作的窗口。
MFC 单文档中动态添加菜单项和响应菜单事件新建一个单文档程序在查看菜单项中增加两个子菜单,分别为隐藏工具栏(ID_HIDE),新建菜单(ID_NEWMENU) 在Resource.h中增加一个ID_NEWMENU宏#define ID_NEWMENU WM_USER+101操作工具栏和状态栏使用GetDescendantWindow函数获取工具栏和状态栏的指针为ID_HIDE添加消息映射,编辑代码如下static bool m_Hide=false;m_Hide=!m_Hide;//获取工具栏指针CWnd* pWndToolBar=(CWnd*)GetDescendantWindow(AFX_IDW_TOOLBAR);//获取状态栏指针CWnd* pWndStatusBar=(CWnd*)GetDescendantWindow(AFX_IDW_STATUS_BAR);CMenu* pMenu=GetMenu();CMenu* pSubMenu=pMenu->GetSubMenu(2);if(m_Hide){pSubMenu->ModifyMenu(ID_HIDE,MF_BYCOMMAND,ID_HIDE,"显示工具栏");if(pWndStatusBar!=NULL) pWndStatusBar->SetWindowText("隐藏工具栏");if(pWndToolBar!=NULL) pWndToolBar->ShowWindow(SW_HIDE);}else{pSubMenu->ModifyMenu(ID_HIDE,MF_BYCOMMAND,ID_HIDE,"隐藏工具栏");if(pWndStatusBar!=NULL) pWndStatusBar->SetWindowText("显示工具栏");if(pWndToolBar!=NULL) pWndToolBar->ShowWindow(SW_SHOW);}动态添加子菜单为ID_NEWMENU增加消息映射,编辑代码如下static UINT m_NewMenu=ID_NEWMENU+1;//获取菜单CMenu* pMenu=GetMenu();//获取索引为2的菜单项,即第3列菜单CMenu* pSubMenu=pMenu->GetSubMenu(2);char buffer[1];itoa(m_NewMenu-ID_NEWMENU,buffer,10);if(m_NewMenu<=ID_NEWMENU+5){pSubMenu->AppendMenu(MF_SEPARATOR); //分隔线pSubMenu->AppendMenu(MF_STRING | MF_ENABLED,m_NewMenu++,CString("新的菜单")+buffer);}//如果m_bAutoMenuEnable为true,则会依次检查View、Document、Frame的//消息映射表是否有这个弹出菜单中每个菜单项的处理函数,澳门新濠天地官网 如果没有就会把那一项改为灰的m_bAutoMenuEnable=false;添加OnCommand的消息映射用来响应添加的子菜单项,代码如下UINT uMsg=LOWORD(wParam);for(UINT i=ID_NEWMENU+1;i<=ID_NEWMENU+5;i++)if(uMsg==i){char buffer[1];itoa(i-ID_NEWMENU,buffer,10);MessageBox(CString("新的菜单") + buffer);}右键菜单在View类中添加OnRButtonDown的消息映射,代码如下CMenu pPopMenu;pPopMenu.CreatePopupMenu();if(pPopMenu==NULL);pPopMenu.AppendMenu(MF_STRING,ID_NEWMENU+6,"右键菜单");this->ClientToScreen(&point);pPopMenu.TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this);在View类中添加OnCommand的消息映射用来响应右键菜单的事件UINT uMsg=LOWORD(wParam);if(uMsg==ID_NEWMENU+6)MessageBox(CString("右键菜单"));。
动态创建菜单条2008年12月13日星期六1:41本文拟结合powerbuilder语言,简述如何实现动态添加菜单效果。
在实际开发过程当中很多时候会因为权限控制的需要,根据用户的不同权限来动态添加菜单项目,如何避免使用繁琐的api函数(如:createmenu、insertmenu、insertmenuitem、appendmenu等),利用powerbuilder语言自身功能达到这一目的呢?本文将就此问题简单予以论述。
一、基本思路在pb帮助的menu object一节当中,关于其properties描述当中有一项:item[ ] menu specifies the menu objects under a menu object.这看似简单的一句话其实包含了三层含义:1、这句话说明menu对象有一个属性为数组类型,它其中的各个元素记录了其所有的具体子item项目,可以借助这个数组中各元素来访问底层的各子菜单;2、这些子item项目仍是menu类型,因此可以按照第一点的逻辑继续向下层推广,借助该子item的item[]属性可以进而访问其所属下层的第二层子菜单,推而广之,即可全面遍历整个菜单体系的所有子菜单项目;3、既然该属性是一个数组类型,那么就可以按照数组类型变量来处理,我们可以对其进行upperbound()、lowerbound()等函数操作,还可以进行数组的扩展,即添加新项目,这一点很重要,它是我们整篇文章的核心,如何利用pb实现动态添加菜单,说白了就是添加这个数组元素(读者必须对此有一个清晰的认识),同时期间有一些配套具体的实现技巧,详见下文。
二、具体实现(一)基本工作创建一个window窗口和二个menu菜单,其中一个菜单命名为m_main,用作窗口的基本主菜单,新增菜单将在其上添加,该菜单初始可以包含一些基本菜单,如:文件、添加、删除、保存、退出等;另外一个菜单命名为m_new,该菜单只有主菜单一个item,其下没有进一步的子菜单,因此该菜单其实就是一个菜单item。
在主窗口中声明实例变量(instance variables):menu im_new[] //声明一菜单数组用于引用新增菜单integer ii_count //声明一变量记录总共新增菜单个数(二)具体代码1、添加一级菜单功能的实现://////////////////////////////////////////////////用途:在最后一项以及菜单之后新增一项一级菜单//时间:2003-6-1////////////////////////////////////////////////integer li_itemcount //声明变量记录当前一级菜单总个数;//新创建一个菜单对象,并将其放到菜单数组im_new[]当中;ii_count++im_new[ii_count]=create m_new//此处对新创建的菜单对象获取引用;li_itemcount=upperbound(m_main.item[])m_main.item[li_itemcount + 1]=im_new[ii_count].item[1]//下面是设置新生成菜单的text属性,这个属性可以从数据库中取,但此处省略简化掉了;m_main.item[li_itemcount + 1].text="新增一级-" + string(li_itemcount + 1)//下面是设置新生成菜单的tag属性,这个属性可以从数据库中取,但此处省略简化掉了;//通过这个tag可以当作功能号等来使用,通过gf_menumessage()函数来予以公共处理;//m_main.item[li_itemcount + 1].tag="xxxxxxxxx"//此处来将新生成的菜单对象显示出来;m_main.item[1].hide()m_main.item[1].show()2、添加二级菜单功能的实现://////////////////////////////////////////////////用途:在最后一项一级菜单下新增一项二级菜单//时间:2003-6-1//////////////////////////////////////////////////声明变量记录当前一级菜单总个数、最后一项一级菜单对应的二级菜单总个数;integer li_precount,li_itemcount//新创建一个菜单对象,并将其放到菜单数组im_new[]当中;ii_count++im_new[ii_count]=create m_new//此处对新创建的菜单对象获取引用;li_precount=upperbound(m_main.item[])li_itemcount=upperbound(m_main.item[li_precount].item[])m_main.item[li_precount].item[li_itemcount + 1]=im_new[ii_count].item[1]//下面是设置新生成菜单的text属性,这个属性可以从数据库中取,但此处省略简化掉了;m_main.item[li_precount].item[li_itemcount + 1].text="新增二级-" + string(li_precount) + "-" + string(li_itemcount + 1)//下面是设置新生成菜单的tag属性,这个属性可以从数据库中取,但此处省略简化掉了;//通过这个tag可以当作功能号等来使用,通过gf_menumessage()函数来予以公共处理;//m_main.item[li_precount].item[li_itemcount + 1].tag="xxxxxxxxx"//此处来将新生成的菜单对象显示出来;m_main.item[1].hide()m_main.item[1].show()3、添加三级菜单功能的实现://////////////////////////////////////////////////用途:在最后一项二级菜单下新增一项三级菜单//时间:2003-6-1//////////////////////////////////////////////////声明变量记录当前一级菜单总个数、最后一项一级菜单对应的二级菜单总个数;integer li_fircount,li_precount,li_itemcount//新创建一个菜单对象,并将其放到菜单数组im_new[]当中;ii_count++im_new[ii_count]=create m_new//此处对新创建的菜单对象获取引用;li_fircount=upperbound(m_main.item[])li_precount=upperbound(m_main.item[li_fircount].item[])if li_precount = 0 thenmessagebox("提示","请先点击-添加二级菜单-按钮创建一个二级菜单,:)")returnend ifli_itemcount=upperbound(m_main.item[li_fircount].item[li_precount].item[])m_main.item[li_fircount].item[li_precount].item[li_itemcount + 1]=im_new[ii_count].item[1]//下面是设置新生成菜单的text属性,这个属性可以从数据库中取,但此处省略简化掉了;m_main.item[li_fircount].item[li_precount].item[li_itemcount + 1].text="新增三级-" + string(li_fircount) &+ "-" + string(li_precount) + "-" + string(li_itemcount + 1)//下面是设置新生成菜单的tag属性,这个属性可以从数据库中取,但此处省略简化掉了;//通过这个tag可以当作功能号等来使用,通过gf_menumessage()函数来予以公共处理;//m_main.item[li_precount].item[li_itemcount + 1].tag="xxxxxxxxx"//此处来将新生成的菜单对象显示出来;m_main.item[1].hide()m_main.item[1].show()4、处理动态生成菜单的clicked事件:总体思想是采用参数化思想,借助统一的函数,根据函数参数不同来予以不同处理。
(1)处理m_new对象的clicked事件:////////////////////////////////////////////////////////////////////////////用途:根据新生成的各菜单所对应的功能号,即从数据库中取出的tag属性// 来调用gf_menumessage()全局函数来实现不同的系统功能;//时间:2003-6-1////////////////////////////////////////////////////////////////////////////此处本应该去调用gf_menumessage()全局函数来处理不同功能所对应要处理的功能号,//但此处均略掉了,具体内容可参见gf_menumessage() 函数;//此处仅仅演示一个messagebox()功能,如下;//integer li_ret//li_ret = gf_menumessage(this.tag)//下面代码是避免点击含有下一级子菜单的菜单时会弹出对话框,导致无法显示下一级菜单的情况;if upperbound(this.item[]) > 0 thenreturnend ifmessagebox("动态菜单演示","您当前点击的菜单是:" + this.text)(2)编写gf_menumessage函数:////////////////////////////////////////////////////////////////////////////用途:根据新生成的各菜单所对应传进来的功能号,即从数据库中取出的tag属性// 来动态判断所要进行的操作;//时间:2003-6-1//输入:string 型as_funcode:对应传进来的菜单要实现的功能号;//输出:integer型1:成功// -1:失败////////////////////////////////////////////////////////////////////////////注:根据新生成的各菜单所对应传进来的功能号,即从数据库中取出的tag属性// 来动态判断所要进行的操作;此操作需要连接数据库,故此处简列思路,具体略string ls_funcode //声明一变量用于记录传进来的功能号;ls_funcode = as_funcodechoose case ls_funcodecase "1"//......比如1 代表入库管理,则去调用入库管理函数gf_rk()等等case "2"//......比如1 代表出库管理,则去调用出库管理函数gf_ck()等等//......case elsereturn -1end choosereturn 1////////////////////////////////////////////////////////////////////////////////////////////////////// ////曾经在一些书上看到用C语言实现动态菜单的方法,需要调用大量的API函数,但是这里我想换一种方法,借助PowerBuilder提供的属性和递归算法实现动态菜单的创建过程。