LoveUnix » 编程开发 & Rational » 通用菜单程序
让LU留住您的每

一天 让LU博客留住您的每一天
2005-1-14 15:57 kuge2004
简介:<br />curses的菜单库调用实在烦琐,并且菜单定义环节更是需要自己编程解决。前段时间看到网上的老贴--用菜单定义文件实现的那个,但是编程风格不太符合模块化、对象化的风格,并且菜单的选项不够丰富,要想自己扩充功能略显不便。<br /><br />一气之下自己写了一个(不过,我是新人,漏洞百出,不过我觉得编程思想还是对路的,请论坛各位老大多批评!之所以贴出来,就是盼望从大家的意见、建议当中吸取借鉴,完善它!源码公开,大家自己也可以完善它!!字符界面的unix应用还是不少的啊!!)<br /><br />菜单库的特点:选项丰富,可以实现任意列和行的菜单,并具有滚动功能,可以设置菜单的disable项,可以设置颜色...嗨,写起来太麻烦,还有很多预留的扩展功能,如果大家有兴趣,我愿意把完整文档还有hello world版例程贴出来。还有一个自己编的功能精简、支持汉字的form库,如果大家觉得需要可以回贴说明,我再另贴贴出。<br /><br />最大的特色就是定义使用方便,我将在第一贴就贴出它的用法,大家看看如何。<br />菜单库中还有一些功能没有实现:例如在“对象化”(意思就是虽然不是c++,但尽量采用封装思想)的前提下,如何自动恢复被覆盖的屏幕内容,还有一个就是多选,当初设计的时候,由于这个菜单库主要面向命令菜单选择,因此没有加上这个功能。<br /><br />程序组成:<br />一个通用库  gcommon.c及头文件<br />一个菜单库  gmenu.c    及头文件<br />一个常用常量和变量定义头文件 gcdk.h<br /><br /><span style='color:red'>2005-1-15:<br />感谢无双斑竹加精!小弟潜水多日,初次发言,得到一个“精”真是高兴!<br />要说明的是:代码量比较大,注意的话还能看到不完备的注释,那是因为我参考了一些GNU库源码的编辑风格,也是在学习之中,希望程序写得规范化。大家可能看起来比较累。<br />不过提供的5个文件是可以在SCO OSR5.0.7 / gcc 2.95上编译通过的,我尽快贴出hello world版例程,好让大家理解。<br /><br />说了以上这么多,希望大家多题意见,共同完善&#33;</span><br /><br /><span style='color:blue'>2005-1-29:<br />改正了源程序中的一个bug,另外文档资料在抽空写.</span>

