多级菜单设计
时间:10-02
整理:3721RD
点击:
菜单设计是嵌入式中不可或缺的一部分,有的简单粗暴的,有的细致复杂。
关于菜单设计的方案也很多,专业问题大家可以参考下相关文献,这里我选择了一种结构鲜明、易于维护,实现简单的方法。
一般来说,多级菜单的逻辑结构都是多叉树的拓扑结构:
像这种:
在编程中,与之对应的可以用链表来组织。
首先确定一个菜单项需要具备的属性:本页菜单数量、显示内容、执行函数、上级菜单、下级菜单。
- struct MenuItem //
- { unsigned char MenuCount; //
- const char *DisplayString; //
- unsigned char (*Subs)(); //
- struct MenuItem *ChildrenMenus; //
- struct MenuItem *ParentMenus; //
- };
例如一页菜单中有5项,可以这样组织:
- struct MenuItem MainMenu[5] = //
- {
- {5,"1.SysTem Set ",&fun1,SysTemSet,NULL},
- {5,"2.EquipmenT ID ",NULL, EquipmenT, NULL},
- {5,"3.BaudRatE ",NULL, BaudRatE, NULL},
- {5,"4.System Infor ",NULL, NULL, NULL},
- {5,"5.System Haha ",NULL, NULL, NULL},
- };
下级菜单同理:
- struct MenuItem SysTemSet[5] = //
- {
- {5,"1.DatA Set ",NULL,NULL,MainMenu},
- {5,"2.TimE Set ",NULL,NULL,MainMenu},
- {5,"3.AlarM Set ",NULL,NULL,MainMenu},
- {5,"4.BacKLed Set ",NULL,NULL,MainMenu},
- {5,"5.Password Set ",NULL,NULL, NULL},
- };
- struct MenuItem BaudRatE[7] = //
- {
- {7,"1.2400 ",NULL,NULL,MainMenu},
- {7,"2.4800 ",NULL,NULL,MainMenu},
- {7,"3.9600 ",NULL,NULL,MainMenu},
- {7,"4.19200 ",NULL,NULL,MainMenu},
- {7,"5.38400 ",NULL,NULL,MainMenu},
- {7,"6.57600 ",NULL,NULL,MainMenu},
- {7,"7.115200 ",NULL,NULL,MainMenu},
- };
- struct MenuItem EquipmenT[4] = //
- {
- {4,"1.No.01 ",NULL,NULL,MainMenu},
- {4,"2.No.02 ",NULL,NULL,MainMenu},
- {4,"3.NO.03 ",NULL,NULL,MainMenu},
- {4,"4.No.04 ",NULL,NULL,MainMenu},
- };
接下根据输入操作来改变指针指向的菜单结构体就可以了。
我这里只有2个按键,定义功能为:点击0键:上,点击1键:下,
短按0键:后退,短按1键:进入,
每次改变光标位置后后,由show_cursor()函数刷新光标位置。
翻页或切换新菜单后,由show_current_menu()函数刷新显示菜单。
- struct MenuItem* ptrMenu = MainMenu;
- u8 select_num = 0;
- u8 page = 0;
- show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);
- while(1)
- {
- static u8 key_num = 0;
- while(key_num == 0)
- {
- key_num = get_key_value();
- }
- if(key1_cilck == key_num)//plus
- {
- select_num = (select_num + 1)%ptrMenu->MenuCount;
- show_cursor(select_num%LCD_MAX_DISP_LINES);
- if(select_num/LCD_MAX_DISP_LINES != page)
- {
- show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);
- page = select_num/LCD_MAX_DISP_LINES;
- }
- }
- if(key0_cilck == key_num)//minus
- {
- if(select_num > 0)select_num--;
- show_cursor(select_num%LCD_MAX_DISP_LINES);
- if(select_num/LCD_MAX_DISP_LINES != page)
- {
- show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);
- page = select_num/LCD_MAX_DISP_LINES;
- }
- }
- if(key1_short == key_num)//enter
- {
- if((ptrMenu+select_num)->ChildrenMenus!=NULL)
- ptrMenu = (ptrMenu+select_num)->ChildrenMenus;
- show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);
- select_num = 0;
- show_cursor(select_num%LCD_MAX_DISP_LINES);
- }
- if(key0_short == key_num)//esc
- {
- if((ptrMenu+select_num)->ParentMenus!=NULL)
- ptrMenu = (ptrMenu+select_num)->ParentMenus;
- show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);
- select_num = 0;
- show_cursor(select_num%LCD_MAX_DISP_LINES);
- }
- key_num = 0;
- }