yanggang2880 发表于 2012-4-26 21:43:31

多种样式的菜单在LCD屏上的实现

本帖最后由 yanggang2880 于 2012-4-27 20:08 编辑

在论坛上获取资源很久了,今天也上传一个我的菜单程序。
此菜单的特点是可以像做网页定义CSS样式一样,定义菜单的显示样式。
包括:菜单项排版,选中不选中文字的颜色,选中不选择按钮图片,图片和文字的排版方式等等。结合美工可以在液晶屏上做出漂亮且功能强大的菜单。
部分代码来自“傻孩子”的菜单实现,在此感谢一下。
以下代码在我的板子上调试通过。

typedef struct IMAGE_RESOURCE      
{
      uint_16 resource_id;
      uint_16 pic_id;
      uint_16 xe;
      uint_16 ye;
      uint_16 xs;
      uint_16 ys;
}ImageResource;


//剪切图片资源
const ImageResource ImageResourceList[] =
{
      {1, BUTTONPICTURE, 0x67, 0x24, 0xDE, 0x3C},                //按钮图标1,未选择
      {2, BUTTONPICTURE, 0x67, 0x43, 0xDE, 0x58},                //按钮图标1,选择
      {3, BUTTONPICTURE, 0x67, 0x64, 0xDB, 0x73},                //按钮图标2,未选择
      {4, BUTTONPICTURE, 0x67, 0x7E, 0xDB, 0x8D},                //按钮图标2,选择
      {0, 0, 0, 0, 0, 0}               
};

typedef struct MENUSTYLE
{
      uint_8 style;
      uint_8 col;                              //菜单最大列数
      uint_8 row;                        //菜单最大行数
      uint_8 dx;                              //水平间距
      uint_8 dy;                              //垂直间距
      uint_8 space_x;                        //文字跟图片起始地址的差值
      uint_8 space_y;
      ImageResource* imgid_sel;                //被选中时菜单按钮图标句柄,NULL没图片不显示,(需LCD GUI支持图片上文字背景色不显示)
      ImageResource* imgid_normal;                //不被选中时菜单按钮图标句柄,NULL没图片不显示
      uint_32 f_color_sel;                        //前景色被选择时
      uint_32 f_color_normal;                //前景色不被选中时
      uint_32 b_color_sel;                        //背景色被选择时
      uint_32 b_color_normal;                //背景色不被选中时
      uint_16 x0;                              //菜单绘制的起始位置
      uint_16 y0;
      //......
      //还可以定义一些字体类型,文字大小等等
}MenuStyle;

typedef struct MENUITEM      
{
      char *DisplayString;
      void (*Subs)();
      struct MENUITEM *ChildrenMenus;
      struct MENUITEM *ParentMenus;

}MenuItem;


typedef struct MENU      
{
      char* MenuName;
      uint_8 MenuItemCount;      
      uint_8 select;                        //当前被选中的
      MenuStyle* menu_style;                //菜单风格选择
      MenuItem* pMenuItem;
}Menu;


const MenuStyle MenuStyleList[] =
{
      {1, 1, 5, 0, 0x1F, 8, 5, (ImageResource*)(&ImageResourceList), (ImageResource*)(&ImageResourceList), COLOR_BLACK, COLOR_BLACK, COLOR_WHITE, COLOR_WHITE, 0x64, 0x24},      
      {2, 2, 6, 0x8F, 0x14, 7, 1, (ImageResource*)(&ImageResourceList), (ImageResource*)(&ImageResourceList), COLOR_BLACK, COLOR_BLACK, COLOR_WHITE, COLOR_WHITE, 0x1E, 0x20},
      {0, 0, 0, 0, 0, 0, 0, NULL, NULL, 0, 0, 0, 0}      
};

MenuItem MainMenuItem;
MenuItem SettingsMenuItem;


Menu MainMenu;
Menu SettingsMenu;


Menu* g_pCurMenu;

void NullSubs(void)
{
      ;
}

static Menu* GetCurMenu(MenuItem* pMenuItem)
{
      Menu* pMenu = NULL;
      
      if (pMenuItem == MainMenuItem)
      {
                pMenu = &MainMenu;
      }
      else if (pMenuItem == SettingsMenuItem)
      {
                pMenu = &SettingsMenu;
      }
      
      return pMenu;
}

static void ImagePaint(uint_16 x, uint_16 y, ImageResource* image)
{
      ;//根据具体的LCD屏调用GUI函数
}

static void TextPaint(uint_16 x, uint_16 y, uint_32 fcolor, uint_32 bcolor, const char* s)
{
      ;//根据具体的LCD屏调用GUI函数
}

