当菜单越来越多,就开始纠结了,这样写维护不便,看起来也不美,还浪费程序空间。
管得太宽 菜单,你就管菜单切换就行了,到了最低一层,也就是实际的测试功能,就不要管了。菜单切换是类似的,实际测试都是不同的。比如在菜单中,按键1,是进入第一个菜单。但是在测试中,按键1,功能都不一样。如果菜单连这个也要管,相同动作功能太多,无法进行统一抽象,就很难模块化。
出发点不一样 上面说到的菜单,出发点都是如何设计一个好的菜单数据结构,让程序快速,高效运行。我想要的却是一个容易维护的菜单结构,至于菜单的代码有多乱多纠结,没关系, 而且,几百上千个菜单,就算用轮询的方法,也不过几百us吧,没关系。
/**
* @brief 菜单对象
*/
typedef struct _strMenu
{
MenuLel l; ///<菜单等级
char cha[MENU_LANG_BUF_SIZE]; ///中文
char eng[MENU_LANG_BUF_SIZE]; ///英文
MenuType type; ///菜单类型
s32 (*fun)(void); ///测试函数
} MENU;
是的,就这么简单,每一个菜单都是这个结构体,用这个结构体填充一个列表。 这就是我们的菜单了。
const MENU EMenuListTest[]=
{
MENU_L_0,//菜单等级
"测试程序",//中文
"test", //英文
MENU_TYPE_LIST,//菜单类型
NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_1,//菜单等级
"LCD",//中文
"LCD", //英文
MENU_TYPE_LIST,//菜单类型
NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_2,//菜单等级
"VSPI OLED",//中文
"VSPI OLED", //英文
MENU_TYPE_FUN,//菜单类型
test_oled,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_2,//菜单等级
"I2C OLED",//中文
"I2C OLED", //英文
MENU_TYPE_FUN,//菜单类型
test_i2coled,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_1,//菜单等级
"声音",//中文
"sound", //英文
MENU_TYPE_LIST,//菜单类型
NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_2,//菜单等级
"蜂鸣器",//中文
"buzzer", //英文
MENU_TYPE_FUN,//菜单类型
test_test,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_2,//菜单等级
"DAC音乐",//中文
"DAC music", //英文
MENU_TYPE_FUN,//菜单类型
test_test,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_2,//菜单等级
"收音",//中文
"FM", //英文
MENU_TYPE_FUN,//菜单类型
test_test,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_1,//菜单等级
"触摸屏",//中文
"tp", //英文
MENU_TYPE_LIST,//菜单类型
NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_2,//菜单等级
"校准",//中文
"calibrate", //英文
MENU_TYPE_FUN,//菜单类型
test_cal,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_2,//菜单等级
"测试",//中文
"test", //英文
MENU_TYPE_FUN,//菜单类型
test_tp,//菜单函数,功能菜单才会执行,有子菜单的不会执行
MENU_L_1,//菜单等级
"按键",//中文
"KEY", //英文
MENU_TYPE_FUN,//菜单类型
test_key,//菜单函数,功能菜单才会执行,有子菜单的不会执行
/*最后的菜单是结束菜单,无意义*/
MENU_L_0,//菜单等级
"END",//中文
"END", //英文
MENU_TYPE_NULL,//菜单类型
NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行
};
-----------------------------------------------
根节点
第1个1级菜单
第1个子菜单
第2个子菜单
第3个子菜单
第2个1级菜单
第1个子菜单
第1个孙菜单
第2个孙菜单
第2个子菜单
第3个子菜单
第3个1级菜单
第4个1级菜单
第5个1级菜单
结束节点
------------------------------------------------
emenu_run(WJQTestLcd, (MENU *)&WJQTestList[0], sizeof(WJQTestList)/sizeof(MENU), FONT_SONGTI_1616, 2);
第1个参数是在哪个LCD上显示菜单,
第2个是菜单列表
第3个是菜单长度,
第4个四字体
第5则是行间距
实现了双列菜单,用数字键选择进入下一层。每页最多显示8个菜单(4*4键盘用1-8键)
实现了单列菜单,通过上下翻查看菜单,确认键进入菜单。3 天顶菜单未实现,谁有兴趣可以加上。
基于LCD驱动架构,这个简易菜单自适应于多种LCD。