借阿莫的宝地开源个原创的LCD菜单内核,希望各位OURDEV的兄弟们继续努力,将这个菜单内
这个得从上一年我要做一个带有菜单的项目说起,一开始听说要做个带有菜单的项目,不知从何做起,在阿莫这看到了《一个占用内存极少的菜单系统的实现》,研究了这个菜单的代码结构并参照这个菜单的内核,自己写了个菜单代码。也就从这里开始,自己理解了菜单是一个怎样的东西。当我把这个写好的菜单用到我的系统上,我注意到了有几个地方要改进,第一:菜单的移植性,第二:菜单的修改维护,第三:菜单项目的扩展功能(使用灵活性)。提示一下:其实我只是提出一些我个人的观点和学术上的建议,我们更多的是互相交流学习,取长补短,共同进步。
第一:菜单的移植性
_CONST_ KbdTabStruct KeyTab[]={
// |-----------> Index
// |Up
// ||Down
// |||Left
// ||||Right --->功能函数
// ||||| |
{ 0, 1, 2, 3, 4,(*DispMenuTop)},// 待机画面
{ 1, 0, 0, 0, 0,(*DispMenuTopUp)},
{ 2, 0, 0, 0, 0,(*DispMenuTopDown)},
{ 3, 0, 0, 0, 0,(*DispMenuTopLeft)},
{ 4, 0, 0, 0, 0,(*DispMenuTopRight)},
{ 5, 6, 7, 8, 9,(*DispIcoMenuInit)}, //图标层菜单
{ 6, 0, 0, 0, 0,(*DispIcoMenuUp)}, //
{ 7, 0, 0, 0, 0,(*DispIcoMenuDown)}, //
{ 8, 0, 0, 0, 0,(*DispIcoMenuLeft)}, //
{ 9, 0, 0, 0, 0,(*DispIcoMenuRight)},//
{10,11,12,13,14,(*DispMenuFuncInit)}, //"功能"
{11, 0, 0, 0, 0,(*DispMenuFuncUp)}, //
{12, 0, 0, 0, 0,(*DispMenuFuncDown)}, //
{13, 0, 0, 0, 0,(*DispMenuFuncLeft)}, //
{14, 0, 0, 0, 0,(*DispMenuFuncRight)},//
{15,16,17,18,19,(*DispMenuParaInit)}, //"参数"
{16, 0, 0, 0, 0,(*DispMenuParaUp)}, //
{17, 0, 0, 0, 0,(*DispMenuParaDown)}, //
{18, 0, 0, 0, 0,(*DispMenuParaLeft)}, //
{19, 0, 0, 0, 0,(*DispMenuParaRight)},//
{20,21,22,23,24,(*DispMenuLanguageInit)}, //"语言"
{21, 0, 0, 0, 0,(*DispMenuLanguageUp)}, //
{22, 0, 0, 0, 0,(*DispMenuLanguageDown)}, //
{23, 0, 0, 0, 0,(*DispMenuLanguageLeft)}, //
{24, 0, 0, 0, 0,(*DispMenuLanguageRight)},//
{25,26,27,28,29,(*DispMenuMeasureInit)}, //"测量"
{26, 0, 0, 0, 0,(*DispMenuMeasureUp)}, //
{27, 0, 0, 0, 0,(*DispMenuMeasureDown)}, //
{28, 0, 0, 0, 0,(*DispMenuMeasureLeft)}, //
{29, 0, 0, 0, 0,(*DispMenuMeasureRight)},//
#ifdef DynamicBar
{30,31,32,33,34,(*DispMenuDataInit)}, //"Data"
{31, 0, 0, 0, 0,(*DispMenuDataUp)}, //
{32, 0, 0, 0, 0,(*DispMenuDataDown)}, //
{33, 0, 0, 0, 0,(*DispMenuDataLeft)}, //
{34, 0, 0, 0, 0,(*DispMenuDataRight)},//
#endif
};
这个是菜单的结构,在做程序的时间都一一定好那个项在那个位置,当移植到其它的项目上,这个菜单全部都得重做。
第二:菜单的修改维护
当菜单项要修改位置、菜单项功能和菜单扩展功能时,所需做的功夫比较大。当菜单项比较多,而且又有菜单扩展功能,修改起来有时很容易搞乱。
第三:菜单项目的扩展功能(使用灵活性)
举个例子:当前菜单项是“电机启动”窗口提示按某个键“启动电机”,当电机启动后菜单项中文显示为“电机停止” 窗口又提示按某个键“电机停止”。
再有就是同一个菜单项要负责多个扩展功能
举个例子:当前菜单项是“电机控制”再按确定后,弹出一个小窗口并列表显示数个电机的顺序,面板上的数字键都可单独控制一个确定的电机启动/运行。
要在这个菜单内核上实现这些功能的时候,就显示有些力不从心了。
/****************************************************************************************/
点击此处下载 ourdev_557291.rar(文件大小:3K) (原文件名:menu.rar)
这个代码是我参照《一个占用内存极少的菜单系统的实现》写的,在可移植性上我还是做了些改进,你留心一下会发现不同的菜单层UP与DOWN的代码是一样的,移植和维护都不用动这一部分的代码。这里只要就是菜单层之间的切换比较麻烦。
/*******************************************************************************************/
以下是我从项目里整理出来的原创菜单源码
我的特点是以菜单节点为对象而组建的一个菜单体,每层菜单最大支持99菜单项
//--------菜单节点结构体
typedef struct _MenuNode
{
unsigned intMenuNodeID;
unsigned char *MenuString;
unsigned char MenuStatus;
struct _MenuNode *First_Node;
struct _MenuNode *Last_Node;
struct _MenuNode *Prev_Node;
struct _MenuNode *Next_Node;
void(*Action)(unsigned char in);
}MenuNode;
//--------菜单链表
typedef struct _MenuList
{
struct _MenuNode *Point_Node;
}MenuList;
根椐菜单的编码结构可以随意修改和添加菜单项目,
//--------当前菜单信息
MenuNode MenuNode1 ={1,"1",0,(void*)0,(void*)0,(void*)0,(void*)0,MenuNode1Action};
MenuNode MenuNode2 ={2,"2",0,(void*)0,(void*)0,(void*)0,(void*)0,MenuNode2Action};
MenuNode MenuNode101={101,"101",0,(void*)0,(void*)0,(void*)0,(void*)0,MenuNode101Action};
MenuNode MenuNode102={102,"102",0,(void*)0,(void*)0,(void*)0,(void*)0,MenuNode102Action};
MenuNode MenuNode103={103,"103",0,(void*)0,(void*)0,(void*)0,(void*)0,MenuNode103Action};
MenuNode MenuNode201={201,"201",0,(void*)0,(void*)0,(void*)0,(void*)0,MenuNode201Action};
菜单的链表结构在菜单初始化完成
//--------菜单初始化
void MenuListInit(void)
{
unsigned char i;
MenuNode *InitMenuNode;
CurrentMenuNode=&MenuNode1;
MenuTotalList.Point_Node=&MenuNode1;
MenuTotalList.Point_Node=&MenuNode2;
MenuTotalList.Point_Node=&MenuNode101;
MenuTotalList.Point_Node=&MenuNode102;
MenuTotalList.Point_Node=&MenuNode103;
MenuTotalList.Point_Node=&MenuNode201;
for(i=0;i<MenuTotalNode;i++)
{
InitMenuNode=MenuTotalList.Point_Node;
(*InitMenuNode).First_Node=SearchMenuNode((*InitMenuNode).MenuNodeID,firstnode);
(*InitMenuNode).Last_Node =SearchMenuNode((*InitMenuNode).MenuNodeID,lastnode);
(*InitMenuNode).Prev_Node =SearchMenuNode((*InitMenuNode).MenuNodeID,prevnode);
(*InitMenuNode).Next_Node =SearchMenuNode((*InitMenuNode).MenuNodeID,nextnode);
}
}
可以灵活添加和修改扩展功能
void MenuNode101Action(unsigned char key)
{
Lcd_Clr();
switch(key)
{
case key0code:
case key1code:
case key2code:
case key3code:
case key4code:
case key5code:
case key6code:
case key7code:
case key8code:
case key9code:if(num101<8){tab101=key;num101++;}break;
case key10code:if(num101>0){num101--;tab101=0;}break;
default:break;
}
LCD_Write_String(0,0,"101请输入:");
LCD_Write_Number(0,1,tab101,num101);
}
菜单内核调度代码在移植时不用修改
//--------菜单显示
void MenuShow(void)
{
unsigned char i;
static MenuNode *ShowMenuNode;
switch(CurrentMenuStatus)
{
case menufunc:
Menu_LCD_Clr();
ShowMenuNode=SearchSomeOneMenuNode((*CurrentMenuNode).MenuNodeID-CurrentMenuCur);
Menu_LCD_Write_String(0,CurrentMenuCur,"->");
for(i=0;i<MaxScreenSize;i++)
{
Menu_LCD_Write_String(2,i,(*ShowMenuNode).MenuString);
if((*ShowMenuNode).Last_Node!=NULL)
{
ShowMenuNode=(*ShowMenuNode).Last_Node;
}
else
break;
}
break;
case numberfunc:
break;
default:break;
}
}
//--------菜单索引操作
void MenuFunctionKey(unsigned char key)
{
MenuIntDisable();
switch(key)
{
case Key_First:
if((*CurrentMenuNode).First_Node!=NULL)
{
CurrentMenuNode=(*CurrentMenuNode).First_Node;
if(CurrentMenuCur>0)
CurrentMenuCur--;
}
break;
case Key_Last:
if((*CurrentMenuNode).Last_Node!=NULL)
{
CurrentMenuNode=(*CurrentMenuNode).Last_Node;
if(CurrentMenuCur<(MaxScreenSize-1))
CurrentMenuCur++;
}
break;
case Key_Prev:
if((*CurrentMenuNode).Prev_Node!=NULL)
{
CurrentMenuNode=(*CurrentMenuNode).Prev_Node;
MenuDeep--;
CurrentMenuCur=MenuCurStack;
}
break;
case Key_Next:
if((*CurrentMenuNode).Next_Node!=NULL)
{
CurrentMenuNode=(*CurrentMenuNode).Next_Node;
MenuCurStack=CurrentMenuCur;
CurrentMenuCur=0;
MenuDeep++;
}
break;
default:break;
}
MenuIntEnable();
}
//--------菜单扩展操作功能
void (*MenuNodeAction)(unsigned char key);
//--------菜单按键功能, 扩展功能
void MenuNumberKey(unsigned char key)
{
MenuIntDisable();
MenuNodeAction=(*CurrentMenuNode).Action;
MenuIntEnable();
(*MenuNodeAction)(key);
}
点击此处下载 ourdev_557288.rar(文件大小:10K) (原文件名:menusource.rar)
说明:这个菜单代码是在老板要求做一个小的手持终端设备,在我对菜单原有的理解和结合新的需要而设计出来的,也是从少少的几代码一步一步添加和调试完善起来的,我这次从这个项目里整理这个菜单代码出来,功能不是很完善,但我觉得这个菜单的内核结构是比较好的。
一些想法和建议:我希望朋友们看下我这个代码,有些不完善的地方可以提出来并自行修改用在你的项目上,并且能在这里跟贴,也尽你的一份责任,让同行兄弟们学习学习。还有就是,我现在不做技术了,有空也会搞下这个,但是少了,我知道阿莫这里平时是很多高手出没的,我希望有些热心的朋友继续完善这个菜单,也或你了解这个内核的结构,会有更好更有创意的想法并结合你自己的长处开发出一个更加好的GUI。当然啦,能开源给兄弟们学习使用,那就最好,兄弟们都会感谢你为我们辛勤而又无私的付出。
谢谢各位的支持!十分感谢!
有什么问题可以随时联系我,我的QQ是:178122887,电话:13570402599 沙发 收下 看来要好好学习才行,顺便过来支持LZ! mark mark 支持楼主的努力! 我最近也要研究一个占用内存极少的菜单系统的实现,前几天有人发过一个占用内存极少的菜单系统的实现在AVR上的移植 学习!!!! 排队学习 先先
贝 学习!!!! mark 谢谢分享 学习 先mark mark 感谢分享 mark MARK 如果论坛的人都像楼主这样就好了! 一直在为菜单的灵活性头痛不已。 支持 mark! LZ, 用什么便宜环境来 写的? thks mark学习一下 牛啊 mark,学习 mark 好啊!!!! 谢谢。 收藏,学习! 支持楼主,之前再用傻孩子的菜单,在其基础上改进了一些,虽然菜单切换比较方便,但觉得执行函数还不是很好!判读一下你的大作! MARK GUI 很棒,感觉好像是糅合了《一个占用内存极少的菜单系统的实现》和傻孩子菜单的优点 好好学习一下 谢谢分享 Mark LZ,可以帖几张图瞧瞧吗? mark 没仔细看,先标记。
一个占用内存极少的菜单系统的实现 看了几遍,没看懂。傻孩子的那个倒全看懂了。 mark mark mark thanks,收下了,以后会有用 呵呵,十分感谢ourdev各位兄弟的支持,我有空再整理些技术资料和一些心得出来和大家分享,望各位兄弟继续支持...... MARK 支持 支持 mark mark 很好 标记先 迟点仔细研究才行~ mark 回复【34楼】jackielau九天
很棒,感觉好像是糅合了《一个占用内存极少的菜单系统的实现》和傻孩子菜单的优点
-----------------------------------------------------------------------
这么厉害啊,那真的要马克一下 具有参数设置功能吗?比如说,电机转速:XXXX, 顶顶!正准备做个界面呢 mark
学学! 谢谢楼主啊 谢谢楼主!花了两天的时间搞懂了!不过有个漏洞。再查找菜单链接时候的一个输入参数定义成了char 型。结果菜单ID号大于255时候就跑飞了。
//--------查找任一菜单节点
MenuNode *SearchSomeOneMenuNode(unsigned int nodeid) 原来是 unsigned char nodeid
{
unsigned char i;
MenuNode *SearchMenuNode;
MenuNode *ReturnMenuNode= 0;
for(i=0;i<MenuTotalNode;i++)
{
SearchMenuNode=MenuTotalList.Point_Node;
if((*SearchMenuNode).MenuNodeID==nodeid)
{
ReturnMenuNode=SearchMenuNode;
break;
}
}
return ReturnMenuNode;
} mark. 好\(^o^)/~ 谢谢分享,支持楼主的精神! 支持!! 喜欢LCD! mark mark up mark 学习了!! 学习了! mark 鼓励一下 mark 谢谢分享 这个要顶 thks 很不错啊赞一个 !!! 回复【34楼】jackielau九天
很棒,感觉好像是糅合了《一个占用内存极少的菜单系统的实现》和傻孩子菜单的优点
-----------------------------------------------------------------------
这个强 MARK 楼主没弄个图片来看看。 MARK 学习下 MARK0001 mark xia 可能会用上,看看。 回复【57楼】XUEPENGBIN 薛鹏斌
-----------------------------------------------------------------------
这位哥们所言极是,大家要注意!1 thanks and mark MARK 这个好!! 很好,谢谢 MARK一下! 再来看一看 很好,谢谢 mark mark!!!!!!!!!!! mark ./emotion/em025.gif very good. Thank you mark mark! 很好的东西,下来看看 最近一个项目应该要用到,参考下,希望有用 mark