原创 LCD中菜单的实现和编程方法【转】

2008-1-11 10:51 5164 6 6 分类: 软件与OS

说明一下:
我定义了一个结构体来表示菜单的每一个选项
通过指针来跳转子目录或者调用功能函数

支持滚屏、多级子菜单、网络式超链接方式(非树形)、风格修改简单。

使用这样的结构,可以很方便的通过修改单独的菜单项来更形菜单,不用在主程序里面修改任何东西,扩展方便,节约资源(某种程度上来说是的,不用因为添加了一个新的子菜单,就重新扩展无用的代码)。程序里面有很详细的说明,大家可以看一下哈,交流一下哈。


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指向实现功能的   *
*         函数。                                    *
****************************************************/


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();
                 
            }
            /*******************目录操作*********************/
        }
        

}


补充一个关于作图的库函数

GRAPH_Command.h
----------------------------

#ifndef        __GRAPH_COMMAND_h__
#define        __GRAPH_COMMAND_h__
#include "lab_parameter.h"
/**********************************************************
*  函数库说明:图形函数扩展库                             *
*  版本:      v1.0                                       *
*  支持库:    Splc501sys.asm / Splc501Hardware.asm       *
*  作者:      傻孩子                                     *
*  日期:      2005年6月8日                               *
*                                                         *
*  说明:      在现有系统图形函数基础上,扩展若干使用     *
*              方便的图形函数                             *  
**********************************************************/

/**************************
*     系 统 宏 定 义      *
**************************/
# define GRAPH          FG_InitGraphic();
# define CLS        FG_ClearScreen(DG_CLS_ERASE);


/**************************
*    全 局 变 量 定 义    *
**************************/
short  Now_Str_X = 1;
short  Now_Str_Y = 1;

/**************************
*     函  数  声  明      *
**************************/
void BOX(short LT_X,short LT_Y,short RB_X,short RB_Y,short IfEraser,short FillColor);
void LOCATE(short Str_x,short Str_y);
void Print(char *Strings);


/***********************************************************
*  函数说明:画矩形框工具                                  *
*      输入:矩框坐标  DrawModel FillColor                 *
*      [DrawModel]           [说明]                        *
*         0                   擦除                         *
*         1                   画线                         *
*         2                   填充                         *
*      [FillColor]           [说明]                        *
*         0                   白                           *
*         1                   黑                           *
*         2                   反色(XOR)                  *
***********************************************************/
void BOX(short LT_X,short LT_Y,short RB_X,short RB_Y,short DrawModel,short FillColor)
{
    if (LT_X < 0)        LT_X = 0;
    if (LT_Y < 0)        LT_Y = 0;
    if (RB_X > 127)      RB_X = 127;
    if (RB_Y > 63)       RB_Y = 63;
    
    LT_X = 127 - LT_X;
    LT_Y = 64 - LT_Y;
    
    RB_X = 127 - RB_X;
    RB_Y = 64 - RB_Y;
        
    switch (DrawModel)
    {
        case 0:
            if(FillColor == 1)
            {
                FG_SetRectStyle(DG_RECT_ERASE);
            }
            else
            {
                FG_SetRectStyle(DG_RECT_COVER);
            }
            FG_Rectangle(RB_X,RB_Y,LT_X,LT_Y);
            break;
        case 1:
            if (FillColor == 1)
            {
                FG_SetRectStyle(DG_RECT_HOLLOW);
            }
            else if(FillColor == 0)
            {
                FG_SetRectStyle(DG_RECT_HOLLOW_ERASE);
            }
            else if(FillColor == 2)
            {
                FG_SetRectStyle(DG_RECT_SOLID_XOR);
            }
            FG_Rectangle(RB_X,RB_Y,LT_X,LT_Y);
            break;
        case 2:
            if (FillColor == 1)
            {
                FG_SetRectStyle(DG_RECT_COVER);
                FG_Rectangle(RB_X,RB_Y,LT_X,LT_Y);
            }
            else if (FillColor == 0)
            {
                FG_ClearRect(RB_X,RB_Y,LT_X,LT_Y,DG_CLS_ERASE);
            }
            else if (FillColor == 2)
            {
                FG_SetRectStyle(DG_RECT_SOLID_XOR);
                FG_Rectangle(RB_X,RB_Y,LT_X,LT_Y);
            }
            
            break;
    }

}

/***********************************************************
*  函数说明:字符串定位函数                                *
*      输入:字符串文本坐标(1:4  1:16)                   *
***********************************************************/
void LOCATE(short Str_y,short Str_x)
{
    if (Str_x >= 1 && Str_x <=17)
    {
        Now_Str_X = Str_x;
    }
    if (Str_y >= 1 && Str_y <=4)
    {
        Now_Str_Y = Str_y;
    }
}

/***********************************************************
*  函数说明:字符串显示函数                                *
*      输入:要显示的字符串                                *
***********************************************************/
void PRINT(char *Strings)
{
    short Temp_X =(Now_Str_X-1)<<3;
    short Temp_Y =(Now_Str_Y-1)<<4;
    if (Temp_X < 0)        Temp_X = 0;
    if (Temp_Y < 1)        Temp_Y = 1;
    
    Temp_X = 127 - Temp_X;
    
    Temp_Y = 63 - Temp_Y;
    
    FG_PutStr(Strings,3,Temp_X,Temp_Y);
}

#endif

文章评论0条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /2 下一条