1# 在自绘编辑框中使用输入法开发指导 (C/C++) 2<!--Kit: IME Kit--> 3<!--Subsystem: MiscServices--> 4<!--Owner: @illybyy--> 5<!--Designer: @andeszhang--> 6<!--Tester: @murphy1984--> 7<!--Adviser: @zhang_yixin13--> 8 9## 场景介绍 10 11IME Kit支持开发者在自绘编辑框中使用输入法,与输入法应用交互,包括显示、隐藏输入法,接收来自输入法应用的文本编辑操作通知等,本文档介绍开发者如何使用C/C++完成此功能开发。 12 13## 接口说明 14 15详细接口说明请参考[InputMethod接口文档](../reference/apis-ime-kit/capi-inputmethod.md)。 16 17## 添加动态链接库 18 19CMakeLists.txt中添加以下lib。 20 21```txt 22libohinputmethod.so 23``` 24 25## 引用头文件 26 27```c 28#include <inputmethod/inputmethod_controller_capi.h> 29``` 30 31 32## 绑定输入法 33 34开发者需要在输入框获焦时,通过调用接口[OH_InputMethodController_Attach](../reference/apis-ime-kit/capi-inputmethod-controller-capi-h.md#oh_inputmethodcontroller_attach)绑定输入法,绑定成功后用户可以通过输入法输入文字。 35 361. 创建InputMethod_TextEditorProxy实例,示例代码如下所示: 37 38 ```c 39 // 创建InputMethod_TextEditorProxy实例 40 InputMethod_TextEditorProxy *textEditorProxy = OH_TextEditorProxy_Create(); 41 ``` 42 433. 创建InputMethod_AttachOptions实例,设置绑定输入法时的选项。示例代码如下所示: 44 45 ```c 46 // 创建InputMethod_AttachOptions实例,选项showKeyboard用于指定此次绑定成功后是否显示键盘,此处以目标显示键盘为例 47 bool showKeyboard = true; 48 InputMethod_AttachOptions *options = OH_AttachOptions_Create(showKeyboard); 49 ``` 50 514. 调用OH_InputMethodController_Attach发起绑定输入法服务,调用成功后,可以获取到用于和输入法交互的InputMethod_InputMethodProxy。示例代码如下所示: 52 53 ```c 54 InputMethod_InputMethodProxy *inputMethodProxy = nullptr; 55 // 发起绑定请求 56 if (OH_InputMethodController_Attach(textEditorProxy, options, &inputMethodProxy) != InputMethod_ErrorCode::IME_ERR_OK) { 57 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "Attach failed!"); 58 } 59 ``` 60 61## 显示/隐藏面板功能 62 63绑定成功后,可以使用获取到的[InputMethod_InputMethodProxy](../reference/apis-ime-kit/capi-inputmethod-inputmethod-inputmethodproxy.md)对象向输入法发送消息。示例代码如下所示: 64 65```c 66// 显示键盘 67if (OH_InputMethodProxy_ShowKeyboard(inputMethodProxy) != InputMethod_ErrorCode::IME_ERR_OK) { 68 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "ShowKeyboard failed!"); 69} 70// 隐藏键盘 71if (OH_InputMethodProxy_HideKeyboard(inputMethodProxy) != InputMethod_ErrorCode::IME_ERR_OK) { 72 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "HideKeyboard failed!"); 73} 74// 通知输入框配置信息变化 75if (OH_InputMethodProxy_NotifyConfigurationChange(inputMethodProxy, InputMethod_EnterKeyType::IME_ENTER_KEY_GO, InputMethod_TextInputType::IME_TEXT_INPUT_TYPE_TEXT) != InputMethod_ErrorCode::IME_ERR_OK) { 76 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "NotifyConfigurationChange failed!"); 77} 78``` 79 80## 监听输入法应用的请求/通知 81 821. 需要先实现对输入法应用发送的请求或通知的响应处理函数,示例代码如下所示: 83 84 ```c 85 // 实现InputMethod_TextEditorProxy中的输入法应用事件响应函数 86 void GetTextConfig(InputMethod_TextEditorProxy *textEditorProxy, InputMethod_TextConfig *config) 87 { 88 // 处理输入法发送的获取输入框配置请求 89 } 90 void InsertText(InputMethod_TextEditorProxy *textEditorProxy, const char16_t *text, size_t length) 91 { 92 // 处理输入法发送的插入文本请求 93 } 94 void DeleteForward(InputMethod_TextEditorProxy *textEditorProxy, int32_t length) 95 { 96 // 处理输入法发送的删除文本请求 97 } 98 // ...... 99 ``` 100 1012. 将实现后的响应函数,设置到[InputMethod_TextEditorProxy](../reference/apis-ime-kit/capi-inputmethod-inputmethod-texteditorproxy.md)中,再通过绑定输入法时调用的[OH_InputMethodController_Attach](../reference/apis-ime-kit/capi-inputmethod-controller-capi-h.md#oh_inputmethodcontroller_attach)将其设置到输入法框架中,完成监听注册。示例代码如下所示: 102 103 ```c 104 // 将实现好的响应处理函数设置到InputMethod_TextEditorProxy中 105 OH_TextEditorProxy_SetGetTextConfigFunc(textEditorProxy, GetTextConfig); 106 OH_TextEditorProxy_SetInsertTextFunc(textEditorProxy, InsertText); 107 OH_TextEditorProxy_SetDeleteForwardFunc(textEditorProxy, DeleteForward); 108 ``` 109 110## 解绑输入法 111 112当编辑框失焦,需要结束使用输入法,通过接口[OH_InputMethodController_Detach](../reference/apis-ime-kit/capi-inputmethod-controller-capi-h.md#oh_inputmethodcontroller_detach)与输入法框架解绑。 113 114```c 115// 发起解绑请求 116if (OH_InputMethodController_Detach(inputMethodProxy) != InputMethod_ErrorCode::IME_ERR_OK) { 117 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "Detach failed!"); 118} 119inputMethodProxy = nullptr; 120OH_TextEditorProxy_Destroy(textEditorProxy); 121textEditorProxy = nullptr; 122OH_AttachOptions_Destroy(options); 123options = nullptr; 124``` 125 126## 完整示例 127 128示例代码展示了绑定输入法、隐藏输入法、解绑输入法的完整流程。 129 130示例代码总入口为InputMethodNdkDemo函数。 131 132> 说明: 133> 134> 需要在CMakeList.txt中添加libohinputmethod.so libhilog_ndk.z.so依赖。 135```c++ 136#include <codecvt> 137#include <locale> 138#include <string> 139 140#include "hilog/log.h" 141#include "inputmethod/inputmethod_controller_capi.h" 142 143void GetTextConfigFunc(InputMethod_TextEditorProxy *proxy, InputMethod_TextConfig *config) { // 处理获取输入框配置请求 144 auto ret = OH_TextConfig_SetEnterKeyType(config, InputMethod_EnterKeyType::IME_ENTER_KEY_SEND); 145 if (ret != IME_ERR_OK) { 146 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "SetEnterKeyType failed, ret=%{public}d", ret); 147 return; 148 } 149 150 ret = OH_TextConfig_SetInputType(config, InputMethod_TextInputType::IME_TEXT_INPUT_TYPE_PHONE); 151 if (ret != IME_ERR_OK) { 152 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "SetInputType failed, ret=%{public}d", ret); 153 return; 154 } 155} 156void InsertTextFunc(InputMethod_TextEditorProxy *proxy, const char16_t *text, size_t length) { 157 // 处理插入文本请求 158 // 将char16_t类型的字符串转换为u16string 159 std::u16string u16Str(text); 160 161 // 转换为UTF-8编码的string 162 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter; 163 std::string utf8Str = converter.to_bytes(u16Str); 164 165 OH_LOG_Print(LOG_APP, LOG_INFO, 0, "testTag", "insertText=%{public}s", utf8Str.c_str()); 166} 167void DeleteForwardFunc(InputMethod_TextEditorProxy *proxy, int32_t length) { 168 // 处理删除光标右侧文本请求 169} 170void DeleteBackwardFunc(InputMethod_TextEditorProxy *proxy, int32_t length) { 171 // 处理删除光标左侧文本请求 172} 173void SendKeyboardStatusFunc(InputMethod_TextEditorProxy *proxy, InputMethod_KeyboardStatus status) { 174 // 处理键盘状态发生变化请求 175} 176void SendEnterKeyFunc(InputMethod_TextEditorProxy *proxy, InputMethod_EnterKeyType type) { 177 // 处理回车键功能发生变化请求 178} 179void MoveCursorFunc(InputMethod_TextEditorProxy *proxy, InputMethod_Direction direction) { 180 // 处理移动光标请求 181} 182void HandleSetSelectionFunc(InputMethod_TextEditorProxy *proxy, int32_t start, int32_t end) { 183 // 处理选中文本请求 184} 185void HandleExtendActionFunc(InputMethod_TextEditorProxy *proxy, InputMethod_ExtendAction action) { 186 // 处理扩展编辑请求 187} 188void GetleftTextOfCursorFunc(InputMethod_TextEditorProxy *proxy, int32_t number, char16_t text[], size_t *length) { 189 // 处理获取光标左侧文本请求 190} 191void GetRightTextOfCursorFunc(InputMethod_TextEditorProxy *proxy, int32_t number, char16_t text[], size_t *length) { 192 // 处理获取光标右侧文本请求 193} 194int32_t GetTextIndexAtCursorFunc(InputMethod_TextEditorProxy *proxy) { 195// 处理获取光标所在输入框文本索引请求 196 return 0; 197} 198int32_t ReceivePrivateCommandFunc(InputMethod_TextEditorProxy *proxy, InputMethod_PrivateCommand *privateCommand[], 199 size_t size) { 200 // 处理私有数据命令请求 201 return 0; 202} 203int32_t SetPreviewTextFunc(InputMethod_TextEditorProxy *proxy, const char16_t *text, size_t length, int32_t start, 204 int32_t end) { 205 // 处理设置预上屏文本请求 206 return 0; 207} 208void FinishTextPreviewFunc(InputMethod_TextEditorProxy *proxy) { 209 // 处理结束预上屏请求 210} 211 212void ConstructTextEditorProxy(InputMethod_TextEditorProxy *textEditorProxy) { 213 OH_TextEditorProxy_SetGetTextConfigFunc(textEditorProxy, GetTextConfigFunc); 214 OH_TextEditorProxy_SetInsertTextFunc(textEditorProxy, InsertTextFunc); 215 OH_TextEditorProxy_SetDeleteForwardFunc(textEditorProxy, DeleteForwardFunc); 216 OH_TextEditorProxy_SetDeleteBackwardFunc(textEditorProxy, DeleteBackwardFunc); 217 OH_TextEditorProxy_SetSendKeyboardStatusFunc(textEditorProxy, SendKeyboardStatusFunc); 218 OH_TextEditorProxy_SetSendEnterKeyFunc(textEditorProxy, SendEnterKeyFunc); 219 OH_TextEditorProxy_SetMoveCursorFunc(textEditorProxy, MoveCursorFunc); 220 OH_TextEditorProxy_SetHandleSetSelectionFunc(textEditorProxy, HandleSetSelectionFunc); 221 OH_TextEditorProxy_SetHandleExtendActionFunc(textEditorProxy, HandleExtendActionFunc); 222 OH_TextEditorProxy_SetGetLeftTextOfCursorFunc(textEditorProxy, GetleftTextOfCursorFunc); 223 OH_TextEditorProxy_SetGetRightTextOfCursorFunc(textEditorProxy, GetRightTextOfCursorFunc); 224 OH_TextEditorProxy_SetGetTextIndexAtCursorFunc(textEditorProxy, GetTextIndexAtCursorFunc); 225 OH_TextEditorProxy_SetReceivePrivateCommandFunc(textEditorProxy, ReceivePrivateCommandFunc); 226 OH_TextEditorProxy_SetSetPreviewTextFunc(textEditorProxy, SetPreviewTextFunc); 227 OH_TextEditorProxy_SetFinishTextPreviewFunc(textEditorProxy, FinishTextPreviewFunc); 228} 229 230void InputMethodNdkDemo() { 231 // 创建InputMethod_TextEditorProxy实例 232 InputMethod_TextEditorProxy *textEditorProxy = OH_TextEditorProxy_Create(); 233 if (textEditorProxy == nullptr) { 234 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "Create TextEditorProxy failed."); 235 return; 236 } 237 238 // 将实现好的响应处理函数设置到InputMethod_TextEditorProxy中 239 ConstructTextEditorProxy(textEditorProxy); 240 241 // 创建InputMethod_AttachOptions实例,选项showKeyboard用于指定此次绑定成功后是否显示键盘,此处以目标显示键盘为例 242 bool showKeyboard = true; 243 InputMethod_AttachOptions *attachOptions = OH_AttachOptions_Create(showKeyboard); 244 if (attachOptions == nullptr) { 245 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "Create AttachOptions failed."); 246 OH_TextEditorProxy_Destroy(textEditorProxy); 247 return; 248 } 249 250 InputMethod_InputMethodProxy *inputMethodProxy = nullptr; 251 // 发起绑定请求 252 auto ret = OH_InputMethodController_Attach(textEditorProxy, attachOptions, &inputMethodProxy); 253 if (ret != IME_ERR_OK) { 254 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "Attach failed, ret=%{public}d.", ret); 255 OH_TextEditorProxy_Destroy(textEditorProxy); 256 OH_AttachOptions_Destroy(attachOptions); 257 return; 258 } 259 260 // 让键盘显示3s 261 std::this_thread::sleep_for(std::chrono::seconds(3)); 262 263 // 隐藏键盘 264 ret = OH_InputMethodProxy_HideKeyboard(inputMethodProxy); 265 if (ret != IME_ERR_OK) { 266 OH_LOG_Print(LOG_APP, LOG_ERROR, 0, "testTag", "HideKeyboard failed, ret=%{public}d.", ret); 267 OH_TextEditorProxy_Destroy(textEditorProxy); 268 OH_AttachOptions_Destroy(attachOptions); 269 return; 270 } 271 272 // 发起解绑请求 273 OH_InputMethodController_Detach(inputMethodProxy); 274 OH_TextEditorProxy_Destroy(textEditorProxy); 275 OH_AttachOptions_Destroy(attachOptions); 276 OH_LOG_Print(LOG_APP, LOG_INFO, 0, "testTag", "Finished."); 277} 278```