static void MenuItemPaint(uint_16 x, uint_16 y, uint_8 space_x, uint_8 space_y, ImageResource* image, uint_32 fcolor, uint_32 bcolor, const char* s)
{
      if (NULL != image)
      {
                ImagePaint(x, y, image);
      }
      TextPaint(x+space_x, y+space_y, fcolor, bcolor, s);
}

static void MenuFramePaint(const char* title)
{
      ;//根据具体的LCD屏调用GUI函数,包括清屏,绘制菜单标题等
}

//菜单绘制
void MenuPaint(uint_8 mode, uint_8 select, Menu* pMenu)
{
      uint_8 i;
      uint_16 x;      
      uint_16 y;
      uint_8 col = 0;
      uint_8 row = 0;
      ImageResource* image;
      uint_32 fcolor;
      uint_32 bcolor;
      uint_8 space_x;
      uint_8 space_y;
      MenuStyle* pMenuStyle;
      
      if (NULL == pMenu)
      {
                return;
      }
      
      pMenuStyle = pMenu->menu_style;
      if (NULL == pMenuStyle)
      {
                return;
      }
      
      x = pMenuStyle->x0;
      y = pMenuStyle->y0;
      
      space_x = pMenuStyle->space_x;
      space_y = pMenuStyle->space_y;
      
      if (mode == 0)      //只绘制变化部分
      {
                x = pMenuStyle->x0;
                y = pMenuStyle->y0;
                if (pMenu->select != select)
                {
                        //撤销原选中项
                        image = pMenuStyle->imgid_normal;;
                        fcolor = pMenuStyle->f_color_normal;
                        bcolor = pMenuStyle->b_color_normal;
                        x = x + (pMenu->select/pMenuStyle->row)*pMenuStyle->dx;
                        y = y + (pMenu->select%pMenuStyle->row)*pMenuStyle->dy;
                        MenuItemPaint(x, y, space_x, space_y, image, fcolor, bcolor, pMenu->pMenuItem.DisplayString);
                        
                        //更新新的选中项
                        x = pMenuStyle->x0;
                        y = pMenuStyle->y0;
                        image = pMenuStyle->imgid_sel;;
                        fcolor = pMenuStyle->f_color_sel;
                        bcolor = pMenuStyle->b_color_sel;
                        x = x + (select/pMenuStyle->row)*pMenuStyle->dx;
                        y = y + (select%pMenuStyle->row)*pMenuStyle->dy;
                        MenuItemPaint(x, y, space_x, space_y, image, fcolor, bcolor, pMenu->pMenuItem.DisplayString);
               
                        pMenu->select = select;
                }
      }
      else      //全部绘制
      {
                MenuFramePaint(pMenu->MenuName);
                for (i=0; i<pMenu->MenuItemCount; i++)
                {
                        if (i == pMenu->select)
                        {
                              image = pMenuStyle->imgid_sel;
                              fcolor = pMenuStyle->f_color_sel;
                              bcolor = pMenuStyle->b_color_sel;
                        }
                        else
                        {
                              image = pMenuStyle->imgid_normal;;
                              fcolor = pMenuStyle->f_color_normal;
                              bcolor = pMenuStyle->b_color_normal;
                        }
                        MenuItemPaint(x, y, space_x, space_y, image, fcolor, bcolor, pMenu->pMenuItem.DisplayString);
                        y += pMenuStyle->dy;
                        row++;
                        if (row == pMenuStyle->row)
                        {
                              row = 0;
                              col++;
                              x += pMenuStyle->dx;
                              y = pMenuStyle->y0;
                        }
                }
      }
}

//获取当前被选中的项值
uint_8 GetMenuSel(Menu* pMenu)
{
      return pMenu->select;
}

//获取目录项个数
uint_8 GetMenuItemCount(Menu* pMenu)
{
      return pMenu->MenuItemCount;
}

