分享一个做菜单的方法,转自傻孩子,准备移植到Mini板上2.8寸LCD显示

2019-07-21 08:20发布

------------------------------------------

贴一段代码大家看看哈(我用来做目录的引擎)

(以上的是我在羚羊上实现的,但是原理是一样的,特别是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指向实现功能的   *

*         函数。                                    *

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





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 = "      lay      ";

    FlashMenu[1].Subs = FlashPlay;

    FlashMenu[1].ChildrenMenus = &Null;

    FlashMenu[1].ParentMenus = MainMenu;

    

    FlashMenu[2].MenuCount = 5;

    FlashMenu[2].DisplayString = "      ause     ";

    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 = "      lay      ";

    VoiceMenu[1].Subs = Play;

    VoiceMenu[1].ChildrenMenus = &Null;

    VoiceMenu[1].ParentMenus = MainMenu;

    

    VoiceMenu[2].MenuCount = 5;

    VoiceMenu[2].DisplayString = "      ause     ";

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

                 

            }

            /*******************目录操作*********************/

        }

        



}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
41条回答
合肥-文盲
1楼-- · 2019-07-21 09:38
补充一个关于作图的库函数



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 rint(char *Strings);





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

*  函数说明:画矩形框工具                                  *

*      输入:矩框坐标  DrawModel FillColor                 *

*      [DrawModel]           [说明]                        *

*         0                   擦除                         *

*         1                   画线                         *

*         2                   填充                         *

*      [FillColor]           [说明]                        *

*         0                   白                           *

*         1                   黑                           *

*         2                   反 {MOD}(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 RINT(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
合肥-文盲
2楼-- · 2019-07-21 09:52
说明一下:

定义了一个结构体来表示菜单的每一个选项

通过指针来跳转子目录或者调用功能函数



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



使用这样的结构,可以很方便的通过修改单独的菜单项来更形菜单,不用在主程序里面修改任何东西,扩展方便,节约资源(某种程度上来说是的,不用因为添加了一个新的子菜单,就重新扩展无用的代码)。程序里面有很详细的说明,大家可以看一下哈,
八度空间
3楼-- · 2019-07-21 12:04
回复【3楼】合肥-文盲:
---------------------------------
谢谢分享!

以文件附件的形式发不好么?
合肥-文盲
4楼-- · 2019-07-21 12:32
 精彩回答 2  元偷偷看……
ArchiChain
5楼-- · 2019-07-21 13:50
谢谢,最近也在写菜单。
合肥-文盲
6楼-- · 2019-07-21 16:58
回复【6楼】ArchiChain:
---------------------------------
写出来没,加QQ聊聊,2300950641

一周热门 更多>