打印

xwj优化的通用菜单程序

[复制链接]
9059|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xwj|  楼主 | 2007-10-25 01:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
se, TE, ui, ST, dc
//呵呵,都在讨论菜单啊?那我也来优化一个!                                  //
//大家多提意见哦:-)                                                         //
//                                                                          //
//--------------------------------------------------------------------------//
//                                                                          //
//                    (c) Copyright 2007-2008 xuwenjun                     //
//                            All Rights Reserved                           //
//                                    V1.00                                 //
//--------------------------------------------------------------------------//
//标 题: xwj优化的通用菜单程序                                             //
//文件名: xwj_menu.c                                                        //
//版 本: V1.00                                                             //
//修改人: xwj                            E-mail:xuwenjun@21cn.com           //
//日 期: 07-10-25                                                          //
//描 述: xwj优化的通用菜单程序                                             //
//声 明:                                                                   //
//        以下代码仅免费提供给学习用途,但引用或修改后必须在文件中声明出处. //
//        如用于商业用途请与作者联系.    E-mail:xuwenjun@21cn.com           //
//        有问题请mailto xuwenjun@21cn.com   欢迎与我交流!                  //
//--------------------------------------------------------------------------//
//老版本: 无                             老版本文件名:                      //
//创建人: xwj                            E-mail:xuwenjun@21cn.com           //
//日 期: 03-11-06                                                          //
//--------------------------------------------------------------------------//
//描 述:                                                                   //
// xwj优化的通用菜单程序                                                    //
// MCU 型号: 任意                                                           //
// 开发环境: ANSI C任意平台                                                 //
// 开发日期: 2007.10.25                                                     //
// 程序编写: XWJ                                                            //
//--------------------------------------------------------------------------//
// 程序特点:                                                                //
//1、程序和数据的分离,菜单可任意定义,甚至放在RAM里                        //
//2、定义好链表和菜单条目后,即可自动显示菜单、自动循环、跳转、执行,       //
//   自动控制程序流向,不需任何额外的判断和switch                           //
//3、保留菜单路径,可原路返回(当然,也可直接跳回去啦:-)  )                //
//4、可任意定义菜单层数,每层菜单可以任意组织,多一层菜单仅需增加1字节RAM   //
//5、节省内存,仅需2字节+菜单层数个RAM                                     //
//--------------------------------------------------------------------------//


#include <stdio.h>
#include “my_displays.h”                    //my_displays.c中包含char putchar (char)的实体
                                            //和 液晶显示模块(点、线、填充...)
                                            //以及printat(x,y,char*),有此足以实现任何界面显示


#define MENU_MAX_LAYER          16          //菜单链最大层数,示例只用到4层
#define MENU_NUM_OF_PAGE        4           //每页可以显示菜单数目

unsigned char Menu_tree[MENU_MAX_LAYER];    //菜单按键树,类似堆栈
unsigned char Menu_tree_ptr;                //当前菜单按键树所在层数
unsigned char Menu_item_ptr;                //当前菜单项在本层中位置

typedef struct
{
    unsigned char code *Menu_NextTab;       //本级菜单菜单链表
    char code *Menu_Name;                   //当前菜单名称
    void    (*CurrentOperate)();            //当前状态应该执行的功能操作
}Menustruct;

void    (*KeyFuncPtr)();                    //按键功能指针

void    refur_Menu(void);                   //刷新菜单层,就是依次打印总标题、各个条目,
void    refur_Menu_item(void);              //刷新本层菜单项,就是恢复原来项颜色,反显当前项
                                            //则两个函数和界面布局有关,自己写吧
                                            
extern void ScanKey(void);                  //键盘扫描