2005-1-14 16:08 kuge2004
首先是菜单定义,放到你主程序的头文件中:<br /><br /><!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1--><br /><br />#include &#60;gmenu.h&#62;<br />/* ---------------------------------------------------------------- */<br />/* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MENU DEFINITIONS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */<br />/* ---------------------------------------------------------------- */<br />/* 这里是函数表定义就是菜单序号与功能的关联表 */<br />/* 具体每项什么含义,看后面的gmenu.h类型定义 */<br />/* 当然中间的函数名,是我程序里的,你要替换成自己的处理函数 */<br />static FUNCS functable&#91;&#93; = {<br /> &nbsp; &nbsp;{ 11, &#39;F&#39;, TF_UserPwdChange, &nbsp; &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 12, &#39;F&#39;, TF_UserLogin, &nbsp; &nbsp; &nbsp; &nbsp;NULL &nbsp;}, &nbsp; &nbsp;<br /> &nbsp; &nbsp;{ 13, &#39;F&#39;, TF_UserManager, &nbsp; &nbsp; &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 14, &#39;F&#39;, TF_ResetUserPwd, &nbsp; &nbsp; NULL &nbsp;},<br /> &nbsp; &nbsp;{ 21, &#39;F&#39;, TF_InquireFee, &nbsp; &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 22, &#39;F&#39;, TF_PrintBankbook, &nbsp; &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 23, &#39;F&#39;, TF_ChangeBankbook, &nbsp; NULL &nbsp;},<br /> &nbsp; &nbsp;{ 31, &#39;F&#39;, TF_BatchDownload, &nbsp; &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 32, &#39;F&#39;, TF_BuildUploadFile, &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 33, &#39;F&#39;, TF_ImportBatchFile, &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 34, &#39;F&#39;, TF_Saving, &nbsp; &nbsp; &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 35, &#39;F&#39;, TF_CheckDayAccounts, NULL &nbsp;},<br /> &nbsp; &nbsp;{ 35, &#39;F&#39;, TF_DayFinalOperate, &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 37, &#39;F&#39;, TF_PrintReport, &nbsp; &nbsp; &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 41, &#39;F&#39;, TF_PayersManage, &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ 42, &#39;F&#39;, TF_ParamSetup, &nbsp; &nbsp; &nbsp; NULL &nbsp;},<br /> &nbsp; &nbsp;{ &nbsp;5, &#39;F&#39;, TF_Exiting, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ &nbsp;0, &#39;@&#39;, NULL, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL &nbsp;}<br />};<br /><br />/* Menu Definitions */<br />/* 定义菜单的功能序号(跟上面的关联)、菜单项名称、子菜单 */<br />/* 可以看到这里就可以定义菜单之间的关联了 */<br />/* 每个数组代表一个菜单,子菜单只要说明指向的数组就行啦 */<br />/* 结构定义也在gmenu.h中 */<br />/* itemid, name, desc, opts, subitems, submenu, imenu, userptr, index, y, x */<br />static ITEM mi_360&#91;&#93; = {<br /> &nbsp;{ 361, &#34;361 代扣成功清单&#34; },<br /> &nbsp;{ 362, &#34;362 存盘失败记录&#34; }, <br /> &nbsp;{ 363, &#34;363 代扣失败清单&#34; },<br /> &nbsp;{ 364, &#34;364 按开户局分类汇总报表&#34; },<br /> &nbsp;{ 0 }<br />}&#59;<br /><br />static ITEM mi_101&#91;&#93; = {<br /> &nbsp;{ 11, &#34;11 更改柜员密码&#34; },<br /> &nbsp;{ 12, &#34;12 重新登录&#34; &nbsp; &nbsp; },<br /> &nbsp;{ 13, &#34;13 柜员信息维护&#34; },<br /> &nbsp;{ 14, &#34;14 重置柜员密码&#34; },<br /> &nbsp;{ 0 }<br />}&#59;<br /><br />static ITEM mi_102&#91;&#93; = {<br /> &nbsp;{ 11, &#34;11 更改柜员密码&#34; },<br /> &nbsp;{ 12, &#34;12 重新登录&#34; &nbsp; &nbsp; },<br /> &nbsp;{ 0 }<br />}&#59;<br /><br />static ITEM mi_20&#91;&#93; = {<br /> &nbsp;{ 21, &#34;21 查询款项&#34; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br /> &nbsp;{ 22, &#34;22 打印记录&#34; },<br /> &nbsp;{ 23, &#34;23 更换登记卡&#34; },<br /> &nbsp;{ 0 }<br />}&#59;<br /><br />static ITEM mi_30&#91;&#93; = {<br /> &nbsp;{ 31, &#34;31 批量下载数据&#34; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br /> &nbsp;{ 32, &#34;32 生成代扣文件&#34; },<br /> &nbsp;{ 33, &#34;33 导入代扣结果&#34; },<br /> &nbsp;{ 34, &#34;34 存盘&#34; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;},<br /> &nbsp;{ 35, &#34;35 对当日帐&#34; &nbsp; &nbsp; },<br /> &nbsp;{ 36, &#34;36 日终处理&#34; &nbsp; &nbsp; },<br /> &nbsp;{ 37, &#34;37 报表打印&#34;, &#34;&#34;, ITO_DEFAULT, mi_360 },<br /> &nbsp;{ 0 }<br />}&#59;<br /><br />static ITEM mi_40&#91;&#93; = {<br /> &nbsp;{ 41, &#34;41 资料维护&#34; },<br /> &nbsp;{ 42, &#34;42 业务参数维护&#34; &nbsp; }, <br /> &nbsp;{ 0 }<br />}&#59;<br /><br />/**************MAIN MENUS*********************/<br />static ITEM mi_main1&#91;&#93; = {<br /> &nbsp;{ 1, &#34;1 柜员功能&#34;, &#34;&#34;, ITO_DEFAULT,mi_101 }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br /> &nbsp;{ 2, &#34;2 前台操作&#34;, &#34;&#34;, ITO_DEFAULT,mi_20 &nbsp;},<br /> &nbsp;{ 3, &#34;3 后台操作&#34;, &#34;&#34;, ITO_DEFAULT,mi_30 &nbsp;},<br /> &nbsp;{ 4, &#34;4 系统维护&#34;, &#34;&#34;, ITO_DEFAULT,mi_40 &nbsp;},<br /> &nbsp;{ 5, &#34;5 退出系统&#34; &nbsp; },<br /> &nbsp;{ 0 }<br />}&#59;<br /><br /><!--c2--></div><!--ec2-->

