作者在 2009-06-15 00:08:55 发布以下内容
struct MenuItem
{
short MenuCount;
char *DisplayString;
void (*Subs)();
struct MenuItem *ChildrenMenus;
struct MenuItem *ParentMenus;
}
说明:之所以能使用struct MenuItem *ChildrenMenus; 指向多个子菜单,是因为子菜单本身就是一个数组类型的线性空间
因此在使用ChildrenMenus指向了子菜单数组的首地址后,我们就已经达到了对应的一片线性空间,而每个子菜单项占据的空间大小是已
知的,因此再加上额外的 MenuCount指明子菜单的个数,显然就能正确的表述整个子菜单
缺点:不能由用户动态的更改菜单结构,而是在编程代码中确定结构,因此不是很灵活
#define MAX_SUBMENU_NUM 10
typedef struct tagMenuTree {
char MenuName[20]; //关联数据为菜单项名称
int SubMenuNum; //当前结点的子菜单个数
struct tagMenuTree * NextNode[MAX_SUBMENU_NUM]; //记录当前结点的子菜单
struct tagMenuTree * Parent; //记录上级菜单
} MenuTree,*pMenuTree;
这样的菜单结构定义就不必要求 子菜单指向的是一个数组结构,因为指针的数组可以把每个子菜单地址单独的指出来,但这个结构需要定义一个常量 MAX_SUBMENU_NUM 不好确定(因此在一定范围内可以添加子菜单)
更灵活的方式(WINDOWS 采用的就是这种构架,可以随意的添加)
typedef struct tagMenuTree {
char MenuName[20]; //关联数据为菜单项名称
struct tagMenuTree* pParent; //上级菜单
struct tagMenuTree* pChildHead; //子菜单头指针
struct tagMenuTree* pChildTail; //子菜单尾指针
struct tagMenuTree* pNext; //兄弟菜单中下一个菜单
struct tagMenuTree* pPrev; //兄弟菜单中前一个菜单
} MenuTree,*pMenuTree;
但是这样的多叉树编码比较麻烦,需要一定的编程功底 20090614
--------------------------------------------------------------------------------------------
------------------------------------------
贴一段代码大家看看哈(我用来做目录的引擎)
(以上的是我在羚羊上实现的,但是原理是一样的,特别是Menu.h可以直接使用)
Menu.h
-------------------------------
#ifndef __MENU_h__
#define __MENU_h__
#include "Functions.h"
/****************************************************
* 支持库说明:提供了使用菜单的基本数据结构 *
* 作者: 傻孩子 *
* 日期: 2005年6月9日 *
****************************************************/
/**********************
* 目录结构体定义 *
**********************/
struct MenuItem
{
short MenuCount;
char *DisplayString;
void (*Subs)();
struct MenuItem *ChildrenMenus;
struct MenuItem *ParentMenus;
}Null;
void NullSubs(void)
{
}
/****************************************************
* 使用说明: *
* 要定义一个菜单,需要做以下几步工作 *
* 1、定义一个结构体数组 *
* 2、如果这个菜单是子菜单,那么把上级菜单的 *
* *ChildrenMenus指针指向该数组的首地址, *
* 并且设置ParentMenus为上层目录的地址 *
* 3、如果这个菜单是跟菜单,那么直接将MenuPoint *
* 指针指向该数组的首地址 *
* 4、通过写一个函数为该数组的每一个元素初始化 *
* 5、如果菜单项是最终选项,那么将*ChildrenMenus*
* 置为NULL,将函数指针*Subs指向实现功能的 *
* 函数。 *
****************************************************/
/**************************************************************** zyd 20090614
说明:之所以能使用struct MenuItem *ChildrenMenus; 指向多个子菜单,是因为子菜单本身就是一个数组类型的线性空间
因此在使用ChildrenMenus指向了子菜单数组的首地址后,我们就已经达到了对应的一片线性空间,而每个子菜单项占据的空间大小是已
知的,因此再加上额外的 MenuCount指明子菜单的个数,显然就能正确的表述整个子菜单
缺点:不能由用户动态的更改菜单结构,而是在编程代码中确定结构,因此不是很灵活
#define MAX_SUBMENU_NUM 10
typedef struct tagMenuTree {
char MenuName[20]; //关联数据为菜单项名称
int SubMenuNum; //当前结点的子菜单个数
struct tagMenuTree * NextNode[MAX_SUBMENU_NUM]; //记录当前结点的子菜单
struct tagMenuTree * Parent; //记录上级菜单
} MenuTree,*pMenuTree;
这样的菜单结构定义就不必要求 子菜单指向的是一个数组结构,因为指针的数组可以把每个子菜单地址单独的指出来,但这个结构需要定义一
个常量 MAX_SUBMENU_NUM 不好确定(因此在一定范围内可以添加子菜单)
更灵活的方式(WINDOWS 采用的就是这种构架,可以随意的添加)
typedef struct tagMenuTree {
char MenuName[20]; //关联数据为菜单项名称
struct tagMenuTree* pParent; //上级菜单
struct tagMenuTree* pChildHead; //子菜单头指针
struct tagMenuTree* pChildTail; //子菜单尾指针
struct tagMenuTree* pNext; //兄弟菜单中下一个菜单
struct tagMenuTree* pPrev; //兄弟菜单中前一个菜单
} MenuTree,*pMenuTree;
但是这样的多叉树编码比较麻烦,需要一定的编程功底 20090614 *****************************/
struct MenuItem MainMenu[3];
struct MenuItem TimeMenu[4];
struct MenuItem VoiceMenu[5];
struct MenuItem RobotMenu[5];
struct MenuItem FlashMenu[5];
/***********************
* 函 数 声 明 区 *
***********************/
void MainMenuInit(void);
void TimeMenuInit(void);
void VoiceMenuInit(void);
void RobotMenuInit(void);
void FlashMenuInit(void);
/**************************************************************
* 函数说明:Flash处理目录初始化函数 *
**************************************************************/
void FlashMenuInit(void)
{
FlashMenu[0].MenuCount = 5;
FlashMenu[0].DisplayString = " Flash Record ";
FlashMenu[0].Subs = FlashRecord;
FlashMenu[0].ChildrenMenus = &Null;
FlashMenu[0].ParentMenus = MainMenu;
FlashMenu[1].MenuCount = 5;
FlashMenu[1].DisplayString = " Play ";
FlashMenu[1].Subs = FlashPlay;
FlashMenu[1].ChildrenMenus = &Null;
FlashMenu[1].ParentMenus = MainMenu;
FlashMenu[2].MenuCount = 5;
FlashMenu[2].DisplayString = " Pause ";
FlashMenu[2].Subs = FlashPause;
FlashMenu[2].ChildrenMenus = &Null;
FlashMenu[2].ParentMenus = MainMenu;
FlashMenu[3].MenuCount = 5;
FlashMenu[3].DisplayString = " Flash Delete ";
FlashMenu[3].Subs = FlashDelete;
FlashMenu[3].ChildrenMenus = &Null;
FlashMenu[3].ParentMenus = MainMenu;
FlashMenu[4].MenuCount = 5;
FlashMenu[4].DisplayString = " Back ";
FlashMenu[4].Subs = NullSubs;
FlashMenu[4].ChildrenMenus = MainMenu;
FlashMenu[4].ParentMenus = MainMenu;
}
/**************************************************************
* 函数说明:机器人控制目录初始化函数 *
**************************************************************/
void RobotMenuInit(void)
{
RobotMenu[0].MenuCount = 5;
RobotMenu[0].DisplayString = " Turn Left ";
RobotMenu[0].Subs = RobotTurnLeft;
RobotMenu[0].ChildrenMenus = &Null;
RobotMenu[0].ParentMenus = MainMenu;
RobotMenu[1].MenuCount = 5;
RobotMenu[1].DisplayString = " Turn Right ";
RobotMenu[1].Subs = RobotTurnRight;
RobotMenu[1].ChildrenMenus = &Null;
RobotMenu[1].ParentMenus = MainMenu;
RobotMenu[2].MenuCount = 5;
RobotMenu[2].DisplayString = " Go Ahead ";
RobotMenu[2].Subs = RobotGoAhead;
RobotMenu[2].ChildrenMenus = &Null;
RobotMenu[2].ParentMenus = MainMenu;
RobotMenu[3].MenuCount = 5;
RobotMenu[3].DisplayString = " Go Back ";
RobotMenu[3].Subs = RobotGoBack;
RobotMenu[3].ChildrenMenus = &Null;
RobotMenu[3].ParentMenus = MainMenu;
RobotMenu[4].MenuCount = 5;
RobotMenu[4].DisplayString = " Back ";
RobotMenu[4].Subs = NullSubs;
RobotMenu[4].ChildrenMenus = MainMenu;
RobotMenu[4].ParentMenus = MainMenu;
}
/**************************************************************
* 函数说明:声音处理目录初始化函数 *
**************************************************************/
void VoiceMenuInit(void)
{
VoiceMenu[0].MenuCount = 5;
VoiceMenu[0].DisplayString = " Voice Record ";
VoiceMenu[0].Subs = VoiceRecord;
VoiceMenu[0].ChildrenMenus = &Null;
VoiceMenu[0].ParentMenus = MainMenu;
VoiceMenu[1].MenuCount = 5;
VoiceMenu[1].DisplayString = " Play ";
VoiceMenu[1].Subs = Play;
VoiceMenu[1].ChildrenMenus = &Null;
VoiceMenu[1].ParentMenus = MainMenu;
VoiceMenu[2].MenuCount = 5;
VoiceMenu[2].DisplayString = " Pause ";
VoiceMenu[2].Subs = Pause;
VoiceMenu[2].ChildrenMenus = &Null;
VoiceMenu[2].ParentMenus = MainMenu;
VoiceMenu[3].MenuCount = 5;
VoiceMenu[3].DisplayString = " Voice Delete ";
VoiceMenu[3].Subs = VoiceDelete;
VoiceMenu[3].ChildrenMenus = &Null;
VoiceMenu[3].ParentMenus = MainMenu;
VoiceMenu[4].MenuCount = 5;
VoiceMenu[4].DisplayString = " Back ";
VoiceMenu[4].Subs = NullSubs;
VoiceMenu[4].ChildrenMenus = MainMenu;
VoiceMenu[4].ParentMenus = MainMenu;
}
/**************************************************************
* 函数说明:时间设定子目录初始化 *
**************************************************************/
void TimeMenuInit(void)
{
TimeMenu[0].MenuCount = 4;
TimeMenu[0].DisplayString = " Time Set ";
TimeMenu[0].Subs = TimeSet;
TimeMenu[0].ChildrenMenus = &Null;
TimeMenu[0].ParentMenus = MainMenu;
TimeMenu[1].MenuCount = 4;
TimeMenu[1].DisplayString = " Date Set ";
TimeMenu[1].Subs = DateSet;
TimeMenu[1].ChildrenMenus = &Null;
TimeMenu[1].ParentMenus = MainMenu;
TimeMenu[2].MenuCount = 4;
TimeMenu[2].DisplayString = " AlertSet ";
TimeMenu[2].Subs = AlertSet;
TimeMenu[2].ChildrenMenus = &Null;
TimeMenu[2].ParentMenus = MainMenu;
TimeMenu[3].MenuCount = 4;
TimeMenu[3].DisplayString = " Back ";
TimeMenu[3].Subs = NullSubs;
TimeMenu[3].ChildrenMenus = MainMenu;
TimeMenu[3].ParentMenus = MainMenu;
}
/**************************************************************
* 函数说明:根目录初始化 *
**************************************************************/
void MainMenuInit(void)
{
MainMenu[0].MenuCount = 3;
MainMenu[0].DisplayString = " Time Set ";
MainMenu[0].Subs = NullSubs;
MainMenu[0].ChildrenMenus = TimeMenu;
MainMenu[0].ParentMenus = &Null;
MainMenu[1].MenuCount = 3;
MainMenu[1].DisplayString = " Voice Center ";
MainMenu[1].Subs = NullSubs;
MainMenu[1].ChildrenMenus = VoiceMenu;
MainMenu[1].ParentMenus = &Null;
/*
MainMenu[2].MenuCount = 3;
MainMenu[2].DisplayString = " Robot Control ";
MainMenu[2].Subs = NullSubs;
MainMenu[2].ChildrenMenus = RobotMenu;
MainMenu[2].ParentMenus = &Null;
*/
MainMenu[2].MenuCount = 3;
MainMenu[2].DisplayString = " Flash Option ";
MainMenu[2].Subs = NullSubs;
MainMenu[2].ChildrenMenus = FlashMenu;
MainMenu[2].ParentMenus = &Null;
}
#endif
Function.h
------------------------------
#ifndef __FUNCTIONS_h__
#define __FUNCTIONS_h__
/****************************************************
* 支持库说明:系统菜单功能文件宏 *
* 日期: 2005年6月9日 *
****************************************************/
#include "TimeSet.h"
#include "VoiceCenter.h"
#include "RobotControl.h"
#include "FlashOption.h"
/*--------------------------------
上面包含的头文件里面包含了菜单
功能选项所要调用的函数。
--------------------------------*/
#endif
main.c
-----------------------------
#include "GRAPH_Command.h"
#include "Functions.h"
#include "Menu.h"
/***********************
* 按键功能键宏定义 *
***********************/
# define UP 0
# define Down 4
# define Enter 5
# define Esc 1
# define Reset 2
/***********************
* 全局变量声明区 *
***********************/
struct MenuItem (*MenuPoint) = MainMenu;
short DisplayStart = 0;
short UserChoose = 0;
short DisplayPoint = 0;
short MaxItems;
/*****************************
* Struct MenuItem: *
* short MenuCount; *
* char *DisplayString; *
* void (*Subs)(); *
* MenuItem *ChildrenMenus;*
* MenuItem *ParentMenus; *
*****************************/
/***********************
* 函 数 声 明 区 *
***********************/
extern void ClearWatchDog();
void MenuInitialation(void);
void SystemInitialation(void);
void ShowMenu(void);
short GetKeyNum(void);
/**************************************************************
* 函数说明:系统初始化函数 *
**************************************************************/
void SystemInitialation(void)
{
Init_sys();
Enable_LCD(); //初始化字库 函数定义在
MenuInitialation(); //初始化菜单
GRAPH //图形初始化
}
/**************************************************************
* 函数说明:目录初始化函数 *
**************************************************************/
void MenuInitialation(void)
{
MainMenuInit();
TimeMenuInit();
VoiceMenuInit();
RobotMenuInit();
FlashMenuInit();
}
/**************************************************************
* 函数说明:目录显示函数 *
**************************************************************/
void ShowMenu(void)
{
short n = 0;
MaxItems = MenuPoint[0].MenuCount;
DisplayPoint = DisplayStart;
if (MaxItems >= 4)
{
for (n = 0;n<4;n++)
{
LOCATE(n+1,1);
PRINT(MenuPoint[DisplayPoint].DisplayString);
if ((DisplayPoint) == UserChoose)
{
BOX(1,n*16+1,126,(n+1)*16-2,1,1);
}
DisplayPoint +=1;
if ((DisplayPoint) == (MaxItems))
{
DisplayPoint = 0;
}
}
}
else
{
for (n = 0;n<MaxItems;n++)
{
LOCATE(n+1,1);
PRINT(MenuPoint[DisplayPoint].DisplayString);
if ((DisplayPoint) == UserChoose)
{
BOX(1,n*16+1,126,(n+1)*16-2,1,1);
}
DisplayPoint +=1;
if ((DisplayPoint) == (MaxItems))
{
DisplayPoint = 0;
}
}
}
//BOX(0,0,127,63,2,2);
}
/**************************************************************
* 函数说明:获得键值函数 *
**************************************************************/
short GetKeyNum(void)
{
short TempKeyNum = 0;
TempKeyNum = F_Key_Scan(); //获取按键值
*P_IOA_Dir = 0x01ff;
*P_IOA_Attrib = 0x01ff;
*P_IOA_Data = 0x01ff;
return TempKeyNum;
}
/**************************************************************
* 函数说明:主函数 *
**************************************************************/
int main()
{
short KeyNum = 0xff;
SystemInitialation(); //系统初始化
ShowMenu();
while(1)
{
ClearWatchDog(); //喂狗
KeyNum = GetKeyNum(); //获取按键值
/*******************目录操作*********************/
/***************************************
* [按键说明] *
* ----------------------------------- *
* [K1] UP(向上) *
* [K5] Down(向下) *
* [K2] Esc(后退) *
* [K6] Enter(确定) *
* [K3] 返回根目录 *
***************************************/
if (KeyNum != 0xff)
{
ShowMenu();
switch(KeyNum)
{
case UP:
UserChoose --;
if (UserChoose < 0)
{
UserChoose = MaxItems-1;
}
break;
case Esc:
if (MenuPoint[0].ParentMenus != &Null)
{
MenuPoint = MenuPoint[0].ParentMenus;
UserChoose = 0;
DisplayStart = 0;
}
break;
case Down:
UserChoose ++;
if (UserChoose == MaxItems)
{
UserChoose = 0;
}
break;
case Enter:
if (MenuPoint[UserChoose].Subs != NullSubs)
{
(*MenuPoint[UserChoose].Subs)();
}
else if (MenuPoint[UserChoose].ChildrenMenus != &Null)
{
MenuPoint = MenuPoint[UserChoose].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();
}
/*******************目录操作*********************/
}
}
说明一下:
我定义了一个结构体来表示菜单的每一个选项
通过指针来跳转子目录或者调用功能函数
支持滚屏、多级子菜单、网络式超链接方式(非树形)、风格修改简单。
使用这样的结构,可以很方便的通过修改单独的菜单项来更形菜单,不用在主程序里面修改任何东西,扩展方便,节约资源(某种程度上来说
是的,不用因为添加了一个新的子菜单,就重新扩展无用的代码)。程序里面有很详细的说明,大家可以看一下哈,交流一下哈。
{
short MenuCount;
char *DisplayString;
void (*Subs)();
struct MenuItem *ChildrenMenus;
struct MenuItem *ParentMenus;
}
说明:之所以能使用struct MenuItem *ChildrenMenus; 指向多个子菜单,是因为子菜单本身就是一个数组类型的线性空间
因此在使用ChildrenMenus指向了子菜单数组的首地址后,我们就已经达到了对应的一片线性空间,而每个子菜单项占据的空间大小是已
知的,因此再加上额外的 MenuCount指明子菜单的个数,显然就能正确的表述整个子菜单
缺点:不能由用户动态的更改菜单结构,而是在编程代码中确定结构,因此不是很灵活
#define MAX_SUBMENU_NUM 10
typedef struct tagMenuTree {
char MenuName[20]; //关联数据为菜单项名称
int SubMenuNum; //当前结点的子菜单个数
struct tagMenuTree * NextNode[MAX_SUBMENU_NUM]; //记录当前结点的子菜单
struct tagMenuTree * Parent; //记录上级菜单
} MenuTree,*pMenuTree;
这样的菜单结构定义就不必要求 子菜单指向的是一个数组结构,因为指针的数组可以把每个子菜单地址单独的指出来,但这个结构需要定义一个常量 MAX_SUBMENU_NUM 不好确定(因此在一定范围内可以添加子菜单)
更灵活的方式(WINDOWS 采用的就是这种构架,可以随意的添加)
typedef struct tagMenuTree {
char MenuName[20]; //关联数据为菜单项名称
struct tagMenuTree* pParent; //上级菜单
struct tagMenuTree* pChildHead; //子菜单头指针
struct tagMenuTree* pChildTail; //子菜单尾指针
struct tagMenuTree* pNext; //兄弟菜单中下一个菜单
struct tagMenuTree* pPrev; //兄弟菜单中前一个菜单
} MenuTree,*pMenuTree;
但是这样的多叉树编码比较麻烦,需要一定的编程功底 20090614
--------------------------------------------------------------------------------------------
------------------------------------------
贴一段代码大家看看哈(我用来做目录的引擎)
(以上的是我在羚羊上实现的,但是原理是一样的,特别是Menu.h可以直接使用)
Menu.h
-------------------------------
#ifndef __MENU_h__
#define __MENU_h__
#include "Functions.h"
/****************************************************
* 支持库说明:提供了使用菜单的基本数据结构 *
* 作者: 傻孩子 *
* 日期: 2005年6月9日 *
****************************************************/
/**********************
* 目录结构体定义 *
**********************/
struct MenuItem
{
short MenuCount;
char *DisplayString;
void (*Subs)();
struct MenuItem *ChildrenMenus;
struct MenuItem *ParentMenus;
}Null;
void NullSubs(void)
{
}
/****************************************************
* 使用说明: *
* 要定义一个菜单,需要做以下几步工作 *
* 1、定义一个结构体数组 *
* 2、如果这个菜单是子菜单,那么把上级菜单的 *
* *ChildrenMenus指针指向该数组的首地址, *
* 并且设置ParentMenus为上层目录的地址 *
* 3、如果这个菜单是跟菜单,那么直接将MenuPoint *
* 指针指向该数组的首地址 *
* 4、通过写一个函数为该数组的每一个元素初始化 *
* 5、如果菜单项是最终选项,那么将*ChildrenMenus*
* 置为NULL,将函数指针*Subs指向实现功能的 *
* 函数。 *
****************************************************/
/**************************************************************** zyd 20090614
说明:之所以能使用struct MenuItem *ChildrenMenus; 指向多个子菜单,是因为子菜单本身就是一个数组类型的线性空间
因此在使用ChildrenMenus指向了子菜单数组的首地址后,我们就已经达到了对应的一片线性空间,而每个子菜单项占据的空间大小是已
知的,因此再加上额外的 MenuCount指明子菜单的个数,显然就能正确的表述整个子菜单
缺点:不能由用户动态的更改菜单结构,而是在编程代码中确定结构,因此不是很灵活
#define MAX_SUBMENU_NUM 10
typedef struct tagMenuTree {
char MenuName[20]; //关联数据为菜单项名称
int SubMenuNum; //当前结点的子菜单个数
struct tagMenuTree * NextNode[MAX_SUBMENU_NUM]; //记录当前结点的子菜单
struct tagMenuTree * Parent; //记录上级菜单
} MenuTree,*pMenuTree;
这样的菜单结构定义就不必要求 子菜单指向的是一个数组结构,因为指针的数组可以把每个子菜单地址单独的指出来,但这个结构需要定义一
个常量 MAX_SUBMENU_NUM 不好确定(因此在一定范围内可以添加子菜单)
更灵活的方式(WINDOWS 采用的就是这种构架,可以随意的添加)
typedef struct tagMenuTree {
char MenuName[20]; //关联数据为菜单项名称
struct tagMenuTree* pParent; //上级菜单
struct tagMenuTree* pChildHead; //子菜单头指针
struct tagMenuTree* pChildTail; //子菜单尾指针
struct tagMenuTree* pNext; //兄弟菜单中下一个菜单
struct tagMenuTree* pPrev; //兄弟菜单中前一个菜单
} MenuTree,*pMenuTree;
但是这样的多叉树编码比较麻烦,需要一定的编程功底 20090614 *****************************/
struct MenuItem MainMenu[3];
struct MenuItem TimeMenu[4];
struct MenuItem VoiceMenu[5];
struct MenuItem RobotMenu[5];
struct MenuItem FlashMenu[5];
/***********************
* 函 数 声 明 区 *
***********************/
void MainMenuInit(void);
void TimeMenuInit(void);
void VoiceMenuInit(void);
void RobotMenuInit(void);
void FlashMenuInit(void);
/**************************************************************
* 函数说明:Flash处理目录初始化函数 *
**************************************************************/
void FlashMenuInit(void)
{
FlashMenu[0].MenuCount = 5;
FlashMenu[0].DisplayString = " Flash Record ";
FlashMenu[0].Subs = FlashRecord;
FlashMenu[0].ChildrenMenus = &Null;
FlashMenu[0].ParentMenus = MainMenu;
FlashMenu[1].MenuCount = 5;
FlashMenu[1].DisplayString = " Play ";
FlashMenu[1].Subs = FlashPlay;
FlashMenu[1].ChildrenMenus = &Null;
FlashMenu[1].ParentMenus = MainMenu;
FlashMenu[2].MenuCount = 5;
FlashMenu[2].DisplayString = " Pause ";
FlashMenu[2].Subs = FlashPause;
FlashMenu[2].ChildrenMenus = &Null;
FlashMenu[2].ParentMenus = MainMenu;
FlashMenu[3].MenuCount = 5;
FlashMenu[3].DisplayString = " Flash Delete ";
FlashMenu[3].Subs = FlashDelete;
FlashMenu[3].ChildrenMenus = &Null;
FlashMenu[3].ParentMenus = MainMenu;
FlashMenu[4].MenuCount = 5;
FlashMenu[4].DisplayString = " Back ";
FlashMenu[4].Subs = NullSubs;
FlashMenu[4].ChildrenMenus = MainMenu;
FlashMenu[4].ParentMenus = MainMenu;
}
/**************************************************************
* 函数说明:机器人控制目录初始化函数 *
**************************************************************/
void RobotMenuInit(void)
{
RobotMenu[0].MenuCount = 5;
RobotMenu[0].DisplayString = " Turn Left ";
RobotMenu[0].Subs = RobotTurnLeft;
RobotMenu[0].ChildrenMenus = &Null;
RobotMenu[0].ParentMenus = MainMenu;
RobotMenu[1].MenuCount = 5;
RobotMenu[1].DisplayString = " Turn Right ";
RobotMenu[1].Subs = RobotTurnRight;
RobotMenu[1].ChildrenMenus = &Null;
RobotMenu[1].ParentMenus = MainMenu;
RobotMenu[2].MenuCount = 5;
RobotMenu[2].DisplayString = " Go Ahead ";
RobotMenu[2].Subs = RobotGoAhead;
RobotMenu[2].ChildrenMenus = &Null;
RobotMenu[2].ParentMenus = MainMenu;
RobotMenu[3].MenuCount = 5;
RobotMenu[3].DisplayString = " Go Back ";
RobotMenu[3].Subs = RobotGoBack;
RobotMenu[3].ChildrenMenus = &Null;
RobotMenu[3].ParentMenus = MainMenu;
RobotMenu[4].MenuCount = 5;
RobotMenu[4].DisplayString = " Back ";
RobotMenu[4].Subs = NullSubs;
RobotMenu[4].ChildrenMenus = MainMenu;
RobotMenu[4].ParentMenus = MainMenu;
}
/**************************************************************
* 函数说明:声音处理目录初始化函数 *
**************************************************************/
void VoiceMenuInit(void)
{
VoiceMenu[0].MenuCount = 5;
VoiceMenu[0].DisplayString = " Voice Record ";
VoiceMenu[0].Subs = VoiceRecord;
VoiceMenu[0].ChildrenMenus = &Null;
VoiceMenu[0].ParentMenus = MainMenu;
VoiceMenu[1].MenuCount = 5;
VoiceMenu[1].DisplayString = " Play ";
VoiceMenu[1].Subs = Play;
VoiceMenu[1].ChildrenMenus = &Null;
VoiceMenu[1].ParentMenus = MainMenu;
VoiceMenu[2].MenuCount = 5;
VoiceMenu[2].DisplayString = " Pause ";
VoiceMenu[2].Subs = Pause;
VoiceMenu[2].ChildrenMenus = &Null;
VoiceMenu[2].ParentMenus = MainMenu;
VoiceMenu[3].MenuCount = 5;
VoiceMenu[3].DisplayString = " Voice Delete ";
VoiceMenu[3].Subs = VoiceDelete;
VoiceMenu[3].ChildrenMenus = &Null;
VoiceMenu[3].ParentMenus = MainMenu;
VoiceMenu[4].MenuCount = 5;
VoiceMenu[4].DisplayString = " Back ";
VoiceMenu[4].Subs = NullSubs;
VoiceMenu[4].ChildrenMenus = MainMenu;
VoiceMenu[4].ParentMenus = MainMenu;
}
/**************************************************************
* 函数说明:时间设定子目录初始化 *
**************************************************************/
void TimeMenuInit(void)
{
TimeMenu[0].MenuCount = 4;
TimeMenu[0].DisplayString = " Time Set ";
TimeMenu[0].Subs = TimeSet;
TimeMenu[0].ChildrenMenus = &Null;
TimeMenu[0].ParentMenus = MainMenu;
TimeMenu[1].MenuCount = 4;
TimeMenu[1].DisplayString = " Date Set ";
TimeMenu[1].Subs = DateSet;
TimeMenu[1].ChildrenMenus = &Null;
TimeMenu[1].ParentMenus = MainMenu;
TimeMenu[2].MenuCount = 4;
TimeMenu[2].DisplayString = " AlertSet ";
TimeMenu[2].Subs = AlertSet;
TimeMenu[2].ChildrenMenus = &Null;
TimeMenu[2].ParentMenus = MainMenu;
TimeMenu[3].MenuCount = 4;
TimeMenu[3].DisplayString = " Back ";
TimeMenu[3].Subs = NullSubs;
TimeMenu[3].ChildrenMenus = MainMenu;
TimeMenu[3].ParentMenus = MainMenu;
}
/**************************************************************
* 函数说明:根目录初始化 *
**************************************************************/
void MainMenuInit(void)
{
MainMenu[0].MenuCount = 3;
MainMenu[0].DisplayString = " Time Set ";
MainMenu[0].Subs = NullSubs;
MainMenu[0].ChildrenMenus = TimeMenu;
MainMenu[0].ParentMenus = &Null;
MainMenu[1].MenuCount = 3;
MainMenu[1].DisplayString = " Voice Center ";
MainMenu[1].Subs = NullSubs;
MainMenu[1].ChildrenMenus = VoiceMenu;
MainMenu[1].ParentMenus = &Null;
/*
MainMenu[2].MenuCount = 3;
MainMenu[2].DisplayString = " Robot Control ";
MainMenu[2].Subs = NullSubs;
MainMenu[2].ChildrenMenus = RobotMenu;
MainMenu[2].ParentMenus = &Null;
*/
MainMenu[2].MenuCount = 3;
MainMenu[2].DisplayString = " Flash Option ";
MainMenu[2].Subs = NullSubs;
MainMenu[2].ChildrenMenus = FlashMenu;
MainMenu[2].ParentMenus = &Null;
}
#endif
Function.h
------------------------------
#ifndef __FUNCTIONS_h__
#define __FUNCTIONS_h__
/****************************************************
* 支持库说明:系统菜单功能文件宏 *
* 日期: 2005年6月9日 *
****************************************************/
#include "TimeSet.h"
#include "VoiceCenter.h"
#include "RobotControl.h"
#include "FlashOption.h"
/*--------------------------------
上面包含的头文件里面包含了菜单
功能选项所要调用的函数。
--------------------------------*/
#endif
main.c
-----------------------------
#include "GRAPH_Command.h"
#include "Functions.h"
#include "Menu.h"
/***********************
* 按键功能键宏定义 *
***********************/
# define UP 0
# define Down 4
# define Enter 5
# define Esc 1
# define Reset 2
/***********************
* 全局变量声明区 *
***********************/
struct MenuItem (*MenuPoint) = MainMenu;
short DisplayStart = 0;
short UserChoose = 0;
short DisplayPoint = 0;
short MaxItems;
/*****************************
* Struct MenuItem: *
* short MenuCount; *
* char *DisplayString; *
* void (*Subs)(); *
* MenuItem *ChildrenMenus;*
* MenuItem *ParentMenus; *
*****************************/
/***********************
* 函 数 声 明 区 *
***********************/
extern void ClearWatchDog();
void MenuInitialation(void);
void SystemInitialation(void);
void ShowMenu(void);
short GetKeyNum(void);
/**************************************************************
* 函数说明:系统初始化函数 *
**************************************************************/
void SystemInitialation(void)
{
Init_sys();
Enable_LCD(); //初始化字库 函数定义在
MenuInitialation(); //初始化菜单
GRAPH //图形初始化
}
/**************************************************************
* 函数说明:目录初始化函数 *
**************************************************************/
void MenuInitialation(void)
{
MainMenuInit();
TimeMenuInit();
VoiceMenuInit();
RobotMenuInit();
FlashMenuInit();
}
/**************************************************************
* 函数说明:目录显示函数 *
**************************************************************/
void ShowMenu(void)
{
short n = 0;
MaxItems = MenuPoint[0].MenuCount;
DisplayPoint = DisplayStart;
if (MaxItems >= 4)
{
for (n = 0;n<4;n++)
{
LOCATE(n+1,1);
PRINT(MenuPoint[DisplayPoint].DisplayString);
if ((DisplayPoint) == UserChoose)
{
BOX(1,n*16+1,126,(n+1)*16-2,1,1);
}
DisplayPoint +=1;
if ((DisplayPoint) == (MaxItems))
{
DisplayPoint = 0;
}
}
}
else
{
for (n = 0;n<MaxItems;n++)
{
LOCATE(n+1,1);
PRINT(MenuPoint[DisplayPoint].DisplayString);
if ((DisplayPoint) == UserChoose)
{
BOX(1,n*16+1,126,(n+1)*16-2,1,1);
}
DisplayPoint +=1;
if ((DisplayPoint) == (MaxItems))
{
DisplayPoint = 0;
}
}
}
//BOX(0,0,127,63,2,2);
}
/**************************************************************
* 函数说明:获得键值函数 *
**************************************************************/
short GetKeyNum(void)
{
short TempKeyNum = 0;
TempKeyNum = F_Key_Scan(); //获取按键值
*P_IOA_Dir = 0x01ff;
*P_IOA_Attrib = 0x01ff;
*P_IOA_Data = 0x01ff;
return TempKeyNum;
}
/**************************************************************
* 函数说明:主函数 *
**************************************************************/
int main()
{
short KeyNum = 0xff;
SystemInitialation(); //系统初始化
ShowMenu();
while(1)
{
ClearWatchDog(); //喂狗
KeyNum = GetKeyNum(); //获取按键值
/*******************目录操作*********************/
/***************************************
* [按键说明] *
* ----------------------------------- *
* [K1] UP(向上) *
* [K5] Down(向下) *
* [K2] Esc(后退) *
* [K6] Enter(确定) *
* [K3] 返回根目录 *
***************************************/
if (KeyNum != 0xff)
{
ShowMenu();
switch(KeyNum)
{
case UP:
UserChoose --;
if (UserChoose < 0)
{
UserChoose = MaxItems-1;
}
break;
case Esc:
if (MenuPoint[0].ParentMenus != &Null)
{
MenuPoint = MenuPoint[0].ParentMenus;
UserChoose = 0;
DisplayStart = 0;
}
break;
case Down:
UserChoose ++;
if (UserChoose == MaxItems)
{
UserChoose = 0;
}
break;
case Enter:
if (MenuPoint[UserChoose].Subs != NullSubs)
{
(*MenuPoint[UserChoose].Subs)();
}
else if (MenuPoint[UserChoose].ChildrenMenus != &Null)
{
MenuPoint = MenuPoint[UserChoose].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();
}
/*******************目录操作*********************/
}
}
说明一下:
我定义了一个结构体来表示菜单的每一个选项
通过指针来跳转子目录或者调用功能函数
支持滚屏、多级子菜单、网络式超链接方式(非树形)、风格修改简单。
使用这样的结构,可以很方便的通过修改单独的菜单项来更形菜单,不用在主程序里面修改任何东西,扩展方便,节约资源(某种程度上来说
是的,不用因为添加了一个新的子菜单,就重新扩展无用的代码)。程序里面有很详细的说明,大家可以看一下哈,交流一下哈。