在LVGL模拟器中使用PC Keyboard

运行环境:

        - Windows 10

        - LVGL 7.5.0

        - SDL2

        - gcc

        LVGL模拟器内已经基于SDL2做了一个基础的键盘输入驱动,先简单叙述下如何使用吧。假设有一个text area,需要基于PC键盘实现文本的基本控制(增、删、移动光标)。值得庆幸的是模拟器内已经做好了框架,在初步跑起来之前需要对 lv_drivers\indev\keyboard.c 文件进行调整。

lv_drivers\indev\keyboard.c

         lv_drivers\indev\keyboard.c 文件内 LV_KEY_BACKSPACE 和 LV_KEY_DEL 被宏控制,需要取消宏,否则text area内将无法使用退格键和删除键,修改后如下:

static uint32_t keycode_to_ascii(uint32_t sdl_key)
{
    /*Remap some key to LV_KEY_... to manage groups*/
    switch(sdl_key) {
        case SDLK_RIGHT:
        case SDLK_KP_PLUS:
            return LV_KEY_RIGHT;

        case SDLK_LEFT:
        case SDLK_KP_MINUS:
            return LV_KEY_LEFT;

        case SDLK_UP:
            return LV_KEY_UP;

        case SDLK_DOWN:
            return LV_KEY_DOWN;

        case SDLK_ESCAPE:
            return LV_KEY_ESC;

// #ifdef  LV_KEY_BACKSPACE        /*For backward compatibility*/
        case SDLK_BACKSPACE:
            return LV_KEY_BACKSPACE;
// #endif

// #ifdef  LV_KEY_DEL        /*For backward compatibility*/
        case SDLK_DELETE:
            return LV_KEY_DEL;
// #endif
        case SDLK_KP_ENTER:
        case '\r':
            return LV_KEY_ENTER;

        default:
            return sdl_key;
    }
}

        LV_KEY_* 键码定义在 lvgl\src\lv_core\lv_group.h 文件内。keycode_to_ascii 函数的作用就是将SDL2内定义的按键码转换成LVGL内定义的按键码,如果需要在Windows里面基于LVGL写一些小工具或者小软件,又需要使用键盘输入的话,直接在这个函数里面改就行,还是很方便的。

LVGL V7版本的文档内对绑定键盘输入的叙述如下:

照猫画虎吧,创建一个text area,再创建一个组,最后做一个绑定:

extern lv_indev_t *keyboard_indev;

static lv_obj_t * text_recv = NULL;
static lv_group_t * g = NULL;

void text(lv_obj_t *obj)
{
    text_recv = lv_textarea_create(obj, NULL);
    lv_obj_set_size(text_recv, 50, 30);
    lv_textarea_set_text_sel(text_recv, true);
    lv_textarea_add_text(text_recv, "hi");
    lv_obj_set_event_cb(text_recv, event_handler_text_recv);

    g = lv_group_create();
    lv_group_add_obj(g, text_recv);
    lv_indev_set_group(keyboard_indev, g);
}

static void event_handler_text_recv(lv_obj_t *obj, lv_event_t event)
{
    lv_indev_data_t data;

    if(event == LV_EVENT_KEY)
    {
        printf("LV_EVENT_KEY\n");

        keyboard_indev->driver.read_cb(keyboard_indev, &data);
        printf("key=%d\n", data.key);
    }
}

        变量 keyboard_indev 存储的是函数 lv_indev_drv_register() 的返回值。在LVGL提供的模拟器工程中,鼠标键盘的初始化被放置在 main.c 的 hal_init() 函数内,但是只做了鼠标注册后返回句柄的存储,键盘的句柄被忽略了,此处需要自己加上,修改后 hal_init() 部分代码如下:

  /* Add the keyboard as input device
   * Use the 'keyboard' driver which reads the PC's keyboard*/
  keyboard_init();
  lv_indev_drv_init(&keyb_drv);
  keyb_drv.type = LV_INDEV_TYPE_KEYPAD;
  keyb_drv.read_cb = keyboard_read;
  
  /* */
  keyboard_indev = lv_indev_drv_register(&keyb_drv);

        编译运行后发现模拟器内的键盘功能只能说堪堪能用,至少小写字母、数字、删除键、退格键以及回车这些都能用,大写字母和需要Shift组合输入的字符就不行了,这个得自己去 keycode_to_ascii 函数内处理。

lv_drivers\indev\keyboard.c 修改了一部分,基本满足目前的需求~

/**
 * @file sdl_kb.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "keyboard.h"

#if USE_KEYBOARD

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static uint32_t keycode_to_ascii(uint32_t sdl_key);

/**********************
 *  STATIC VARIABLES
 **********************/
static uint32_t last_key;
static lv_indev_state_t state;
static uint32_t last_mod;

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

/**
 * Initialize the keyboard
 */
void keyboard_init(void)
{
    /*Nothing to init*/
}

/**
 * Get the last pressed or released character from the PC's keyboard
 * @param indev_drv pointer to the related input device driver
 * @param data store the read data here
 * @return false: because the points are not buffered, so no more data to be read
 */
