当菜单越来越多,就开始纠结了,这样写维护不便,看起来也不美,还浪费程序空间。
作为一个天天看《编程之美》的码农,决定改变现状。酷狗百度一番,找到了两个参考:《基于二叉树的多层的液晶菜单界面设计》《基于节点编号的通用树状菜单设计方法与实现.pdf》按照他们的设计方法,鼓捣了一个版本,能用,挺好,但是也纠结。因为他们用了树这种数据结构。对于程序运行来说,非常好,效率高。但是对于我来说,菜单代码是一次性的,但是菜单内容,却是会经常改的。让我用人脑去维护一个包含几十个上百个菜单的树,不容易。想来想去,这些菜单到底有什么不好?对于我来说,为什么不好用?得出下面结论:管得太宽菜单,你就管菜单切换就行了,到了最低一层,也就是实际的测试功能,就不要管了。菜单切换是类似的,实际测试都是不同的。比如在菜单中,按键1,是进入第一个菜单。但是在测试中,按键1,功能都不一样。如果菜单连这个也要管,相同动作功能太多,无法进行统一抽象,就很难模块化。
出发点不一样上面说到的菜单,出发点都是如何设计一个好的菜单数据结构,让程序快速,高效运行。我想要的却是一个容易维护的菜单结构,至于菜单的代码有多乱多纠结,没关系,而且,几百上千个菜单,就算用轮询的方法,也不过几百us吧,没关系。
根据需求,我重新设计了一个菜单结构体:/***
brief菜单对象*/typedefstruct_strMenu{MenuLell;///菜单等级charcha[MENU_LANG_BUF_SIZE];///中文chareng[MENU_LANG_BUF_SIZE];///英文MenuTypetype;///菜单类型s32(*fun)(void);///测试函数}MENU;是的,就这么简单,每一个菜单都是这个结构体,用这个结构体填充一个列表。这就是我们的菜单了。constMENUEMenuListTest[]={MENU_L_0,//菜单等级"测试程序",//中文"test",//英文MENU_TYPE_LIST,//菜单类型NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_1,//菜单等级"LCD",//中文"LCD",//英文MENU_TYPE_LIST,//菜单类型NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_2,//菜单等级"VSPIOLED",//中文"VSPIOLED",//英文MENU_TYPE_FUN,//菜单类型test_oled,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_2,//菜单等级"I2COLED",//中文"I2COLED",//英文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音乐",//中文"DACmusic",//英文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需要一个根节点和结束节点2子节点必须跟父节点,类似下面结构。-----------------------------------------------根节点第1个1级菜单第1个子菜单第2个子菜单第3个子菜单第2个1级菜单第1个子菜单第1个孙菜单第2个孙菜单第2个子菜单第3个子菜单第3个1级菜单第个1级菜单第5个1级菜单结束节点------------------------------------------------
第2个1级菜单有3个子菜单,子菜单是2级菜单,其中第1个子菜单下面又有2个孙菜单(3级菜单)。维护菜单,就是维护这个列表,添加删除修改,非常容易。那菜单程序怎么样呢?管他呢。定义好菜单后,通过下面函数运行菜单:emenu_run(WJQTestLcd,(MENU*)WJQTestList[0],sizeof(WJQTestList)/sizeof(MENU),FONT_SONGTI_,2);第1个参数是在哪个LCD上显示菜单,
第2个是菜单列表
第3个是菜单长度,
第个四字体
第5则是行间距
注意:运行这个菜单需要有rtos,因为菜单代码是while(1)的,陷进去就不出来了。需要有其他线程(TASK)维护系统,例如按键扫描。代码托管在github:转载请注明:http://www.0431gb208.com/sjszjzl/1043.html