# 键盘适配
本文档介绍如何在 Emscripten 项目中集成微信小游戏虚拟键盘模块。
# 概述
本模块提供完整的虚拟键盘实现,将 C++ 的键盘操作映射到微信小游戏的 wx.showKeyboard、wx.hideKeyboard、wx.updateKeyboard 等 API。
业务只需要:
- 创建键盘配置对象
- 配置键盘参数(默认值、确认按钮类型等)
- 设置输入/确认/关闭回调
- 显示键盘
# 功能特性
| 功能 | 说明 |
|---|---|
| 单行输入 | 标准文本输入 |
| 多行输入 | 支持换行的多行文本输入 |
| 确认按钮类型 | 发送、搜索、下一个、前往、完成 |
| 键盘类型 | 文本键盘、数字键盘(客户端8.0.57+) |
| 输入实时回调 | 用户输入时实时通知 |
| 确认回调 | 用户点击确认按钮时通知 |
| 关闭回调 | 键盘关闭时通知 |
| 确认保持 | 点击确认后保持键盘打开(连续输入场景) |
| 动态更新 | 支持在键盘显示时更新输入内容 |
# 快速开始
# 集成到项目
# CMakeLists.txt 配置
cmake_minimum_required(VERSION 3.10)
project(MyGame)
set(WXGAMESDK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wxgamesdk")
add_executable(mygame main.cpp)
target_include_directories(mygame PRIVATE
${WXGAMESDK_DIR}/include
)
target_link_libraries(mygame
${WXGAMESDK_DIR}/lib/libwxgamesdk.a
)
set_target_properties(mygame PROPERTIES
LINK_FLAGS "\
-s WASM=1 \
-s EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\", \"stringToUTF8\", \"UTF8ToString\", \"lengthBytesUTF8\", \"allocateUTF8\"]' \
-s EXPORTED_FUNCTIONS='[\
\"_KeyboardOnInput\", \
\"_KeyboardOnConfirm\", \
\"_KeyboardOnComplete\", \
\"_main\", \"_free\", \"_malloc\"]' \
--js-library ${WXGAMESDK_DIR}/jslib/libwxkeyboard_open.jslib \
-Wl,--whole-archive ${WXGAMESDK_DIR}/lib/libwxgamesdk.a -Wl,--no-whole-archive"
)
# API 参考
# 头文件
#include "keyboard/wx_keyboard_interface.h"
# 命名空间
所有键盘相关接口都在 WXGameSDK 命名空间下。
# 枚举类型
# KeyboardConfirmType - 确认按钮类型
| 值 | 说明 |
|---|---|
Send | 发送 |
Search | 搜索 |
Next | 下一个 |
Go | 前往 |
Done | 完成(默认) |
# KeyboardType - 键盘类型
| 值 | 说明 |
|---|---|
Text | 文本键盘(默认) |
Number | 数字键盘(客户端8.0.57+) |
# KeyboardEventType - 键盘事件类型
| 值 | 说明 |
|---|---|
InputChanged | 键盘输入内容变化 |
Confirmed | 键盘确认(用户点击完成/发送等) |
Closed | 键盘关闭(点击输入框外区域收起键盘) |
# 核心接口
# 1. 创建与释放键盘
// 创建键盘配置对象
// keyboard_id: 输出参数,返回键盘ID
// 返回: KeyboardConfigInterface* 键盘配置对象,nullptr表示创建失败
WXGameSDK::KeyboardConfigInterface* CreateKeyboard(int* keyboard_id);
// 释放键盘配置对象
// 返回: 0 成功,-1 失败
int ReleaseKeyboard(int keyboard_id);
# 2. 显示与隐藏键盘
// 显示微信键盘
// 返回: 0 成功,-1 失败
int ShowKeyboard(int keyboard_id);
// 隐藏微信键盘(会触发对应键盘的complete回调)
// 返回: 0 成功,-1 失败
int HideKeyboard();
# 3. 键盘内容操作
// 更新键盘输入内容(仅在键盘显示时有效)
// 返回: 0 成功,-1 失败
int UpdateKeyboardValue(int keyboard_id, const std::string& text);
// 获取当前键盘输入内容
std::string GetKeyboardValue(int keyboard_id);
# 配置接口 (KeyboardConfigInterface)
| 方法 | 说明 |
|---|---|
SetConfirmType(type) | 设置确认按钮类型 |
SetDefaultValue(text) | 设置默认输入内容 |
SetMaxLength(length) | 设置最大输入长度(默认255) |
SetMultiple(enable) | 设置是否多行输入 |
SetConfirmHold(enable) | 设置确认后是否保持键盘打开 |
SetKeyboardType(type) | 设置键盘类型(文本/数字) |
SetInputCallback(callback, user_data) | 设置输入变化回调 |
SetConfirmCallback(callback, user_data) | 设置确认回调 |
SetCompleteCallback(callback, user_data) | 设置键盘关闭回调 |
# 回调函数签名
// 输入变化/确认/关闭回调
std::function<void(const std::string& text, void* user_data)>
# 使用示例
# 基本使用
#include "keyboard/wx_keyboard_interface.h"
#include <cstdio>
using namespace WXGameSDK;
// 创建键盘配置
int keyboard_id = -1;
KeyboardConfigInterface* keyboard = CreateKeyboard(&keyboard_id);
if (!keyboard) {
printf("创建键盘失败\n");
return;
}
// 配置键盘
keyboard->SetDefaultValue("请输入内容");
keyboard->SetMaxLength(100);
keyboard->SetConfirmType(KeyboardConfirmType::Done);
// 设置回调
keyboard->SetInputCallback([](const std::string& text, void* user_data) {
printf("输入变化: %s\n", text.c_str());
}, nullptr);
keyboard->SetConfirmCallback([](const std::string& text, void* user_data) {
printf("用户确认: %s\n", text.c_str());
}, nullptr);
keyboard->SetCompleteCallback([](const std::string& text, void* user_data) {
printf("键盘关闭: %s\n", text.c_str());
}, nullptr);
// 显示键盘
int ret = ShowKeyboard(keyboard_id);
if (ret == 0) {
printf("键盘显示成功\n");
} else {
printf("键盘显示失败\n");
}
// ... 使用完毕后释放
ReleaseKeyboard(keyboard_id);
# 多行输入
int keyboard_id = -1;
KeyboardConfigInterface* keyboard = CreateKeyboard(&keyboard_id);
// 启用多行输入
keyboard->SetMultiple(true);
keyboard->SetDefaultValue("第一行\n第二行");
keyboard->SetMaxLength(500);
keyboard->SetConfirmType(KeyboardConfirmType::Send);
// 设置回调...
ShowKeyboard(keyboard_id);
# 搜索模式(确认后保持键盘)
int keyboard_id = -1;
KeyboardConfigInterface* keyboard = CreateKeyboard(&keyboard_id);
// 确认后保持键盘打开(适用于连续搜索场景)
keyboard->SetConfirmHold(true);
keyboard->SetConfirmType(KeyboardConfirmType::Search);
keyboard->SetConfirmCallback([](const std::string& text, void* user_data) {
printf("执行搜索: %s\n", text.c_str());
// 搜索完成后键盘仍然打开,用户可继续输入
}, nullptr);
ShowKeyboard(keyboard_id);
# 动态更新键盘内容
// 在键盘显示时更新内容
UpdateKeyboardValue(keyboard_id, "新的内容");
// 获取当前输入内容
std::string current = GetKeyboardValue(keyboard_id);
printf("当前输入: %s\n", current.c_str());
# UE 引擎集成
UE 引擎通过实现 IPlatformTextField 接口来适配微信小游戏键盘。完整的适配示例请参考:
HTML5PlatformTextField.h- 头文件HTML5PlatformTextField.cpp- 实现文件
# 集成步骤
# 1. 添加头文件
将 SDK 头文件添加到 UE 项目的 Include 路径:
Source/ThirdParty/wxgamesdk/include/keyboard/wx_keyboard_interface.h
# 2. 添加静态库
将编译产物 libwxgamesdk.a 添加到链接选项:
Source/ThirdParty/wxgamesdk/lib/libwxgamesdk.a
# 3. 添加 JS 库
确保 libwxkeyboard_open.jslib 被包含在 Emscripten 链接选项中:
--js-library path/to/libwxkeyboard_open.jslib
# 4. 导出函数
确保以下函数被导出:
-s EXPORTED_FUNCTIONS='["_KeyboardOnInput", "_KeyboardOnConfirm", "_KeyboardOnComplete", ...]'
# UE 适配原理
UE 引擎的文本输入框(如 SEditableText)在需要显示虚拟键盘时,会调用平台适配层的 IPlatformTextField 接口。适配层需要:
实现
ShowVirtualKeyboard方法:- 当
bShow=true时,创建键盘配置并显示键盘 - 当
bShow=false时,隐藏键盘
- 当
处理三种回调事件:
InputCallback:实时更新 UE 控件文本(TextEntryUpdated)ConfirmCallback:确认输入(TextEntryAccepted)CompleteCallback:取消/关闭输入(TextEntryCanceled)
键盘类型映射:
- 将 UE 的
EKeyboardType映射为微信的KeyboardConfirmType
- 将 UE 的
# UE 适配关键代码说明
void FHTML5PlatformTextField::ShowVirtualKeyboard(bool bShow, int32 UserIndex,
TSharedPtr<IVirtualKeyboardEntry> TextEntryWidget) {
if (bShow && TextEntryWidget.IsValid()) {
// 保存当前活跃的控件引用
ActiveTextWidget = TextEntryWidget;
// 创建键盘配置
KeyboardConfigInterface* Keyboard = WXGameSDK::CreateKeyboard(&KeyboardId);
// 从 UE 控件获取默认文本
FString DefaultText = TextEntryWidget->GetText().ToString();
Keyboard->SetDefaultValue(TCHAR_TO_UTF8(*DefaultText));
// 根据控件属性配置键盘
Keyboard->SetMultiple(TextEntryWidget->IsMultilineEntry());
Keyboard->SetConfirmType(GetWxConfirmType(TextEntryWidget->GetVirtualKeyboardType()));
// 设置回调,将微信键盘事件转发给 UE 控件
Keyboard->SetInputCallback([this](const std::string& Text, void* UserData) {
HandleKeyboardInput(Text, UserData);
}, this);
// ... 其他回调设置
// 显示键盘
WXGameSDK::ShowKeyboard(KeyboardId);
} else {
// 隐藏键盘
WXGameSDK::HideKeyboard();
}
}
# 注意事项
- 生命周期管理:创建的键盘配置对象需要在不使用时调用
ReleaseKeyboard释放 - 回调线程:所有回调都在主线程(JS 线程)中执行
- 同一时间只能显示一个键盘:如果调用
ShowKeyboard时已有键盘显示,会先关闭旧键盘 - 回调中禁止操作:在回调函数中不能调用
ShowKeyboard、HideKeyboard、ReleaseKeyboard - 最大实例数:最多同时存在 5 个键盘配置实例
# 错误处理
| 返回值 | 说明 |
|---|---|
| 0 | 成功 |
| -1 | 通用错误 / 操作失败 |
| nullptr | 创建失败(CreateKeyboard 返回) |
# 下一步
- 了解 HTTP 客户端适配
- 了解 文件系统适配
- 了解 WebSocket 适配
- 了解 微信开放接口