请教傻孩子大侠多级菜单的问题.
/*********************** 目录结构体定义 *
**********************/
typedef struct datas
{
unsigned char MenuCount; //当前层节点数
unsigned intstr; //菜单标题
void (*Subs)(void); //节点函数
struct datas const *ChildrenMenus; //子节点
struct datas const *ParentMenus; //父节点
}MenuItem;
MenuItem const MainMenu[]=
{
{4,{'时','间','设','置'},Main_son, TimsMenu, Null},
{4,{'参','数','设','置'},Main_son, DatfMenu, Null},
{4,{'系','数','标','定'},Main_son, DatdMenu, Null},
{4,{'退','出','设','置'},Exit_son, Null, Null},
};
void NullSubs(void)
{
}
int main()
{
short KeyNum = 0xff;
SystemInitialation(); //系统初始化
ShowMenu();
while(1)
{
ClearWatchDog(); //喂狗
KeyNum = GetKeyNum(); //获取按键值
/*******************目录操作*********************/
/***************************************
* [按键说明] *
*----------------------------------- *
* UP(向上) *
* Down(向下) *
* Esc(后退) *
* Enter(确定) *
* 返回根目录 *
***************************************/
if (KeyNum != 0xff)
{
ShowMenu();
switch(KeyNum)
{
case UP:
UserChoose --;
if (UserChoose < 0)
{
UserChoose = MaxItems-1;
}
break;
case Esc:
if (MenuPoint.ParentMenus != &Null)
{
MenuPoint = MenuPoint.ParentMenus;
UserChoose = 0;
DisplayStart = 0;
}
break;
case Down:
UserChoose ++;
if (UserChoose == MaxItems)
{
UserChoose = 0;
}
break;
case Enter:
if (MenuPoint.Subs != NullSubs)
{
(*MenuPoint.Subs)();
}
else if (MenuPoint.ChildrenMenus != &Null)
{
MenuPoint = MenuPoint.ChildrenMenus;
UserChoose = 0;
DisplayStart = 0;
}
break;
case Reset:
MenuPoint = MainMenu;
UserChoose = 0;
DisplayStart = 0;
break;
}
if ((UserChoose < DisplayStart) || (UserChoose > (DisplayStart+3)))
{
DisplayStart = UserChoose;
}
CLS
ShowMenu();
}
/*******************目录操作*********************/
}
}
请教傻孩子大侠,当进入void (*Subs)();函数后,如在里面设置完数据后,如何退出.还有菜单操作部分全部是死循环:即死等按键直到退出菜单。
也就是说,进入菜单操作过程时,主程序中的其它程序就无法执行了.如何才能避免.大侠能不能发表一个最简单的示例.谢谢! 比较实际的一个问题!
我的做法是:定义一个全局变量(字符或整型,根据实际晶振选),每次键盘按下,给一个初值给变量(如100),每次中断中减1,直到为零,最后在按键识别函数增加对这个变量是否为零的检测,如变量=0则返回或弹回你想要的菜单!我的中断是20ms,20x200=4秒,即4秒返回!
个人愚见,不知道大家怎么做的? 在我的按键菜单里是每次按下时,将一个全局变量清0,在给定的时间内没有按键在次按下时,退出按键程序。但是一直没有做出一个好的多级菜单出来。看了傻孩子大侠的示例后,觉得算法很好,但是里面设置完数据后,如何退出。还有菜单操作部分全部是死循环:即死等按键直到退出菜单。这个部分一直没有想出好的算法,不知道有没有哪位大侠能指导一下。谢谢!在网上看到下面的示例觉得也没有想的很全。也存在这个问题。
void GetKeyInput(void)
{
void (*KeyFuncPtr)(); //按键功能指针
}
unsigned char KeyValue;
typedef struct
{
unsigned char state;//当前索引号
unsigned char keydn;//同一级菜单下移索引号
unsigned char keyon;//同一级菜单上移索引号
unsigned char keynext;//下一级菜单索引号
unsigned char keyback;//上一级菜单索引号
void(*pFun)();
}_Fun_Test;
_Fun_Test code KeyTab =
{
{0,1,5,6,0,lcdm},
{1,2,0,10,1,lcdm2},
{2,3,1,11,2,lcdm3},
{3,4,2,12,3,lcdm4},
{4,5,3,13,4,lcdm5},
{5,0,4,14,5,lcdm6},
{6,7,20,21,0,lcdse1},
{7,15,6,22,0,lcdse2},
{8,8,8,8,6,lcdth1},
{9,9,9,9,6,lcdth2},
{10,10,10,10,1,lcdsetemp},
{11,11,11,11,2,lcdsetemp},
{12,12,12,12,3,lcdsetemp},
{13,13,13,13,4,lcdsetemp},
{14,14,14,14,5,lcdsetemp},
{15,16,7,8,0,lcdse3},
{16,17,15,9,0,lcdse4},
{17,18,16,17,0,lcdse5},
{18,19,17,18,0,lcdse6},
{19,20,18,19,0,lcdse7},
{20,6,19,20,0,lcdse8},
{21,21,21,21,6,simulation},
{22,22,22,22,7,onoff}
};
//LEDRUN = 0;
KeyValue = P2 & 0XFF; //
DelayMs(20*3);
lightflashon(); //工作标志灯
switch(KeyValue)
{
case LCDKEY1: //回车键,找出新的菜单状态编号
{
KeyFuncIndex=KeyTab.keynext;
sound = 1;
DelayMs(5*3);
sound = 0;
delchar(); //del all char
delzipic(); //del haizi and picture
break;
}
case LCDKEY2: //向上键,找出新的菜单状态编号
{
KeyFuncIndex=KeyTab.keyon;
sound = 1;
DelayMs(5*3);
sound = 0;
break;
}
case LCDKEY3: //向下键,找出新的菜单状态编号
{
KeyFuncIndex=KeyTab.keydn;
sound = 1;
DelayMs(5*3);
sound = 0;
break;
}
case LCDKEY4: //返回键,找出新的菜单状态编号
{
KeyFuncIndex=KeyTab.keyback;
sound = 1;
DelayMs(5*3);
sound = 0;
delchar(); //del all char
delzipic(); //del haizi and picture
break;
}
default: //按键错误的处理
break;
}
KeyFuncPtr=KeyTab.pFun;
(*KeyFuncPtr)(); //执行当前按键的操作
lightflashoff(); //工作标志灯
//LEDRUN = 1;
} 简单的做法,就是全部使用状态机,就能解决你的疑惑。
可以尝试自己先画状态图,再用if或者switch结构来实现这个状态机。 我原来就是用的 switch,但是看了你的多级菜单的示例后,发现进与出父子菜单真的很方便。但是现在想不出一个好的方法来,如何才能在你示例的基础,让数据设置变的很简单。还有如何能避免菜单操作部分是死循环。 给你一个诀窍,你把所有的死循环都用状态机来实现。 typedef struct _menu_item
{
FLASH INT8U* strItemText;
HANDLE pfItemFunc;
}MENU_ITEM;
typedef struct _menu
{
void* pMenuItemBase;
INT8UFLASH * pTitle;
INT8U TotalItem;
INT8U CurItem;
}MENU;
typedef struct _bar_menu
{
void* pMenuItemBase;
INT8UFLASH * pTitle;
INT8U TotalItem;
INT8U CurItem;
INT8U WhereItem;
INT8U Range;
}BAR_MENU;
typedef struct _icon_menu
{
void* pMenuItemBase;
INT8UFLASH * pTitle;
INT8UTotalItem;
INT8UCurItem;
INT8U FLASH** pIconDataBase;
}ICON_MENU;
typedef MENU* (*MENU_STK)[];
typedef struct _menu_stk_obj
{
MENU_STK pMenuStack;
INT8U Top;
INT8U Size;
}MENU_STK_OBJ;
用堆栈也行的。上面是我的几种菜单的定义。
至于LZ的问题,设一个刷新屏幕的标志,主程序定时检查标志就行,有就刷一次,没有就算了。 收藏学习中! 回复【3楼】Gorgon Meducer 傻孩子
-----------------------------------------------------------------------
多谢提醒 太好了,我看了傻孩子大侠书中的讲的知识点以后还是有点疑惑,碰巧这里有这个主题,再学习学习一下! 多谢各位大侠,受教了。 Gorgon Meducer 傻孩子大侠 :
我一直在琢磨你写的菜单结构,看你用的是结构体,里面把数据和处理数据的函数放在一个结构体里面,我百看也不能理解是怎么实现的? 这个好像是面向对象的程序设计了吧!? 可是我没有学过C++, 对面向对象的程序设计方法不理解? 你能不能详细的指导指导我们一下啊!?不胜感激!!!!!!!!!!! to 【11楼】 liaogang1314
用C语言实现面向对象的技术,请参考下面链接里面的文档(数据结构章节)
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3239709&bbs_page_no=1&bbs_id=3039 多谢傻孩子大侠!!谢谢你无私的指导! 还有 请教Gorgon Meducer 傻孩子大侠:
你发布的这个结构体菜单是不是用了链表或者队列等数据结构里面的一些知识呢 我仅仅学了数据结构里面的一点点单向链表知识 其他的没学过 老是看不懂你的 郁闷呀!还请大侠百忙之中告知一二!不胜感激!!!!!!!!!!!!!!多多谢!!!!!!!!! 队列应该没有用,严格的说,用的是数据结构里面“树”的知识。(更严格的说,其实是“图”) Gorgon Meducer 傻孩子:
太谢谢大侠的指导了!真的很不好意思!让你手把手的教我!!我去好好看看数据结构 争取把你的菜单结构搞懂!!!!做出一个自己的小东西来!!!!!再次表示忠心的感谢!!!!! 请教一下,这个菜单程序,如果用在51单片机内可以使用吗 Gorgon Meducer 傻孩子:
傻孩子大侠,我很高兴把你的菜单结构弄懂了,非常非常的感谢你无私的帮助!是你让我从无知到有知!从迷惘到开明,再次表示衷心的感谢!
但是我碰到的一个问题是:我想实现一个3、4级或者更多级的菜单,不知道该怎么写!这个问题困扰了我很久也没办法解决!穷途之中再次想起了你!尽管很不好意思打扰大侠!不知道大侠能不能再在百忙之中抽出一点指点一二呀!多多感谢!!!! Gorgon Meducer 傻孩子:
大侠这么快就回复我了, 真是太感谢了,其实我也知道你菜单的意思了,多级的话就是再增加几个菜单结构型数组,也就是把这个链表作长一点 但是我我感觉那样的话,内存用起来就很可观了,然后我又仔细看了《一个占用内存极小的菜单实现》的那个例子,他用查索引号找对应的函数的方法,这样的话, 内存是少了, 但是改动就又很大。更何况我只是能看懂两位大侠的意思,照搬还可以,要我自己想又想不出好的办法来解决这个问题, 再三厚着脸皮来了,不知道大侠还能指点一二么?多多谢谢!!! 想用白菜的价来买肉是买不到的 【20楼】 liaowei
没办法!菜鸟的很!阁下如有好的建议!还望不吝赐教!本人不胜感激啊! mark 学习贴,顶一个。 MARK 学习贴,顶一个。 liaogang1314 发表于 2010-11-15 15:48 static/image/common/back.gif
Gorgon Meducer 傻孩子:
大侠这么快就回复我了, 真是太感谢了,其实我也知道你菜单的意思了,多级 ...
原则上菜单都应该保存在__flash里面……这样对SRAM消耗就没有那么大。 菜单需要 一直关注大侠,有问题要问:
1,在计算机层次上,汇编语言带来了什么抽象?
2,在汇编语言上,C及其编译器带来了什么抽象?
3,C++等面向对象带来了什么抽象? mark。自己一开始做过多级菜单。但不是很好。
“树”,回家后也好好研究一下。 发现一个东西:多级菜单。。。打开了一扇门。。。 谢谢分享 New_Bird_De_Bug 发表于 2012-12-23 21:27
一直关注大侠,有问题要问:
1,在计算机层次上,汇编语言带来了什么抽象?
2,在汇编语言上,C及其编译器 ...
概念一直在变,只有追求偷懒的“抽象”是不变的。 New_Bird_De_Bug 发表于 2012-12-23 21:27
一直关注大侠,有问题要问:
1,在计算机层次上,汇编语言带来了什么抽象?
2,在汇编语言上,C及其编译器 ...
我的看法是:
1.机器指令到汇编语言,从很难记住的01代码成了容易记住和书写的助记符。对应关系大约是一一对应(不考虑宏)。
2.汇编到C,一次抽象,对应关系是一句C代码对应多个汇编代码。而且C语言更符合人的思维习惯,不用考虑那么多底层细节了(交给编译器来做)。
3.C到C++,编程思想的改变。C和汇编都是面向过程的编程语言,其实本质上单个CPU执行代码是串行的,即一句一句执行,我们写程序之前分析问题,也是想着怎么一步一步解决这个问题,然后写成编程语言。这是你一个人在做事情。
而面向对象,在分析问题的时候,只需要把问题分解为一个一个的"对象",每个对象就像是一个一个的人,可以"做一些事情",有一些"口袋",里面装着一些东西,现在,你需要解决的问题,由这一群人来共同解决。
但是本质上,单个CPU只能一步一步来执行指令,想让一个人变成一群人(不是人格分裂),只要这个人不停的在这群人的身份之间转变就行,一会是这个,一会是另一个人(操作系统完成这个转变的任务,还可以写成状态机的形式)。
第一次交流,不对的地方还请各位老师指正!
——大三狗。
页:
[1]