在上篇文章中已经讲了源码实现,这篇文章将教会你怎么使用和移植到自己的项目中去,以此系列第一篇文章的效果视频为例,通过实例的方式展现其用法,快速上手。
还是先贴上代码:
`#ifndef __M_GUI_TEST_H
define __M_GUI_TEST_H
define BUILD_TITLE(X,Y) \
{ \ if(!((*(X)).pszTitle)) \ { \ for(uint32_t i = 0;i < COUNTOF(X);i++) \ { \ (X)[i].pszTitle = (tTitle)&(Y)[i]; \ } \ } \ }
endif/__M_GUI_TEST_H/
`
`#include "./m_gui/m_gui.h"
include "./m_gui/m_gui_test.h"
include "./key_board/key_board.h"
include "./oled.h"
static M_U32 key_up(void); static M_U32 key_down(void); static M_U32 key_left(void); static M_U32 key_right(void); static M_U32 key_enter(void); static M_U32 key_exit(void);
MENU_GUI gui;
opsTypeDef ops = { .pset = (void ()(M_U16, M_U16, M_U8))OLED_DrawPoint, .pclear = (void ()(void))OLED_clcScreen, .pputString = (void ()(M_U16, M_U16, M_U8, void ))OLED_INT_CharDisp, };
keyTypeDef key = { .up = key_up, .down = key_down, .left = key_left, .right = key_right, .enter = key_enter, .exit = key_exit, };
//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\// static void page_item1_S_f(void);
static const struct sTitle page_item1_o_t[] = { {"speed-10",40,16}, {"speed-20",40,96}, {"speed-30",40,176}, }; static const struct sItem page_item1_o[] = { {(tTitle)&page_item1_o_t[0],NULL}, {(tTitle)&page_item1_o_t[1],NULL}, {(tTitle)&page_item1_o_t[2],NULL}, }; static const struct sTitle page_item1_t[] = {"速度选择",0,0}; static struct sMenu page_item1[] = {(tTitle)page_item1_t,(tItem)page_item1_o,COUNTOF(page_item1_o),0,1,3,(thmi)hmi_def,page_item1_S_f};
static void page_item1_S_f(void) { gui_put_string(10, OLED_Y_COR_CENTER(strlen(gui.active->pszTitle->str)), 0, gui.active->pszTitle->str); } //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\// static void page_item2_S_f(void);
static const struct sTitle page_item2_o_t[] = { {"选项1",29,40}, }; static struct sItem page_item2_o[] = { {NULL,page_item1}, }; static const struct sTitle page_item2_t[] = {"菜单3",0,0}; static struct sMenu page_item2[] = {(tTitle)page_item2_t,(tItem)page_item2_o,COUNTOF(page_item2_o),0,1,3,(thmi)hmi_def,page_item2_S_f};
static void page_item2_S_f(void) { BUILD_TITLE(page_item2_o,page_item2_o_t)
gui_put_string(10, OLED_Y_COR_CENTER(strlen(gui.active->pszTitle->str)), 0, gui.active->pszTitle->str); } //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\// static void page_item3_S_f(void);
static struct sMenu page_item3[] = {(tTitle)NULL,(tItem)NULL,0,0,0,0,(thmi)hmi_def,page_item3_S_f};
static void page_item3_S_f(void) { char tmpStr[32] = {0};
sprintf(tmpStr,"%s","测试test");
gui_put_string(10, OLED_Y_COR_CENTER(strlen(tmpStr)), 0, tmpStr); } //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\// static void page_item4_S_f(void);
static const struct sTitle page_item4_o_t[] = { {"选项1",29,40}, {"选项2",29,152}, {"选项3",48,40}, }; static struct sItem page_item4_o[] = { {NULL,page_item1}, {NULL,page_item2}, {NULL,page_item3}, }; static const struct sTitle page_item4_t[] = {"菜单2",0,0}; static struct sMenu page_item4[] = {(tTitle)page_item4_t,(tItem)page_item4_o,COUNTOF(page_item4_o),0,1,3,(thmi)hmi_def,page_item4_S_f};
static void page_item4_S_f(void) { BUILD_TITLE(page_item4_o,page_item4_o_t)
gui_put_string(10, OLED_Y_COR_CENTER(strlen(gui.active->pszTitle->str)), 0, gui.active->pszTitle->str); } //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\// static void page_item5_S_f(void);
static const struct sTitle page_item5_o_t[] = { {"speed-10",40,16}, {"speed-20",40,96}, {"speed-30",40,176}, }; static const struct sItem page_item5_o[] = { {(tTitle)&page_item5_o_t[0],NULL}, {(tTitle)&page_item5_o_t[1],NULL}, {(tTitle)&page_item5_o_t[2],NULL}, }; static const struct sTitle page_item5_t[] = {"速度选择",0,0}; static struct sMenu page_item5[] = {(tTitle)page_item5_t,(tItem)page_item5_o,COUNTOF(page_item5_o),0,1,3,(thmi)hmi_def,page_item5_S_f};
static void page_item5_S_f(void) { gui_put_string(10, OLED_Y_COR_CENTER(strlen(gui.active->pszTitle->str)), 0, gui.active->pszTitle->str); } //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\// static void pageS_f(void);//主界面
static const struct sTitle page_o_t[] = { {"选项1",29,40}, {"选项2",29,152}, {"选项3",48,40}, {"选项4",48,152}, {"选项5",29,40}, }; static struct sItem page_o[] = { {NULL,page_item1}, {NULL,page_item2}, {NULL,page_item3}, {NULL,page_item4}, {NULL,page_item5}, }; static const struct sTitle page_t[] = {"菜单1",0,0}; static struct sMenu page[] = {(tTitle)page_t,(tItem)page_o,COUNTOF(page_o),0,2,2,(thmi)hmi_def,pageS_f};
static void pageS_f(void) { BUILD_TITLE(page_o,page_o_t)
gui_put_string(10, OLED_Y_COR_CENTER(strlen(gui.active->pszTitle->str)), 0, gui.active->pszTitle->str); } //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//
void gui_test(void) { gui_init(&gui,&ops,&key); gui_select(&gui); gui_set_active(page); gui_send_sig(gui.active); }
M_U32 key_up(void) { return (KeyGetState(KEY_UP) == KEY_RELEASE); }
M_U32 key_down(void) { return (KeyGetState(KEY_DOWN) == KEY_RELEASE); }
M_U32 key_left(void) { return (KeyGetState(KEY_LEFT) == KEY_RELEASE); }
M_U32 key_right(void) { return (KeyGetState(KEY_RIGHT) == KEY_RELEASE); }
M_U32 key_enter(void) { return (KeyGetState(KEY_ENTER) == KEY_RELEASE); }
M_U32 key_exit(void) { return (KeyGetState(KEY_EXIT) == KEY_RELEASE); }
/* 使用示例(一个任务或者定时器) void gui_task(void) { M_U32 tmpCnt = 0; gui_test();//初始化
for(;;) { //按键每10ms扫描一次 if(0 == (tmpCnt++ % 10)) { //你的键盘扫描 do something
//响应按键后的具体操作 gui_key_scan(); }
//有事件时更新 gui_flush();
//1ms调度 vTaskDelay(1); } }
//目前键盘仅实现了菜单项的选择,菜单的切换功能,如果想实现数值修改等其它功能,只需要新增相应的键盘操作即可,可参考hmi_def的实现 */ `
通过以上代码就实现了此系列第一篇文章的效果,可以看到,每一个菜单都是一个小部分,可以随意的增删改,而不会影响其它的菜单,更不用改了一个菜单后还需要重新构建菜单层级关系,使用和维护都是非常方便的。
总结:这个小项目虽然简单,但是在合适的场景其发挥的作用可以说是举足轻重的 ,从最开始的上千行代码,到现在的几百行代码就能完成的功能,对我来说也是一种进步,经过好几版的改进,重构,才有了现在的效果,我不能说这已经是最好的,但可以说是目前更好的,希望我的思路能给你带来启发。
点击下面的链接查看系列其它文章:
单色OLED屏可移植多级菜单式GUI(1)-简介
单色OLED屏可移植多级菜单式GUI(2)-源码

评论区
登录后即可参与讨论
立即登录