304 lines
7.9 KiB
C
304 lines
7.9 KiB
C
/**
|
||
* @file menu_example.c
|
||
* @brief 菜单组件使用示例
|
||
* @note 工业级嵌入式菜单组件 - 使用示例
|
||
*/
|
||
#include "menu.h"
|
||
#include "menu_port.h"
|
||
#include <stdio.h>
|
||
|
||
// 条件编译:处理不同平台的键盘输入函数
|
||
#if defined(_WIN32)
|
||
#include <conio.h> // Windows平台
|
||
#else
|
||
// MinGW或其他平台的模拟实现
|
||
#include <termios.h>
|
||
#include <unistd.h>
|
||
#include <fcntl.h>
|
||
|
||
int _kbhit(void)
|
||
{
|
||
struct termios oldt, newt;
|
||
int ch;
|
||
int oldf;
|
||
|
||
tcgetattr(STDIN_FILENO, &oldt);
|
||
newt = oldt;
|
||
newt.c_lflag &= ~(ICANON | ECHO);
|
||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
|
||
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
|
||
|
||
ch = getchar();
|
||
|
||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||
fcntl(STDIN_FILENO, F_SETFL, oldf);
|
||
|
||
if(ch != EOF)
|
||
{
|
||
ungetc(ch, stdin);
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
int _getch(void)
|
||
{
|
||
struct termios oldt, newt;
|
||
int ch;
|
||
|
||
tcgetattr(STDIN_FILENO, &oldt);
|
||
newt = oldt;
|
||
newt.c_lflag &= ~(ICANON | ECHO);
|
||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||
|
||
ch = getchar();
|
||
|
||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||
|
||
return ch;
|
||
}
|
||
#endif
|
||
|
||
/************************** 菜单节点ID定义 **************************/
|
||
#define MENU_ID_MAIN 100 ///< 主菜单
|
||
#define MENU_ID_SETTINGS 200 ///< 设置菜单
|
||
#define MENU_ID_DISPLAY 201 ///< 显示设置
|
||
#define MENU_ID_LANGUAGE 202 ///< 语言设置
|
||
#define MENU_ID_PARAMETER 300 ///< 参数设置
|
||
#define MENU_ID_ABOUT 400 ///< 关于
|
||
|
||
/************************** 参数ID定义 **************************/
|
||
#define PARAM_ID_BRIGHTNESS 1000 ///< 亮度参数
|
||
#define PARAM_ID_CONTRAST 1001 ///< 对比度参数
|
||
|
||
/************************** 菜单回调函数 **************************/
|
||
/**
|
||
* @brief 主菜单进入回调
|
||
* @param node_id 菜单节点ID
|
||
* @return 错误码
|
||
*/
|
||
static MenuErrCode menu_cb_main(MenuNodeId node_id)
|
||
{
|
||
(void)node_id; // 未使用的参数
|
||
printf("Enter Main Menu\r\n");
|
||
return MENU_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置菜单进入回调
|
||
* @param node_id 菜单节点ID
|
||
* @return 错误码
|
||
*/
|
||
static MenuErrCode menu_cb_settings(MenuNodeId node_id)
|
||
{
|
||
(void)node_id; // 未使用的参数
|
||
printf("Enter Settings Menu\r\n");
|
||
return MENU_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief 显示设置进入回调
|
||
* @param node_id 菜单节点ID
|
||
* @return 错误码
|
||
*/
|
||
static MenuErrCode menu_cb_display(MenuNodeId node_id)
|
||
{
|
||
(void)node_id; // 未使用的参数
|
||
printf("Enter Display Settings\r\n");
|
||
return MENU_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief 语言设置进入回调
|
||
* @param node_id 菜单节点ID
|
||
* @return 错误码
|
||
*/
|
||
static MenuErrCode menu_cb_language(MenuNodeId node_id)
|
||
{
|
||
(void)node_id; // 未使用的参数
|
||
printf("Enter Language Settings\r\n");
|
||
return MENU_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief 参数设置进入回调
|
||
* @param node_id 菜单节点ID
|
||
* @return 错误码
|
||
*/
|
||
static MenuErrCode menu_cb_parameter(MenuNodeId node_id)
|
||
{
|
||
(void)node_id; // 未使用的参数
|
||
printf("Enter Parameter Settings\r\n");
|
||
return MENU_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief 关于菜单进入回调
|
||
* @param node_id 菜单节点ID
|
||
* @return 错误码
|
||
*/
|
||
static MenuErrCode menu_cb_about(MenuNodeId node_id)
|
||
{
|
||
(void)node_id; // 未使用的参数
|
||
printf("Enter About Menu\r\n");
|
||
printf("Industrial Menu Component v1.0\r\n");
|
||
printf("Highly Portable & Modular\r\n");
|
||
return MENU_OK;
|
||
}
|
||
|
||
/************************** 辅助函数 **************************/
|
||
/**
|
||
* @brief 按键扫描函数(Windows平台示例)
|
||
* @return 按键事件类型
|
||
*/
|
||
static MenuEventType key_scan(void)
|
||
{
|
||
if (_kbhit())
|
||
{
|
||
int key = _getch();
|
||
switch (key)
|
||
{
|
||
case 'w':
|
||
case 'W':
|
||
case 72: // 上箭头
|
||
return MENU_EVENT_KEY_UP;
|
||
case 's':
|
||
case 'S':
|
||
case 80: // 下箭头
|
||
return MENU_EVENT_KEY_DOWN;
|
||
case 13: // 回车键
|
||
return MENU_EVENT_KEY_ENTER;
|
||
case 'b':
|
||
case 'B':
|
||
case 27: // ESC键
|
||
return MENU_EVENT_KEY_BACK;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
return MENU_EVENT_NONE;
|
||
}
|
||
|
||
/************************** 主函数 **************************/
|
||
int main(void)
|
||
{
|
||
printf("Industrial Menu Component Example\r\n");
|
||
printf("==================================\r\n");
|
||
printf("Controls:\r\n");
|
||
printf(" W/Up Arrow - Up\r\n");
|
||
printf(" S/Down Arrow - Down\r\n");
|
||
printf(" Enter - Enter\r\n");
|
||
printf(" B/ESC - Back\r\n");
|
||
printf(" Q - Quit\r\n");
|
||
printf("==================================\r\n\r\n");
|
||
|
||
/************************** 初始化菜单组件 **************************/
|
||
MenuErrCode err = menu_init();
|
||
if (err != MENU_OK)
|
||
{
|
||
printf("Menu initialization failed: %d\r\n", err);
|
||
return -1;
|
||
}
|
||
printf("Menu initialized successfully\r\n\r\n");
|
||
|
||
/************************** 注册菜单节点 **************************/
|
||
// 注册主菜单
|
||
err = menu_register_node(0, MENU_ID_MAIN, "Main Menu", menu_cb_main, NULL);
|
||
if (err != MENU_OK)
|
||
{
|
||
printf("Register Main Menu failed: %d\r\n", err);
|
||
return -1;
|
||
}
|
||
|
||
// 注册设置菜单
|
||
err = menu_register_node(MENU_ID_MAIN, MENU_ID_SETTINGS, "Settings", menu_cb_settings, NULL);
|
||
if (err != MENU_OK)
|
||
{
|
||
printf("Register Settings Menu failed: %d\r\n", err);
|
||
return -1;
|
||
}
|
||
|
||
// 注册显示设置菜单
|
||
err = menu_register_node(MENU_ID_SETTINGS, MENU_ID_DISPLAY, "Display Settings", menu_cb_display, NULL);
|
||
if (err != MENU_OK)
|
||
{
|
||
printf("Register Display Menu failed: %d\r\n", err);
|
||
return -1;
|
||
}
|
||
|
||
// 注册语言设置菜单
|
||
err = menu_register_node(MENU_ID_SETTINGS, MENU_ID_LANGUAGE, "Language", menu_cb_language, NULL);
|
||
if (err != MENU_OK)
|
||
{
|
||
printf("Register Language Menu failed: %d\r\n", err);
|
||
return -1;
|
||
}
|
||
|
||
// 注册参数设置菜单
|
||
err = menu_register_node(MENU_ID_MAIN, MENU_ID_PARAMETER, "Parameters", menu_cb_parameter, NULL);
|
||
if (err != MENU_OK)
|
||
{
|
||
printf("Register Parameter Menu failed: %d\r\n", err);
|
||
return -1;
|
||
}
|
||
|
||
// 注册关于菜单
|
||
err = menu_register_node(MENU_ID_MAIN, MENU_ID_ABOUT, "About", menu_cb_about, NULL);
|
||
if (err != MENU_OK)
|
||
{
|
||
printf("Register About Menu failed: %d\r\n", err);
|
||
return -1;
|
||
}
|
||
|
||
/************************** 注册参数 **************************/
|
||
#if MENU_CONFIG_ENABLE_PARAM
|
||
// 注册亮度参数(范围0-100,默认50,步长1)
|
||
err = menu_param_register(MENU_ID_DISPLAY, PARAM_ID_BRIGHTNESS,
|
||
MENU_PARAM_TYPE_UINT8, 0.0f, 100.0f, 50.0f, 1.0f);
|
||
if (err != MENU_OK)
|
||
{
|
||
printf("Register Brightness Param failed: %d\r\n", err);
|
||
return -1;
|
||
}
|
||
|
||
// 注册对比度参数(范围0-100,默认50,步长1)
|
||
err = menu_param_register(MENU_ID_DISPLAY, PARAM_ID_CONTRAST,
|
||
MENU_PARAM_TYPE_UINT8, 0.0f, 100.0f, 50.0f, 1.0f);
|
||
if (err != MENU_OK)
|
||
{
|
||
printf("Register Contrast Param failed: %d\r\n", err);
|
||
return -1;
|
||
}
|
||
#endif
|
||
|
||
printf("Menu nodes registered successfully\r\n\r\n");
|
||
|
||
/************************** 主循环 **************************/
|
||
while (1)
|
||
{
|
||
// 扫描按键
|
||
MenuEventType event = key_scan();
|
||
if (event != MENU_EVENT_NONE)
|
||
{
|
||
// 发送按键事件到菜单组件
|
||
menu_post_event(event, 0);
|
||
}
|
||
|
||
// 处理菜单主循环
|
||
menu_main_loop();
|
||
|
||
// 检查退出条件
|
||
if (_kbhit() && _getch() == 'q')
|
||
{
|
||
printf("\r\nQuit program\r\n");
|
||
break;
|
||
}
|
||
|
||
// 轻微延迟,避免CPU占用过高
|
||
menu_port_delay_ms(10);
|
||
}
|
||
|
||
return 0;
|
||
} |