void    Menu_Key_Func(unsigned char NowKey); //菜单按键功能
{
    switch(NowKey)
    {
        case    KEY_UP:
                if(*(KeyTab[Menu_tree][Menu_tree_ptr]].Menu_NextTab))         //Menu_NextTab[0]不为0,是菜单
//              也可以判断函数指针是否是NULL,写成下面这样:
//              if(KeyTab[Menu_tree][Menu_tree_ptr]].CurrentOperate == NULL)) //Menu_NextTab[0]不为0,是菜单
                {
                    Menu_item_ptr--;        //菜单项上移
                    if(Menu_tree_ptr== -1)  //菜单项上移到顶翻转了,修正到最后一项
                        Menu_item_ptr=sizeof(*(KeyTab[Menu_tree][Menu_tree_ptr]].Menu_NextTab))-1;  //菜单循环
                       refur_Menu_item();                   //刷新本层菜单项
                }
                else
                    Error_Beep();           //否则不是菜单,上下移无效,蜂鸣警告
            break;
        case    KEY_doWN:
                if(*(KeyTab[Menu_tree][Menu_tree_ptr].Menu_NextTab))     //Menu_NextTab[0]不为0,是菜单
                {
                    Menu_item_ptr++;        //菜单项下移
                    if(Menu_item_ptr==sizeof(*(KeyTab[Menu_tree][Menu_tree_ptr]].Menu_NextTab))-1) //菜单项下移到底
                        Menu_item_ptr=0;    //菜单项下移到底,循环上去
                       refur_Menu_item();                   //刷新本层菜单项
                }
                else
                    Error_Beep();           //否则不是菜单,上下移无效,蜂鸣警告
                break;
        case    KEY_OK://KEY_OK,    KEY_UP,    KEY_ESC,
                if(*(KeyTab[Menu_tree][Menu_tree_ptr]].Menu_NextTab))    //Menu_NextTab[0]不为0,是菜单
                {
                    Menu_tree[Menu_tree_ptr+1]=KeyTab[Menu_tree][Menu_tree_ptr]].Menu_NextTab[Menu_item_ptr]);
                                            //下一级菜单压进菜单树,能看懂吗?
                    Menu_tree_ptr++;        //菜单又多了一级
                       refur_Menu();          //刷新菜单层,当前菜单当然是在Menu_tree[Menu_tree_ptr]中啦
                }
                else                        //不是菜单,执行当前菜单项的操作
                {
                    KeyFuncPtr=KeyTab[Menu_tree][Menu_tree_ptr]].CurrentOperate;
                    (*KeyFuncPtr)();        //执行当前菜单项的操作
                }
                break;
        case    KEY_ESC:
                //
                if(Menu_tree_ptr)               //当前菜单位置不是顶层(主界面)
                {
                    Menu_tree_ptr--;            //则返回上一层
                       refur_Menu();          //刷新菜单层,当前菜单当然是在Menu_tree[Menu_tree_ptr]中啦
                }
                else
                    Error_Beep();               //否则蜂鸣警告
                break;
                //
       //case   Other:
       //....
       }         //
}



//************************************************************************
//Menu struct:                              //菜单示例,共4层19项
//************************************************************************
// First Bmp--------------------->(MenuID_0)
// ---+                 
//    |View--------------------->(MenuID_1)
//    +---+             
//    |   |About Recorde-------->(MenuID_2)
//    |   +--------------
//    |   |HandSet Clock-------->(MenuID_3)
//    |   +--------------
//    |Operation---------------->(MenuID_4)
//    +---+             
//        |Set Position--------->(MenuID_5)
//        +---+             
//        |   |Rd Zj To Flash------->(MenuID_6)
//        |   +--------------
//        |   |Rd Zl To Ram--------->(MenuID_7)
//        |   +--------------
//        |   |Del Given Zl--------->(MenuID_8)
//        |   +--------------
//        |   |Del All Zl----------->(MenuID_9)
//        |   +--------------
//        |Test--------------------->(MenuID_10)
//        +---+             
//        |   |Ram Test------------->(MenuID_11)
//        |   +--------------
//        |   |Flash Test----------->(MenuID_12)
//        |   +--------------
//        |System Set--------------->(MenuID_13)
//        +---+            
//        |Debug---------------->(MenuID_14)
//        +---+        
//        |   |PassWord--------->(MenuID_15)
//        |   +--------------
//        |   |See Picture------>(MenuID_16)
//        |   +--------------
//        |Set Hand Clk--------->(MenuID_17)
//        +--------------
//************************************************************************

//菜单链表,每项菜单一条,共19项
unsigned char code Tab_First_Bmp[]=
{1,4,0x00
};
unsigned char code Tab_View[]=
{2,3,0x00
};
unsigned char code Tab_About_Recorde[]=
{0x00
};
unsigned char code Tab_HandSet[]=
{0x00
};
unsigned char code Tab_Operation[]=
{5,10,13,14,17,0x00
};
unsigned char code Tab_Set_Position[]=
{6,7,8,9,0x00
};
unsigned char code Tab_Rd_Zj_To_Flash[]=
{0x00
};
//...
                                //每项菜单一条,共19项


