完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近在做一个多级菜单项目,看了很多资料,大体分两种设计思路:1、通过双向链表实现;2、通过数组实现。思路无非是把菜单联系起来,可以跳到下级菜单,也可以返回上级菜单。用傻孩子的双向链表的方法,大体上实现了。但是有些细节没有想明白,感觉代码写的一团糟。现在发帖,和大家一起谈论下。
傻孩子给的历程,一会我以附件的形式给出。 /*********************** * 结构体宏定义 * ***********************/ struct MenuItem { char MenuCount; //本级菜单项目数 char *DisplayString; //本菜单显示字符串 void (*Subs)(); //本菜单对应的功能函数,可以为NULL struct MenuItem *ChildrenMenus; //下级菜单指针,可以为NULL struct MenuItem *ParentMenus; //上级菜单指针,可以为NULL }NULL_MENU; 问题1: char *DisplayString 这个变量有必要吗? 只给显示函数函数要显示的内容,不给坐标,有什么用? 问题2: 按着下面给出的历程,每个按键的功能,在每个界面都是一样的,如果不同的界面,按键含义不同,怎处理? 问题3: void (*Subs)()指向的函数,只有当按下Enter键时候才执行,也就是说void (*Subs)()指向的函数一旦返回,就不能再进入。这样就有问题,当用户要输入参数时候,加入没有输入完,函数是不能返回的,这个时候就会阻塞main函数,怎么解决? int main() { short KeyNum = 0xff; SystemInitialation(); //系统初始化 ShowMenu(); while(1) { ClearWatchDog(); //喂狗 KeyNum = GetKeyNum(); //获取按键值 /*******************目录操作*********************/ /*************************************** * [按键说明] * * ----------------------------------- * * [K1] UP(向上) * * [K5] Down(向下) * * [K2] Esc(后退) * * [K6] Enter(确定) * * [K3] 返回根目录 * ***************************************/ if (KeyNum != 0xff) { ShowMenu(); switch(KeyNum) { case UP: UserChoose --; if (UserChoose < 0) { UserChoose = MaxItems-1; } break; case Esc: if (MenuPoint[0].ParentMenus != &Null) { MenuPoint = MenuPoint[0].ParentMenus; UserChoose = 0; DisplayStart = 0; } break; case Down: UserChoose ++; if (UserChoose == MaxItems) { UserChoose = 0; } break; case Enter: if (MenuPoint[UserChoose].Subs != NullSubs) { (*MenuPoint[UserChoose].Subs)(); } else if (MenuPoint[UserChoose].ChildrenMenus != &Null) { MenuPoint = MenuPoint[UserChoose].ChildrenMenus; UserChoose = 0; DisplayStart = 0; } break; case Reset: MenuPoint = MainMenu; UserChoose = 0; DisplayStart = 0; break; } if ((UserChoose < DisplayStart) || (UserChoose > (DisplayStart+3))) { DisplayStart = UserChoose; } ShowMenu(); } /*******************目录操作*********************/ } } 傻孩子菜单历程.rar (3.42 KB ) |
|
相关推荐
34个回答
|
|
ST官方有一个软件包STM32F10x_AN2790_FW_V2.0.0,里面有一个简单的菜单结构,最近我自己做的一个菜单就是按照里面的菜单结构的思路扩充的,可以参考一下
menu.zip (9.52 KB ) |
|
|
|
怎么没有人呢?
|
|
|
|
目前用二维数组来做多级菜单,效果还可以,虽然没有链表做菜单强,但胜在节省了很多SRAM,在SRAM资源充足的情况下还是建议用链表不要用数组
|
|
|
|
NULL_MENU *p_menu;假设有三个菜单menu1,menu2,menu3
然后具体按键中判断 if (p_menu == &menu1) else if (p_menu == &menu2) …… 手机不好打字,只好打个大概不知楼主看懂没 主要就是比较当前指针与哪个菜单的地址匹配 |
|
|
|
就是状态机,不是太复杂用switch也不错的
|
|
|
|
switch+goto就够了,简单
|
|
|
|
|
|
|
|
谢谢,我参考下,我有不明的地方,还望您多多指教。
|
|
|
|
问题3为什么不会呢?
|
|
|
|
几个界面可以用switch,界面多了,代码就有点乱,也不利于修改。
|
|
|
|
那还不如用我现在的函数指针的方法,条例还清晰,也便于修改和维护。
|
|
|
|
大体上明白,就是现判断目前的界面处于那个界面,然后去执行本界面相关的函数或者操作。
|
|
|
|
为什么费SRAM呢?前面加const不就完了,所有的结构体都在ROM里。
|
|
|
|
结构体加const???恕我C语言基础薄弱,如果加了const还能修改里面的内容么?
比如菜单当前索引号占据了1个字节,函数指针占据4个字节,光是这2个东西都用了5个字节了,还没算上其他呢 |
|
|
|
结构体,为什么就不能加const?
.h文件里声明一个结构体: struct MenuItem { _UBYTE MenuCount; //本层菜单项目数 void (*Subs)(); //本层菜单执行函数 struct MenuItem *ChildrenMenus; //子菜单指针 struct MenuItem *ParentMenus; //父菜单指针 }; 在.C文件里定义一个变量: /*****************一级菜单***************/ //首页 const struct MenuItem Menu_USER_Frist_struct[3]= { // {2,USER_LCD_Frist_Function,(struct MenuItem*) Menu_USER_Second1,(struct MenuItem*)NULL}, {2,USER_LCD_Frist_Function,(struct MenuItem*) NULL,(struct MenuItem*)NULL}, {2,USER_LCD_Frist_Function,(struct MenuItem*) Menu_USER_Second2,(struct MenuItem*)NULL}, {1,USER_LCD_Frist_Function,(struct MenuItem*)&Menu_USER_Second3,(struct MenuItem*)NULL}, }; 怎么就废SRAM了?全部在ROM里。 |
|
|
|
结构体,为什么就不能加const?
.h文件里声明一个结构体: struct MenuItem { _UBYTE MenuCount; //本层菜单项目数 void (*Subs)(); //本层菜单执行函数 struct MenuItem *ChildrenMenus; //子菜单指针 struct MenuItem *ParentMenus; //父菜单指针 }; 在.C文件里定义一个变量: /*****************一级菜单***************/ //首页 const struct MenuItem Menu_USER_Frist_struct[3]= { // {2,USER_LCD_Frist_Function,(struct MenuItem*) Menu_USER_Second1,(struct MenuItem*)NULL}, {2,USER_LCD_Frist_Function,(struct MenuItem*) NULL,(struct MenuItem*)NULL}, {2,USER_LCD_Frist_Function,(struct MenuItem*) Menu_USER_Second2,(struct MenuItem*)NULL}, {1,USER_LCD_Frist_Function,(struct MenuItem*)&Menu_USER_Second3,(struct MenuItem*)NULL}, }; 怎么就废SRAM了?全部在ROM里。 |
|
|
|
引用傻孩子的一句话:你真的理解了这个菜单了?
|
|
|
|
我用了你给的代码做了个测试,在菜单结构里面加了个索引号index来指示当前菜单索引到哪个子菜单,但只要对这个索引号进行修改就出现图中的错误,很明显存放在FLASH里面的数据是不能直接修改的,不知道是我理解错了还是你理解错了 |
|
|
|
你好好看看傻孩子给的历程,就明白了。
|
|
|
|
只有小组成员才能发言,加入小组>>
3308 浏览 9 评论
2988 浏览 16 评论
3490 浏览 1 评论
9049 浏览 16 评论
4083 浏览 18 评论
1167浏览 3评论
601浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
592浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2329浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1892浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-17 14:49 , Processed in 1.716211 second(s), Total 84, Slave 75 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号