框架结构体如下:
struct ui_menu
{
uint8_t item; // 当前选择的子菜单编号
uint8_t level; // 菜单级别,0是最高级别,主菜单。
struct ui_menu* parent; // 父菜单,即上一级菜单
struct ui_menu* items[UI_MENU_ITEM_MAX];//此菜单下的子菜单
uint8_t (*on_Key_Up)(void); // 返回值,是否是最后一个子项,可根据此返回值执行特定的操作
uint8_t (*on_Key_Down)(void); // 返回值,是否是最后一个子项,可根据此返回值执行特定的操作
struct ui_menu* (*on_Key_Back)(void); // 返回上一级菜单
struct ui_menu* (*on_Key_OK)(uint8_t* flag);
void (*menu_Show)(void); // 显示逻辑在此处执行
void (*menu_Enter)(uint8_t item); // 进入此菜单会被调用一次
void (*menu_Exit)(void); // 退出此菜单会被调用一次
};
菜单的链接实现
/*
* 连接菜单
* @param in:parent:父菜单,为空则为顶级菜单
* @param in:item:父菜单下的一个菜单项,不能为空
* @param in:itemIndex:本菜单功能不使用动态分配,索引不能超过最大索引。
*/
int UI_Menu_Link(ui_menu_t* parent,ui_menu_t* item,uint8_t itemIndex)
{
if(item == NULL)
{
return -1;
}
if(itemIndex >= UI_MENU_ITEM_MAX)
{
return -1;
}
if(parent == NULL)
{
return -1;
}
item->level = parent->level + 1; // 将当前项设置为父菜单的下一级
item->parent = parent;
parent->items[itemIndex] = item;
return 0;
}
ui_menu_t* UI_Menu_Top_Get(ui_menu_t* item)
{
ui_menu_t* top = item;
if(top != NULL)
{
while(top->parent != NULL){
top = top->parent;
}
}
return top;
}
菜单的调用方式,根据不同的按键执行对应的功能。
void UI_Page_Menu_Handler(uint16_t key)
{
uint16_t keyEvent = key;
uint8_t isSave = 0;
if(keyEvent == KEY_OK) // 保存参数,进入下一步
{
if(curMenu->on_Key_OK)
{
curMenu = curMenu->on_Key_OK(&isSave); // 调用当前菜单的OK
if(curMenu->menu_Enter)
{
if(curMenu->level > lastMenu->level)
{
curMenu->menu_Enter(lastMenu->itemID);
}
}
lastMenu = curMenu;
}
else
{
isSave = 0xFF;
}
if(isSave == 1) // 保存数据
{
}
else if(isSave == 0)
{
}
}
else if(keyEvent == KEY_BACK)
{
if(curMenu->menu_Exit)
{
curMenu->menu_Exit();
}
if(curMenu->on_Key_Back)
{
curMenu = curMenu->on_Key_Back();
lastMenu = curMenu;
}
}
else if(keyEvent == KEY_UP)
{
if(curMenu->on_Key_Up)
{
if(curMenu->on_Key_Up())
{
}
else
{
}
}
}
else if(keyEvent == KEY_DOWN)
{
if(curMenu->on_Key_Down)
{
if(curMenu->on_Key_Down())
{
}
else
{
}
}
}
curMenu->menu_Show();
}
本框架没有使用动态内存分配。在菜单分级较多的情况下,没有框架的支持,写起来会显得非常混乱。在框架的支持下,可以将各个菜单功能解耦合,利于后期的维护及扩展。