//设置目录初始化函数                        
void SettingsMenuInit(void)
{
      SettingsMenu.select = 0;
      SettingsMenu.menu_style = (MenuStyle*)(&MenuStyleList);
      SettingsMenu.MenuItemCount = 12;
      SettingsMenu.pMenuItem = SettingsMenuItem;
      SettingsMenu.MenuName = "Settings";

            SettingsMenuItem.DisplayString = "Test1";
            SettingsMenuItem.Subs = NullSubs;
            SettingsMenuItem.ChildrenMenus = NULL;
            SettingsMenuItem.ParentMenus = MainMenuItem;

            SettingsMenuItem.DisplayString = "Test2";
            SettingsMenuItem.Subs = NullSubs;
            SettingsMenuItem.ChildrenMenus = NULL;
            SettingsMenuItem.ParentMenus = MainMenuItem;

         SettingsMenuItem.DisplayString = "Test3";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = NULL;
    SettingsMenuItem.ParentMenus = MainMenuItem;

    SettingsMenuItem.DisplayString = "Test4";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = NULL;
    SettingsMenuItem.ParentMenus = MainMenuItem;

    SettingsMenuItem.DisplayString = "Test5";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = NULL;
    SettingsMenuItem.ParentMenus = MainMenuItem;
   
    SettingsMenuItem.DisplayString = "Test6";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = NULL;
    SettingsMenuItem.ParentMenus = MainMenuItem;
   
    SettingsMenuItem.DisplayString = "Test7";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = NULL;
    SettingsMenuItem.ParentMenus = MainMenuItem;
   
    SettingsMenuItem.DisplayString = "Test8";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = NULL;
    SettingsMenuItem.ParentMenus = MainMenuItem;
   
    SettingsMenuItem.DisplayString = "Test9";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = NULL;
    SettingsMenuItem.ParentMenus = MainMenuItem;
   
    SettingsMenuItem.DisplayString = "Test10";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = NULL;
    SettingsMenuItem.ParentMenus = MainMenuItem;
   
    SettingsMenuItem.DisplayString = "Test11";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = NULL;
    SettingsMenuItem.ParentMenus = MainMenuItem;
   
    SettingsMenuItem.DisplayString = "Back";
    SettingsMenuItem.Subs = NullSubs;
    SettingsMenuItem.ChildrenMenus = MainMenuItem;
    SettingsMenuItem.ParentMenus = MainMenuItem;
}


//根目录初始化                                    
void MainMenuInit(void)
{
      MainMenu.select = 0;
      MainMenu.menu_style = (MenuStyle*)(&MenuStyleList);
      MainMenu.MenuItemCount = 5;
      MainMenu.pMenuItem = MainMenuItem;
      MainMenu.MenuName = "Main Menu";

      MainMenuItem.DisplayString = "Test1;
      MainMenuItem.Subs = NullSubs;
      MainMenuItem.ChildrenMenus = NULL;
      MainMenuItem.ParentMenus = NULL;

      MainMenuItem.DisplayString = "Test2";
      MainMenuItem.Subs = NullSubs;
      MainMenuItem.ChildrenMenus = NULL;
      MainMenuItem.ParentMenus = NULL;

      MainMenuItem.DisplayString = "Test3";
      MainMenuItem.Subs = NullSubs;
      MainMenuItem.ChildrenMenus = NULL;   
      MainMenuItem.ParentMenus = NULL;

      MainMenuItem.DisplayString = "Settings";
      MainMenuItem.Subs = NullSubs;
      MainMenuItem.ChildrenMenus = SettingsMenuItem;   
      MainMenuItem.ParentMenus = NULL;


      MainMenuItem.DisplayString = "Test4";
      MainMenuItem.Subs = NullSubs;
      MainMenuItem.ChildrenMenus = NULL;   
      MainMenuItem.ParentMenus = NULL;
      
      g_pCurMenu = &MainMenu;
}

void MenuInit(vodi)
{
      MainMenuInit();
      SettingsMenuInit();
}

void EventKeyEnter(void)
{
      g_pCurMenu->pMenuItem.Subs();
      if (NULL != g_pCurMenu->pMenuItem.ChildrenMenus)
      {
                g_pCurMenu = GetCurMenu(g_pCurMenu->pMenuItem.ChildrenMenus);
                g_pCurMenu->select = 0;
                //更换目录,整个重绘
                MenuPaint(1, 0, g_pCurMenu);
      }
}


void EventKeyUp(void)
{
      uint_8 sel;
      
      sel = GetMenuSel(g_pCurMenu);
      if (sel > 0)
      {
                sel--;
                MenuPaint(0, sel, g_pCurMenu);
      }
}
void EventKeyDown(void)
{
      uint_8 sel;
      
      sel = GetMenuSel(g_pCurMenu);
      if (sel < GetMenuItemCount(g_pCurMenu)-1)
      {
                sel++;
                MenuPaint(0, sel, g_pCurMenu);
      }
      
}

void Test(void)
{
      MenuInit();
      while (1)
      {
                //调用按键扫描
      }
}

有图有真相,贴上我已经实现的几种样式。
1.单排纯文本样式。
{4, 1, 8, 0, 0x11, 0x14, 0, NULL, NULL, 0x001F, COLOR_WHITE, COLOR_WHITE, 0x001F, 0x70, 0x1A},


2.多排纯文本样式。
{5, 4, 8, 0x40, 0x11, 0x14, 0, NULL, NULL, 0x001F, COLOR_WHITE, COLOR_WHITE, 0x001F, 0x10, 0x30},