//菜单结构,每项菜单一条,,共19项
Menustruct  MenuTab[]=
{
//Menu_NextTab,     Menu_Name,    CurrentOperate
//本级菜单菜单链表, 当前菜单名称, 当前状态应该执行的功能操作
{Tab_First_Bmp,"First_Bmp",*First_Bmp},    //实际上菜单功能可以为NULL,由refur_Menu()统一操作;
    {Tab_View,"View",*View},               //不是菜单则用实际功能函数
    {Tab_About_Recorde,"About Recorde",*About_Recorde},   //非菜单
    {Tab_HandSet Clock,"HandSet Clock",*HandSet_Clock},   //非菜单
    {Tab_Operation,"Operation",*NULL},                     //菜单
    {Tab_Set_Position,"Set Position",*NULL},               //菜单
    {Tab_Rd_Zj_To_Flash,"Rd Zj To Flash",*Rd_Zj_To_Flash}, //非菜单
//...
                                //每项菜单一条,共19项
};

//使用方法:       
//1、定义好链表和菜单条目,写好每个功能函数
//2、主循环中不停的读按键,然后Menu_Key_Func();即可自动显示菜单、自动循环、跳转、执行
//比如:

void main(void)
{
    Menu_tree_ptr=0;                //当前菜单按键树所在层数
    Menu_item_ptr=0;                //当前菜单项在本层中位置
    refur_Menu();                   //刷新顶层菜单
    refur_Menu_item();              //刷新本层菜单项
    
    
    while(1)
    {
        ScanKey();              //键盘扫描
        if(KeyOk)
            Menu_Key_Func();    //有按键则执行按键功能
    }
}


//本程序由xwj设计的UltraEdit脚本加亮显示,如需要脚本请访问我的Blog或联系xwjfile@21cn.com

相关帖子

沙发
yewuyi| | 2007-10-25 09:08 | 只看该作者

沙发……

使用特权

评论回复
板凳
fsaok| | 2007-10-25 09:20 | 只看该作者

.

很好,在慢慢消化中

使用特权

评论回复
地板
jskuangren| | 2007-10-25 09:23 | 只看该作者

搬张板凳,慢慢看.搞个菜单的专题也不错!!!

使用特权

评论回复
5
mamalihui| | 2007-10-25 09:32 | 只看该作者

慢慢看

使用特权

评论回复
6
古道热肠| | 2007-10-25 11:05 | 只看该作者

先收下了,我会抽空试试看的

  谢谢发表!

使用特权

评论回复
7
skey79| | 2007-10-25 12:59 | 只看该作者

不错,顶一下

XWJ太厉害了,不的不顶。

使用特权

评论回复
8
aihe| | 2007-10-25 13:48 | 只看该作者

就算站着也要看的

使用特权

评论回复
9
BitFu| | 2007-10-25 13:50 | 只看该作者

我也贴一个菜单程序

http://www.chipart.cn/cam8x/ui.asp

使用特权

评论回复
10
燕南啸| | 2007-10-25 16:29 | 只看该作者

呵呵,好东东,先拿下来学习学习

使用特权

评论回复
11
sodwell| | 2007-10-25 22:50 | 只看该作者

re

写得不错,既然菜单是面向对象的东西,大家记着写程序的时候用到面向对象的思想就行了,也就是把菜单的属性和操作封装在一起(也就是结构体了),这对于以后的维护和可扩展行相当有好处。

使用特权

评论回复
12
dcp| | 2007-10-25 22:53 | 只看该作者

不错

使用特权

评论回复
13
hotpower| | 2007-10-25 23:19 | 只看该作者

不错~~~反正结构要好就是了~~~

使用特权

评论回复
14
figoxwm| | 2007-11-1 15:24 | 只看该作者

好贴顶起来

好贴子顶起来,虽然看得不是很懂

使用特权

评论回复
15
keer_zu| | 2007-11-1 15:57 | 只看该作者

支持!

使用特权

评论回复
16
gavin_he| | 2007-11-1 16:27 | 只看该作者

要顶

使用特权

评论回复
17
yczhang| | 2007-11-1 17:25 | 只看该作者

有时间再看

使用特权

评论回复
18
左手换右手| | 2007-11-1 19:22 | 只看该作者

这些通用菜单都比较容易对付

 关键的是一些特殊情况,比如:
1、参数输入
2、单选菜单
3、菜单选择对应具体功能的错误提示及错误处理
...

使用特权

评论回复
19
coldra| | 2007-11-1 19:45 | 只看该作者

板主呢?建议给条裤子

使用特权

评论回复
20
wswh2o| | 2007-11-2 13:29 | 只看该作者

19楼说得不错

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

xwj

288

主题

22797

帖子

35

粉丝