/******************************************************************************* * 菜单控制 模块退出时必须向菜单管理发出菜单关闭消息 ********************************************************************************/
#include <iom128v.h> #include <macros.h> #include <Eeprom.h>
#include "Const.h" #include "EepromEnum.h" #include "News.h" #include "NewsEnum.h" #include "Window.h" #include "Source.h"
#include "LcdDrive.h" #include "Timer.h" #include "CpuEeprom.h" #include "Serial.h" #include "Math.h" #include "Sound.h"
enum{ eLEFT, eRIGHT };
#define TIME_MENULIMIT 40 //菜单显示时间
static unsigned char mMenu_TimeLimit; //控制菜单显示时间,以秒为单位
static unsigned char mMenu_Id; //在使用的菜单的层里面的索引 static unsigned char mMenu_ItemId; //菜单层的项索引 static unsigned char fMenu_Select; /*=1菜单选中了,已经离开菜 单,执行功能去了,执行完返回控制给菜单,会清0*/
static unsigned char fMenu_RequStore; /*菜单选择有效请求,模块响应 后,退出时发nMenu_ReturnControl,控制权交回菜单*/
/****************************************************************** 菜单结构定义 ******************************************************************/ struct MenuUnit{ //菜单单元结构 unsigned char mX; unsigned char mY;
unsigned char Str[6]; //显示的字符串
unsigned char mSubId; /*选中后执行的子菜单一层的ID,==0无,和mNewsId关联*/ unsigned char mNewsId; /*选中后执行的消息ID,==0无,和mSubId关联*/
unsigned char mReturnId; /*退出后执行的菜单层的ID号,==0相当关闭,由本身*/ };
static const struct MenuUnit *psMenuCurrentUnit;
/****************************************************************** 菜单构造 x,y, 字符串 要执行的ID,要执行的消息 返回执行的ID ******************************************************************/ const struct MenuUnit sMenuUnit_Close[]={ //每行是个SubId.关闭菜单,ID=0 0,9, "x097", 0, nXxx0_On, 0, //关闭菜单 };
const struct MenuUnit sMenuUnit_Main[]={ //每行是个SubId.主菜单,ID=1 0,9, "x090", 2, 0, 0, // 20,9, "x091", 0, nXxx1_On, 0, // 40,9, "x092", 0, nXxx2_SetupOn, 0, //设置 60,9, "x098", 3, nSetVolume_On, 0, //参数调节,执行ID=3的菜单 80,9, "x099", 0, nPrinter_SetupOn, 0, //打印设置 100,9, "x096", 0, 0, 0, //BACK,向上回去 };
const struct MenuUnit sMenuUnit_Moudel[]={ //每行是个SubId.模块菜单,ID=2 0,4, "Xxx31", 0, nXxx30_SetupOn, 0, //Xxx30 36,4, "Xxx32", 0, nXxx31_SetupOn, 0, //Xxx31 72,4, "Xxx4", 0, nXxx4_SetupOn, 0, //Xxx4 0,14, "Xxx5", 0, nXxx5_SetupOn, 0, //Xxx5 36,14, "Xxx5", 0, nXxx5_SetupOn, 0, //Xxx5 72,14, "Xxx5", 0, nXxx5_SetupOn, 0, //Xxx5 108,9, "x096", 1, 0, 0, //BACK,向上回去 };
const struct MenuUnit sMenuUnit_AdjVolume[]={ //每行是个SubId.参数调节菜单,ID=3 0,9, "x094", 0, nSetAlarmVolume_On, 4, //声音,返回执行ID=4,继续报警音量调节 };
const struct MenuUnit sMenuUnit_AdjAlarm[]={ //每行是个SubId.参数调节菜单,ID=4 0,9, "x094", 0, nSetLight_On, 5, //声音,返回执行ID=5,继续亮度 };
const struct MenuUnit sMenuUnit_AdjLight[]={ //每行是个SubId.参数调节菜单,ID=5 0,9, "x094", 0, 0, 0, //亮度,返回执行ID=0. };
//一层菜单,有很多菜单单元组成 const struct MenuUnit * const psMenuLayer[]={ sMenuUnit_Close, //ID=0,关闭菜单 sMenuUnit_Main, //ID=1,主菜单 sMenuUnit_Moudel, //ID=2,模块选择 sMenuUnit_AdjVolume, //ID=3,设置音量 sMenuUnit_AdjAlarm, //ID=4,设置报警音量 sMenuUnit_AdjLight, //ID=5,亮度调节 };
const unsigned char mMenuLayerMax[]={ sizeof(sMenuUnit_Close)/sizeof(struct MenuUnit), //ID=0,关闭菜单 sizeof(sMenuUnit_Main)/sizeof(struct MenuUnit), //ID=1,主菜单 sizeof(sMenuUnit_Moudel)/sizeof(struct MenuUnit), //ID=2,模块选择 sizeof(sMenuUnit_AdjVolume)/sizeof(struct MenuUnit), //ID=3,设置音量 sizeof(sMenuUnit_AdjAlarm)/sizeof(struct MenuUnit), //ID=4,设置报警音量 sizeof(sMenuUnit_AdjLight)/sizeof(struct MenuUnit), //ID=5,亮度调节 };
#define dSPEEDKEY_MenuId 1 //快捷键对应功能的菜单项 #define dSPEEDKEY_MenuItemId 0 //快捷键对应功能的菜单项中的选项
/****************************************************************** 清除菜单区域 ******************************************************************/ void InMenuWindowCls(void) { Lcd_SetupId(Eeprom_Read(eP_DW_Menu)); LcdData_ClrScreen( (em_BLACK<<4)+em_BLACK ); }
/****************************************************************** 显示当前菜单 必须窗口有效 只有一项时不反白显示.这样关闭菜单或单参数菜单不反白。 已经设置好全局的菜单指针 ******************************************************************/ void InMeun_DispItem(unsigned char mId) { Lcd_SetupId(Eeprom_Read(eP_DW_Menu)); if(LcdData_WindowVisible()==False)return;
psMenuCurrentUnit=&(psMenuLayer[mMenu_Id])[mId]; //得到当前菜单项的结构指针
LcdData_MoveTo( (*psMenuCurrentUnit).mX,(*psMenuCurrentUnit).mY ); if((mId==mMenu_ItemId)&&(mMenuLayerMax[mMenu_Id]>1)){ //反白显示 LcdData_SwapColor(); } LcdData_CodeStrings( (*psMenuCurrentUnit).Str,em_CharOverlay );
psMenuCurrentUnit=&(psMenuLayer[mMenu_Id])[mMenu_ItemId]; //得到当前菜单项的结构指针 }
/****************************************************************** 移动 mXxx1=eLEFT,左,否则右 ******************************************************************/ void InMeun_MoveItem(unsigned char mXxx1) { unsigned char i;
if(mMenu_Id==0){ //展开 mMenu_Id=1; mMenu_ItemId=0;
for(i=0;i<mMenuLayerMax[1];i++){ InMeun_DispItem(i); } } else { if(mXxx1==eLEFT){ i=mMenu_ItemId; if(mMenu_ItemId==0){ mMenu_ItemId=mMenuLayerMax[mMenu_Id]-1; } else mMenu_ItemId--; } else { i=mMenu_ItemId++; if(mMenu_ItemId==mMenuLayerMax[mMenu_Id]){ mMenu_ItemId=0; } } InMeun_DispItem(i); InMeun_DispItem(mMenu_ItemId); } }
/****************************************************************** 显示全部菜单项,并设置相应参数 ******************************************************************/ void InMenu_DispNewMenuItem(unsigned char mItem) { unsigned char i,j;
InMenuWindowCls(); mMenu_ItemId=0; mMenu_Id=mItem;
j=mMenuLayerMax[mMenu_Id];
for(i=0;i<j;i++)InMeun_DispItem(i); }
/****************************************************************** 菜单确认时执行动作 ******************************************************************/ void InMenu_Valid(void) { if((fMenu_RequStore)||(fMenu_Select))return;
if( (*psMenuCurrentUnit).mNewsId>0){ //有消息,改变当前消息。 fMenu_RequStore=(*psMenuCurrentUnit).mNewsId; //有选择,等待模块返回 fMenu_Select=1; //选择有效
News_Push(fMenu_RequStore); if((*psMenuCurrentUnit).mSubId>0){ //有子菜单命令,执行 InMenu_DispNewMenuItem((*psMenuCurrentUnit).mSubId); } } else { InMenu_DispNewMenuItem((*psMenuCurrentUnit).mSubId); } }
/****************************************************************** 主菜单选中时,执行的转换或相应处理 转发消息 ******************************************************************/ void InMenu_ChangeNews(void) { News_Replace((*psMenuCurrentUnit).mNewsId+1+gNews_Word-eNews_KeySpeed); }
/****************************************************************** 菜单中的消息转换的消息处理:eNews_beign ******************************************************************/ void Menu_NewsPreProcess(void) { if(gNews_Word<eNews_KeySpeed){ switch(gNews_Word){ case eNews_KeyPush0: // Timer3_Switch(); break;
case eNews_KeyPush1: //Xxx5 News_Replace(nXxx5_Ctl_Key); break;
case eNews_KeyPush2: // News_Replace(nSound_ClockSwitch); break;
case eNews_KeyPush3: //保留 News_Pop(); break; } return; }
if( gNews_Word>eNews_KeyPushReturn )return; //只对快捷键,左,右,回车控制
mMenu_TimeLimit=0; //清计时器
if(fMenu_Select==1){ InMenu_ChangeNews(); //已经在有效状态,转换消息 return; }
//在菜单控制下 switch(gNews_Word){ case eNews_KeySpeed: //快捷键 News_Pop(); if(mMenu_Id){ //菜单已经展开,关闭菜单 InMenu_DispNewMenuItem(0); } else { //直接进入快捷键对应的菜单选项 mMenu_ItemId=dSPEEDKEY_MenuItemId; mMenu_Id=dSPEEDKEY_MenuId;
InMenu_Valid(); //菜单有效 } break;
case eNews_KeyPushLeft: News_Pop(); InMeun_MoveItem(eLEFT); break;
case eNews_KeyPushRight: News_Pop(); InMeun_MoveItem(eRIGHT); break;
case eNews_KeyPushReturn: //对当前选中 News_Pop(); InMenu_Valid(); //菜单有效 break; } }
/****************************************************************** 菜单中的消息滞后处理,处理未被接收和处理的消息。 属于菜单发出的模块消息,未被接收,将是菜单退出,并清除该消息 ******************************************************************/ void Menu_NewsLagProcess(void) { unsigned char i; if(gNews_Word==fMenu_RequStore){ //向模块发出的消息未被接受,且菜单在Select状态,退出到上层 fMenu_RequStore=fMenu_Select=0; InMenu_DispNewMenuItem((*psMenuCurrentUnit).mReturnId); //返回时显示的菜单项 } //销毁 i=News_Pop(); while(i){i--;News_Pop();} }
/****************************************************************** 菜单中的消息处理: 模块退出返回的消息 执行当前菜单的返回ID ******************************************************************/ void Menu_NewsProcess(void) { unsigned char i;
i=gNews_Word; News_Pop(); //接受消息
switch(i){ case nMenu_ReturnControl: fMenu_RequStore=fMenu_Select=0; //选择无效状态 InMenu_DispNewMenuItem((*psMenuCurrentUnit).mReturnId); //返回时显示的菜单项 break;
case nMenu_OverFlow: //菜单时间到 if(fMenu_Select){ News_PreInsert(eNews_KeySpeed); //快捷 } else { fMenu_RequStore=fMenu_Select=0; InMenu_DispNewMenuItem(0); //菜单回根 } break; } }
/****************************************************************** 菜单循环控制,主要显示延时控制 1S进入 ******************************************************************/ void Menu_Loop(void) { if( (fMenu_Select)||(mMenu_Id) ){
if(++mMenu_TimeLimit>=TIME_MENULIMIT){ //超时,关闭菜单动作 mMenu_TimeLimit=0; News_Push(nMenu_OverFlow); //菜单时间到 } } }
/****************************************************************** 菜单初始化 ******************************************************************/ void Menu_Init(void) { mMenu_TimeLimit=0; fMenu_RequStore=fMenu_Select=0; //选择无效状态 InMenu_DispNewMenuItem(0); //菜单回根
//预处理消息注册 News_Register(Menu_NewsPreProcess,eNews_beign,eNews_beign);
//滞后处理消息注册 News_Register(Menu_NewsLagProcess,eNews_Lag,eNews_Lag);
//本模块使用的消息处理函数 News_Register(Menu_NewsProcess,nMenu_ReturnControl,nMenu_OverFlow); } |