3.图文并茂模式,文字在图片上,单排
{1, 1, 5, 0, 0x1F, 8, 5, (ImageResource*)(&ImageResourceList), (ImageResource*)(&ImageResourceList), COLOR_BLACK, COLOR_BLACK, COLOR_WHITE, COLOR_WHITE, 0x64, 0x24},


4.图文并茂模式,文字在图片上,多排
{2, 2, 6, 0x8F, 0x14, 7, 1, (ImageResource*)(&ImageResourceList), (ImageResource*)(&ImageResourceList), COLOR_BLACK, COLOR_BLACK, COLOR_WHITE, COLOR_WHITE, 0x1E, 0x20},


5.图文并茂模式,文字图片分离显示
{3, 1, 10, 0, 0x11, 0x14, 0, (ImageResource*)(&ImageResourceList), (ImageResource*)(&ImageResourceList), 0xFFE0, COLOR_WHITE, COLOR_BLACK, COLOR_BLACK, 0x10, 0x1A},


要做的好看,还是需要美工的配合啊。或者网上找一些按钮图片素材。

ljt80158015 发表于 2012-4-26 22:00:23

无图无真相!~

yanggang2880 发表于 2012-4-26 22:08:36

ljt80158015 发表于 2012-4-26 22:00 static/image/common/back.gif
无图无真相!~

明天有空再抓个图来。

ljt80158015 发表于 2012-4-26 22:11:25

本帖最后由 ljt80158015 于 2012-4-26 22:20 编辑

如果能实现树形菜单,那就太好了。

gxy508 发表于 2012-4-26 22:11:59

有空研究研究

yypdou 发表于 2012-4-27 10:31:49

有空看看!~!~~

shotstar 发表于 2012-4-27 11:23:42

果然比较复杂~~

Excellence 发表于 2012-4-27 11:27:49

不错。。。。。。。。。

yanggang2880 发表于 2012-4-27 20:21:48

ljt80158015 发表于 2012-4-26 22:11 static/image/common/back.gif
如果能实现树形菜单,那就太好了。

可以实现的。不过我显示方式是一屏只显示一个菜单。显示下个菜单的时候就切画面。

ljt80158015 发表于 2012-4-28 10:13:48

相当不错!~

dwfc 发表于 2012-5-23 00:54:28

好教程值得看看!!

pcwhy 发表于 2012-5-23 02:01:36

代码封装得不错。遇到那些文本框和菜单混排的界面就有点麻烦了。

njchenmin 发表于 2012-5-23 05:44:38

这个不错的,感觉做菜单时间非常要耐心的事。

dory_m 发表于 2012-5-23 16:03:19

不错,学习!!!{:biggrin:}{:biggrin:}{:biggrin:}

sync765 发表于 2012-5-23 16:11:13

很值得学习啊

fyyy4030 发表于 2012-6-14 10:46:26

楼主为什么不把完整源码公开一下?有图没有真相~!!!!

mofire 发表于 2012-6-16 10:24:09

关注中!求真相

Jimmyxu 发表于 2013-5-2 09:16:01

頂一下,有空再看看~~~~

阿毛 发表于 2013-5-2 09:30:58

相当不错的东西

lanyuye 发表于 2013-5-2 10:01:22

学习学习

zyw19987 发表于 2013-5-3 08:01:09

动态输入的内容如何显示呢?

zyw19987 发表于 2013-5-3 08:34:48

菜单应该有动态输入内容显示,自动返回上一层(长时间未操作)吧!和你的很类似。有机会交流一下

hamipeter 发表于 2013-5-3 09:25:00

不错不错

wadz365 发表于 2013-5-3 12:35:24

学习。。。。。。。。。。。。。

huanger 发表于 2013-5-5 00:51:00

非常不的资料!!

pig4451 发表于 2013-5-5 17:42:49

不錯{:smile:}

dmxfeng 发表于 2013-5-5 22:00:38

很強大,頂樓主

tanchengfang 发表于 2013-5-12 09:19:05

学习了,谢谢分享

wns245249509 发表于 2013-5-12 22:42:19

谢谢楼主的辛勤劳作

keton_cxc 发表于 2013-5-12 23:09:10

LCD 菜单 好东西 学习了

li沉默是金 发表于 2014-9-10 15:45:52

mark,学习,。

mxzwish 发表于 2014-9-11 17:54:46

代码质量非常高!!赞一个!

blueagle888 发表于 2014-10-11 16:12:54

这个真心好。实现了图文混排,代码简洁。

blade_li 发表于 2014-10-11 23:39:19

无图无真相,如果代码能配合图就更好了
页: [1]
查看完整版本: 多种样式的菜单在LCD屏上的实现