树状菜单实现
多级菜单编程实现
1)菜单结构
菜单结构采用树状结构,由若干个节点组成多级菜单。每个节点由当前层级节点数、标题,操作函数、父节点和子节点构成,如下代码所示。
typedef struct Menu{uint8_t MenuNodes; //当前层节点数目 char *MenuName; //菜单标题void (*func)(uint16_t key); //节点函数const struct Menu *Parent; //父节点const struct Menu *Child; //子节点
}Menu_typedef;
2)菜单定义
这里我们实现一个多媒体管理菜单
【我的音乐】
----【经典音乐】
--------【曲目1】
--------【曲目2】
----【流行音乐】
【我的文档】
----【电子书】
----【说明书】
代码实现如下:
const Menu_typedef MainMenu[2] = { //一级菜单{2, "我的音乐", NullSubs, NULL, MusicMenu},{2, "我的文档", NullSubs, NULL, DocMenu}
};const Menu_typedef MusicMenu[2] = { //二级菜单{2, "经典音乐", NullSubs, MainMenu, Music_1_Menu},{2, "流行音乐", NullSubs, MainMenu, NULL}
};const Menu_typedef DocMenu[2] = { //二级菜单{2, "电子书", NullSubs, MainMenu, Doc_1_Menu},{2, "说明书", NullSubs, MainMenu, NULL}
};const Menu_typedef Music_1_Menu[2] = { //三级菜单{2, "曲目1", MusicPlayer, MusicMenu, NULL},{2, "曲目2", MusicPlayer, MusicMenu, NULL},
};const Menu_typedef Doc_1_Menu[1] = { //三级菜单{2, "语文", Reader, DocMenu, NULL}
};
定义一个节点,用来保存当前节点信息,初始化指向主菜单
Menu_typedef *MenuPoint = (Menu_typedef*)MainMenu;
char UserChoose = 0; //当前层级节点序号
定义一个空函数,补充没有操作的节点。
void NullSubs(uint16_t key)
{ }
实现音乐播放函数(省略)
void MusicPlayer(uint16_t key)
{ switch(UserChoose){case 0://play music 1break;case 1://play music 2break; }
}
实现文档阅读器(省略)
void MusicPlayer(uint16_t key)
{ if(key == )switch(UserChoose){case 0://语文break; }
}
3)菜单操作
菜单操作由以下功能组成:上、下、返回、确定。
菜单任务的入口函数为按键操作值,根据用户的输入设备传入
/*** @brief 菜单选择.* @Note * @param keyvalue 输入按键* @retval None*/
void MenuTask(uint16_t Keyvalue)
{if(OperationFunc == 0){ if(Keyvalue){switch(Keyvalue) { case UP: //向上 UserChoose--;if (UserChoose < 0){ UserChoose = MenuPoint->MenuNodes - 1; //跳转到最后一项} break; case ESC: // 返回OperationFunc = 0;if (MenuPoint[UserChoose].Parent != NULL) //父级是否存??{MenuPoint = (Menu_typedef*)MenuPoint[UserChoose].Parent; UserChoose = 0;} break;case DOWN: //向下UserChoose ++; if (UserChoose > MenuPoint->MenuNodes - 1) { UserChoose = 0; //跳转到子级菜单的第一项} break; case ENTER: // ENTER if (MenuPoint[UserChoose].func != NullSubs) //判断是否有行为函数{ Flag.OperationFunc = 1; //启动函数操作标志layernumber++; } else if (MenuPoint[UserChoose].Child != NULL) //判断子级是否为空{ MenuPoint = (Menu_typedef*)MenuPoint[UserChoose].Child; //进入子级UserChoose = 0; //跳转到子级菜单的第一} break;}} Keyvalue = 0; //清零,防止直接ENTER Dipstr = MenuPoint[UserChoose].MenuName; //保存当前菜单标题,输出到显示设备}if(OperationFunc == 1){(*MenuPoint[UserChoose].func)(Keyvalue); //执行函数操作 }}
4)结语
这个树状菜单结构具备较好的扩展性和移植性,可以很方便的移植到其他平台,而且结构使用稳定,有问题请留言。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
