• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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```