先看看效果图
上面的 ABC, BCD,EFG分别是一个菜单列表的菜单
菜单的结构框图为
对于单个菜单的结构为
对于每个菜单,分别有指向它上面的菜单,下面的菜单,它的子菜单,它的父菜单,它的菜单列表,和这个菜单对应执行的函数的指针
对于一组菜单列表为
使用非常方便,我们来看下对于刚才效果图所展示的菜单的使用
首先定义有几个菜单列表
和一个指向当前状态的菜单
菜单的初始化
首先先给每个菜单列表里添加相应的菜单
然后把各个菜单列表连接起来
上图中RefreshMenu函数是根据CurrentMenu来刷新液晶屏的,这个要各位自己实现
然后再主函数里不停的执行
MenuHandler是这样处理得到的按键的
以上只给出了如何使用
其实还有些函数如 获得当前菜单为当前菜单列表中第几项 等子函数没列出来,这些通过都是链表的指针实现的
贡献出代码
头文件
#ifndef _MENU_H
#define _MENU_H
#include "sys.h"
#define IndexType unsigned char //¶¨Òå²Ëµ¥Ë&pide;ÒýºÅÀàÐÍ
#define MenuStringLengh 15
#define MaxMenuLengh 9
struct MenuType
{
struct MenuType *UpMenu;
struct MenuType *DownMenu;
struct MenuType *NextMenu; //¸Ã²Ëµ¥¶ÔÓ¦µÄ×Ӳ˵¥
struct MenuType *BackMenu; //Éϼ¶²Ëµ¥µÄ²Ëµ¥Ïî
struct MList *CurrentMuenList; //Ö¸Ïòµ±Ç°²Ëµ¥Áбí
char Context[MenuStringLengh]; //µ±Ç°²Ëµ¥¶ÔÓ¦µÄÎı¾
void (*function)(); //µ±Ç°²Ëµ¥Ïî¶ÔÓ¦µÄº¯Êý
};
//MenuType;
typedef struct MList
{
int MenuLengh; //²Ëµ¥ÖÐÓжàÉٲ˵¥Ïî
int MenuLevel; //²Ëµ¥µÄ²ã¼¶£¬Ö&pide;²Ëµ¥Îª1£¬Ö&pide;²Ëµ¥µÄ×Ӳ˵¥Îª2£¬ÀàÍÆ
struct MenuType *FirstMenu;
struct MenuType *LastMenu;
} MenuList;
void MenuInit(void);
void MenuHandler(u8 key);
void RefreshMenu(void);
#endif
C文件
#include "menu.h"
#include "stdlib.h"
#include "lcd.h"
#include "key.h"
#include "delay.h"
#include "string.h"
#include "menufunction.h"
MenuList MainMenu={0,0,0,0};
MenuList SubMenu={0,0,0,0};
MenuList level3Menu1={0,0,0,0};
MenuList level3Menu2={0,0,0,0};
MenuList level2Menu1={0,0,0,0};
MenuList level4Menu1={0,0,0,0};
void functiontest1(void);
void functiontest2(void);
struct MenuType *CurrentMenu;
struct MenuType* GetMenuFromList(MenuList *mymenulist,u8 index)
{
struct MenuType *t = mymenulist->FirstMenu;;
if(index <= mymenulist->MenuLengh && index>0 )
{
while(--index)
{
t = t->DownMenu;
}
return t;
}
return 0;
}
u8 GetMenuIndexFromList(struct MenuType *mymenu)
{
u8 res = 1;
if(mymenu->CurrentMuenList != 0)
{
while(mymenu->UpMenu != 0)
{
res++;
mymenu = mymenu->UpMenu;
}
return res;
}
return 0;
}
void AddMenu(MenuList *mymenulist, char *text, void (*fun)())
{
struct MenuType *t;
int i=0;
t = (struct MenuType *)malloc(sizeof(struct MenuType));
t->function = fun;
t->CurrentMuenList = mymenulist;
while(*text!='\0')
{
t->Context[i] = *text;
i++;
text++;
}
t->Context[i] = '\0';
if(mymenulist->MenuLengh == 0)
{
mymenulist->FirstMenu = t;
mymenulist->LastMenu = t;
}
else
{
t->UpMenu = mymenulist->LastMenu;
mymenulist->LastMenu->DownMenu = t;
mymenulist->LastMenu = t;
}
mymenulist->MenuLengh++;
}
void MenuLinkMenulist(struct MenuType *mymenu, MenuList *mymenulist)
{
u8 i;
struct MenuType *t = mymenulist->FirstMenu;
if(mymenulist->MenuLengh != 0)
{
mymenu->NextMenu = mymenulist->FirstMenu;
for(i=0;iMenuLengh;i++)
{
t->BackMenu = mymenu;
t = t->DownMenu;
}
}
}
void MenuInit(void)
{
AddMenu(&MainMenu,"ABC",0);
AddMenu(&MainMenu,"BCD",0);
AddMenu(&MainMenu,"EFG",functiontest1);
MainMenu.MenuLevel = 1;
AddMenu(&SubMenu,"sub1",0);
AddMenu(&SubMenu,"sub2",functiontest2);
SubMenu.MenuLevel = 2;
AddMenu(&level3Menu1,"ZJY",0);
AddMenu(&level3Menu1,"XZ",0);
AddMenu(&level3Menu1,"WT",0);
AddMenu(&level3Menu1,"LY",0);
level3Menu1.MenuLevel = 3;
AddMenu(&level3Menu2,"DDG",0);
AddMenu(&level3Menu2,"LMY",0);
AddMenu(&level3Menu2,"LLY",0);
AddMenu(&level3Menu2,"CYH",0);
AddMenu(&level3Menu2,"ZQC",0);
level3Menu2.MenuLevel = 3;
AddMenu(&level2Menu1,"LLL1",0);
AddMenu(&level2Menu1,"LLL2",0);
AddMenu(&level2Menu1,"LLL3",0);
AddMenu(&level2Menu1,"SendNum",PrintNumApp);
level2Menu1.MenuLevel = 2;
AddMenu(&level4Menu1,"level4",0);
AddMenu(&level4Menu1,"LEVEL4",0);
level4Menu1.MenuLevel = 4;
MenuLinkMenulist(GetMenuFromList(&MainMenu,2),&SubMenu);
MenuLinkMenulist(GetMenuFromList(&MainMenu,3),&level2Menu1);
MenuLinkMenulist(GetMenuFromList(&SubMenu,1),&level3Menu1);
MenuLinkMenulist(GetMenuFromList(&level2Menu1,3),&level3Menu2);
MenuLinkMenulist(GetMenuFromList(&level3Menu2,4),&level4Menu1);
CurrentMenu = MainMenu.FirstMenu;
RefreshMenu();
}
void ShowCurrentMenu(void)
{
LCD_ShowString(0,300," ");
LCD_ShowString(0,300,"Current:");
LCD_ShowString(64,300,(u8 *)CurrentMenu->Context);
}
void MenuHandler(u8 key)
{
switch(key)
{
case KEY_UP:
if(CurrentMenu->UpMenu != 0)
{
CurrentMenu = CurrentMenu->UpMenu;
RefreshMenu();
}
break;
case KEY_DOWN:
if(CurrentMenu->DownMenu != 0)
{
CurrentMenu = CurrentMenu->DownMenu;
RefreshMenu();
}
break;
case KEY_LEFT:
if(CurrentMenu->BackMenu != 0)
{
CurrentMenu = CurrentMenu->BackMenu;
RefreshMenu();
}
break;
case KEY_RIGHT:
if(CurrentMenu->NextMenu != 0)
{
CurrentMenu = CurrentMenu->NextMenu;
RefreshMenu();
}
break;
case KEY_PRESS:
if(CurrentMenu->function != 0)
{
CurrentMenu->function();
RefreshMenu();
}
break;
}
}
void ShowMenuList(MenuList *mymenulist,unsigned int x)
{
int i;
unsigned int stringlengh;
unsigned int startX;
struct MenuType *t = mymenulist->FirstMenu;
POINT_COLOR=BLACK;
for(i=0;iMenuLengh;i++)
{
stringlengh = strlen(t->Context);
startX = x + 40-stringlengh*4;
startX = startXContext); //ÏÔʾ²Ëµ¥×Ö·û´®
LCD_DrawRectangle(x,20+20*i,x+80,40+20*i);
if(t->NextMenu != 0)
{
LCD_DrawLine(x+75,27+20*i,x+75,33+20*i);
LCD_DrawLine(x+76,28+20*i,x+76,32+20*i);
LCD_DrawLine(x+77,29+20*i,x+77,31+20*i);
LCD_DrawLine(x+78,30+20*i,x+78,30+20*i);
}
t = t->DownMenu;
}
POINT_COLOR=RED;
}
void HighLightMenu(struct MenuType *mymenu,unsigned int x)
{
unsigned int stringlengh;
unsigned int startX;
struct MenuType *t = mymenu;
u8 index;
index = GetMenuIndexFromList(t);
stringlengh = strlen(mymenu->Context);
startX = x + 40-stringlengh*4;
startX = startXContext);
if(t->NextMenu != 0)
{
LCD_DrawLine(x+75,7+20*index,x+75,13+20*index);
LCD_DrawLine(x+76,8+20*index,x+76,12+20*index);
LCD_DrawLine(x+77,9+20*index,x+77,11+20*index);
LCD_DrawLine(x+78,10+20*index,x+78,10+20*index);
}
POINT_COLOR=RED;
BACK_COLOR = WHITE;
}
void RefreshMenu(void)
{
u8 currentlevel = 0;
struct MenuType *t = CurrentMenu;
LCD_Fill(0,20,240,200,WHITE);
currentlevel = t->CurrentMuenList->MenuLevel;
if(currentlevel == 0)
{
LCD_ShowString(60,40,"MenuLevelError");
}
else
{
currentlevel = currentlevel>3 ? 3 : currentlevel;
do
{
ShowMenuList(t->CurrentMuenList, currentlevel*80-80);
t = t->BackMenu;
currentlevel--;
}
while(currentlevel>0);
t = CurrentMenu;
currentlevel = t->CurrentMuenList->MenuLevel;
currentlevel = currentlevel>3 ? 3 : currentlevel;
do
{
HighLightMenu(t,currentlevel*80-80);
t = t->BackMenu;
currentlevel--;
}
while(currentlevel>0);
}
}
void functiontest1()
{
LCD_ShowString(60,180,"testfunction1");
}
void functiontest2()
{
LCD_ShowString(60,180,"testfunction2");
}
注释乱码,渣keil,函数的英文名写的挺清楚的也能看