bool keyboard_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
{
    (void)indev_drv; /*Unused*/
    data->state = state;
    data->key = keycode_to_ascii(last_key);

    return false;
}

/**
 * It is called periodically from the SDL thread to check a key is pressed/released
 * @param event describes the event
 */
void keyboard_handler(SDL_Event *event)
{
    /* We only care about SDL_KEYDOWN and SDL_KEYUP events */
    switch (event->type)
    {
    case SDL_KEYDOWN:                     /*Button press*/
        last_key = event->key.keysym.sym; /*Save the pressed key*/
        last_mod = event->key.keysym.mod; /* Save current key modifiers */

        /* 忽略控制按键 */
        switch (last_key)
        {
        case SDLK_CAPSLOCK:
            // 大写键
        case SDLK_LCTRL:
            // 左Ctrl键
        case SDLK_RCTRL:
            // 右Ctrl键
        case SDLK_LSHIFT:
            // 左Shift键
        case SDLK_RSHIFT:
            // 右Shift键
        case SDLK_LALT:
            // 左Alt键
        case SDLK_RALT:
            // 右Alt键
        case SDLK_LGUI:
            // 左Win键
        case SDLK_RGUI:
            // 右Win键
            state = LV_INDEV_STATE_REL;
            return;

        default:
            break;
        }
        state = LV_INDEV_STATE_PR; /*Save the key is pressed now*/
        break;
    case SDL_KEYUP:                 /*Button release*/
        state = LV_INDEV_STATE_REL; /*Save the key is released but keep the last key*/
        break;
    default:
        break;
    }
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/**
 * Convert the key code LV_KEY_... "codes" or leave them if they are not control characters
 * @param sdl_key the key code
 * @return
 */
static uint32_t keycode_to_ascii(uint32_t sdl_key)
{
    /*Remap some key to LV_KEY_... to manage groups*/
    switch (sdl_key)
    {
    case SDLK_RIGHT:
    case SDLK_KP_PLUS:
        return LV_KEY_RIGHT;

    case SDLK_LEFT:
    case SDLK_KP_MINUS:
        return LV_KEY_LEFT;

    case SDLK_UP:
        return LV_KEY_UP;

    case SDLK_DOWN:
        return LV_KEY_DOWN;

    case SDLK_ESCAPE:
        return LV_KEY_ESC;

    /*For backward compatibility*/
    case SDLK_BACKSPACE:
        return LV_KEY_BACKSPACE;

    /*For backward compatibility*/
    case SDLK_DELETE:
        return LV_KEY_DEL;

    case SDLK_KP_ENTER:
    case '\r':
        return LV_KEY_ENTER;

    default:
        /* 大写键被按下 */
        if (last_mod == KMOD_CAPS)
        {
            if ((last_key >= 'a') && (last_key <= 'z'))
            {
                return (last_key - 0x20);
            }
        }

        /* shift键按下 */
        if (last_mod & KMOD_SHIFT)
        {
            switch (last_key)
            {
            case '`':
                return '~';
            case '1':
                return '!';
            case '2':
                return '@';
            case '3':
                return '#';
            case '4':
                return '$';
            case '5':
                return '%';
            case '6':
                return '^';
            case '7':
                return '&';
            case '8':
                return '*';
            case '9':
                return '(';
            case '0':
                return ')';
            case '-':
                return '_';
            case '=':
                return '+';
            case '[':
                return '{';
            case ']':
                return '}';
            case '\\':
                return '|';
            case '\'':
                return '"';
            case ',':
                return '<';
            case '.':
                return '>';
            case '/':
                return '?';
            case ';':
                return ':';

            default:
                break;
            }
        }
        return sdl_key;
    }
}
#endif

对于使用VSCode来模拟运行LVGL(Light and Versatile Graphics Library)的方法,以下是一些步骤: 1. 首先,确保你已经安装了VSCode编辑器和C/C++扩展插件。 2. 打开VSCode,并创建一个新的文件夹用于你的LVGL项目。 3. 在新的文件夹创建一个名为`main.c`的C文件,并在其编写你的LVGL代码。 4. 在VSCode的侧边栏,点击左侧的调试按钮(一个虫子的图标),然后点击顶部的齿轮图标以编辑`launch.json`文件。 5. 在`launch.json`文件,找到`configurations`部分,并添加一个新的配置,如下所示: ```json { "name": "LVGL Simulator", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/main.c", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": true, "MIMode": "lldb" } ``` 6. 保存`launch.json`文件。 7. 现在你可以在VSCode的调试面板选择“LVGL Simulator”配置,并点击绿色的播放按钮来运行LVGL模拟器。 8. 模拟器将在外部控制打开,并显示你的LVGL应用程序的输出。 请注意,这只是一种可能的方法来使用VSCode模拟运行LVGL应用程序。具体的配置可能因你的项目需求而有所不同。如果你使用的是不同的模拟器或调试器,你需要相应地修改`launch.json`文件的配置。 希望这些步骤能帮助到你开始使用VSCode来模拟运行LVGL应用程序!如有任何进一步的问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值