2005-1-14 16:13 kuge2004
精华来了,看我怎么调用吧:<br /><!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1--><br /> <br />/* 用popup_menu_byitems弹出根菜单,其它参数定义菜单大小位置,请看gmenu.c中的原型 */<br />/* 函数会把用户选择的菜单项序号传给rtn */<br /> rtn=popup_menu_byitems&#40;mi_main1, 0, 0, 3, 0&#41;;<br />/* 用封装好的函数Get_Func_Ord找出函数对照表中的函数指针,然后调用,就这么简单 */<br /> if &#40; &#40;i=Get_Func_Ord&#40;functable,rtn&#41; &#41;&#62;0 &#41;{<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#40;* functable&#91;i&#93;.pfunc&#41;&#40;&#41;;<br /><br /><!--c2--></div><!--ec2-->

2005-1-14 16:14 kuge2004
<span style='font-size:14pt;line-height:100%'><b>源代码改成附件了:</b></span>

2005-1-14 19:59 jxppp
顶一下.

2005-1-15 12:41 无双
good <br /><br />虽然没有编译

2005-1-17 23:16 fanbing66
历害,小弟也得向这个水平发展

2005-1-24 10:30 wbxaa1
老大能不能把例程发给我?先谢谢了。w_b_xaa@sina.com

2005-1-25 08:56 kuge2004
hello world版例程<br /><!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->#include &#34;gmenu.h&#34;<br /><br />static FUNCS functable&#91;&#93; = {<br /> &nbsp; &nbsp;{ &nbsp;1, &#39;F&#39;, TF_Hello, &nbsp; &nbsp;NULL &nbsp;},<br /> &nbsp; &nbsp;{ &nbsp;0, &#39;@&#39;, NULL, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NULL &nbsp;}<br />};<br /><br />static ITEM mi&#91;&#93; = {<br /> &nbsp;{ 1, &#34;1 Selection1&#34; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br /> &nbsp;{ 1, &#34;2 Selection2&#34; &nbsp; },<br /> &nbsp;{ 1, &#34;3 Selection3&#34; &nbsp; },<br /> &nbsp;{ 0 }<br />};<br /><br />static int<br />TF_Hello&#40;&#41;<br />{<br /> &nbsp; &nbsp;mvprintw&#40;LINES-1, 0, &#34;Hello world&#33;&#34;&#41;; &nbsp;<br /> &nbsp; &nbsp;return 1;<br />}<br /><br />extern int<br />main&#40;&#41;<br />{<br /> &nbsp; &nbsp;int &nbsp;rtn;<br /> &nbsp; &nbsp;<br /> &nbsp; &nbsp;win_initial&#40;&#41;;<br /> &nbsp; &nbsp;<br /> &nbsp; &nbsp;rtn = popup_menu_byitems&#40;mi, 0, 0, 3, 1&#41;;<br /> &nbsp; &nbsp;if &#40; Get_Func_Ord&#40;functable,rtn&#41; &#62;= 0 &#41;{<br /> &nbsp; &nbsp; &nbsp; &nbsp;&#40;* functable&#91;i&#93;.pfunc&#41;&#40;&#41;;<br /> &nbsp; &nbsp;}<br /> &nbsp; &nbsp;<br /> &nbsp; &nbsp;win_end&#40;&#41;;<br />}<!--c2--></div><!--ec2-->

2005-1-25 09:03 kuge2004
截了一个屏,用的是这个菜单库。

2005-1-25 13:01 wbxaa1
运行成功了界面如下:<br /><img src='http://www.loveunix.net/bbs/uploads/a1.gif' border='0' alt='user posted image' />

2005-1-25 13:10 wbxaa1
我想得到如下的程序界面能帮帮我吗?<br /><img src='http://www.loveunix.net/bbs/uploads/abc.gif' border='0' alt='user posted image' />

2005-1-26 16:19 tangxb
强!这是我在网上见到的最好的示例了,启发很大。

2005-1-26 18:50 无双
互相交流 <!--emo&:)--><img src='style_emoticons/default/smile.gif' border='0' style='vertical-align:middle' alt='smile.gif' /><!--endemo-->

2005-1-27 17:28 xjx79
能否发给我一份开发文档亚,谢谢了,<br />xjx7794cn@163.com

