搜索
bottom↓
回复: 13

请问一下,如何用结构做菜单?

[复制链接]

出0入0汤圆

发表于 2006-6-20 21:30:50 | 显示全部楼层 |阅读模式
我前几天做液晶菜单,现在已经成功了,但用的是数组,但我感觉应该结构比较清晰,但不知道怎么用,忘能指教

比如做一个设置日月年,小时,分钟,秒的菜单,前几天也向各位请教了,已经成功,但现在就想用结构做,谢谢,这是前几天询问的帖子,上面有具体说明

http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=638375&bbs_page_no=1&bbs_id=1000

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

发表于 2006-6-20 21:37:33 | 显示全部楼层
给你一个例子看看吧.

LCD多级菜单具体实现









另:技术问题不要问偶,偶不懂的.

出0入0汤圆

发表于 2006-6-20 21:37:43 | 显示全部楼层
老古论坛上有篇菜单程序可以参考下。
头像被屏蔽

出0入0汤圆

发表于 2006-6-21 07:17:53 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2006-6-21 07:45:52 | 显示全部楼层
果然不好找,我自己今天去找了趟也没找到,幸好备份了,贴上来吧,不过如果有版权问题就请版权所有者联系我或者ARMOK把帖子删了吧。





/*******************************************************************************

菜单控制

模块退出时必须向菜单管理发出菜单关闭消息

********************************************************************************/

#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);

}

出0入0汤圆

发表于 2006-6-21 09:10:14 | 显示全部楼层
收到,谢谢!

出0入0汤圆

发表于 2009-6-5 15:52:53 | 显示全部楼层
谢谢,目前正在学习。

出0入0汤圆

发表于 2009-6-5 21:39:44 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-23 11:19:57 | 显示全部楼层
很强大!!!!!!

出0入0汤圆

发表于 2011-5-10 17:26:02 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-10-19 22:41:05 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-10-20 23:49:00 | 显示全部楼层
很强大!!!!!!

出0入0汤圆

发表于 2012-12-11 13:59:43 | 显示全部楼层
好文,书签

出0入0汤圆

发表于 2013-8-17 17:46:00 | 显示全部楼层
正在学习中,多谢
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-10-3 16:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表