2005-1-28 10:01 wbxaa1
kuge2004,有一个问题。在调用popup_menu_byitems函数后若再次调用则就会报段错误(core dumped),请问在第二次调用之前是不是要进行什么处理?谢谢。<br />

2005-1-28 11:00 tangxb
wbxaa1兄,我这边做测试没问题啊,你把你的程序段贴出来看看

2005-1-28 14:38 wbxaa1
................. <br />ch=getch();<br />      switch(ch)<br />        {<br />          case 10:  /*当按下enter时显示菜单,选择相应的菜单后程序返回(在这里返回后没有进行任何操作)。当要再次显示菜单(再次按下enter)就报错了。*/<br />                  rtn = popup_menu_byitems(mi_main1, 0, 0, 5, 10);<br />                  break;<br />       ..........

2005-1-28 21:00 kuge2004
应该没问题的,菜单肯定要反复调用的,我的程序中没有出现这种情况,你能把调菜单涉及到的定义、函数完整的贴出来吗?<br />文档正在整理之中。<br /><br />两个可能的错误:<br /><br />一是所有菜单项数组要以NULL结束,因为动态的,靠他来知道大小.<br /><br />二是代码里有个bug,发生在gmenu.h的popup_menu_byitems()函数开头,<br /><!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1--> items=&#40;ITEM **&#41;calloc&#40;ARRAY_SIZE&#40;names&#41;,sizeof&#40;ITEM *&#41;&#41;;<br /> &nbsp; &nbsp;if &#40;&#33;items&#41;<br /> &nbsp; &nbsp; &nbsp; &nbsp;return E_SYSTEM_ERROR; &nbsp; &nbsp;<!--c2--></div><!--ec2--><br />改为:<br /><!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->for &#40;i=0; names&#91;i&#93;; i++&#41;<br /> &nbsp; &nbsp;NULL;<br />items=&#40;ITEM **&#41;calloc&#40;i+1,sizeof&#40;ITEM *&#41;&#41;;<br />if &#40;&#33;items&#41;<br /> &nbsp; &nbsp;return E_SYSTEM_ERROR;<!--c2--></div><!--ec2--><br />因为names是**,不能用sizeof算大小

2005-1-30 17:46 abist
<br />我对C不太懂,正在学,很喜欢你的这个程序,能否给我一些例子和开发文档,谢谢!<br />另:能否给我你的联系方式?<br />                             wwjfa@163.com

2005-1-31 10:26 wbxaa1
菜单定义如下:<br />static ITEM mi_101[] = {<br /> { 11, &quot;11 设备入库&quot; },<br /> { 12, &quot;12 入库查询&quot; },<br /> { 0 }<br />};<br /><br />static ITEM mi_20[] = {<br /> { 21, &quot;21 设备出库&quot; },<br /> { 22, &quot;22 出库查询&quot; },<br /> { 0 }<br />};<br /><br />static ITEM mi_30[] = {<br /> { 31, &quot;31 库存查询&quot; },<br /> { 32, &quot;32 库存打印&quot; },<br /> { 0 }<br />};<br /><br />static ITEM mi_40[] = {<br /> { 41, &quot;41 密码修改&quot; },<br /> { 42, &quot;42 资料修改&quot; },<br /> { 0 }<br />};<br /><br />static ITEM mi_main1[] = {<br /> { 1, &quot;1 设备入库管理&quot;,&quot;&quot;, ITO_DEFAULT,mi_101 },<br /> { 2, &quot;2 设备出库管理&quot;,&quot;&quot;, ITO_DEFAULT,mi_20  },<br /> { 3, &quot;3 设备库存管理&quot;,&quot;&quot;, ITO_DEFAULT,mi_30  },<br /> { 4, &quot;4 操作人员管理&quot;,&quot;&quot;, ITO_DEFAULT,mi_40  },<br /> { 5, &quot;5 退出系统&quot;   },<br /> { 0 }<br />};<br /><br /><br /><br />/*&quot;一是所有菜单项数组要以NULL结束,因为动态的,靠他来知道大小.&quot;是什么意思啊?*/<br />

2005-1-31 13:58 无双
最后一个定义应该是<br />也就是<br /><br /> { 0 }<br /><br />看上面数组的最后一个<br /><br />

2005-1-31 15:17 wbxaa1
我的菜单定义有问题吗?

2005-1-31 22:46 abist
kuge2004,能给个完整的例子吗,如菜单程序调用?

页: [1] 2 3
查看完整版本: 通用菜单程序


Powered by Discuz! Archiver 5.5.0  © 2001-2006 Comsenz Inc.