miniGUI源码分析:软键盘界面美化

上一篇文章说到,miniGUI软键盘根本上是由图片和按键坐标配合实现的,若想美化软键盘,则需替换重新设计的键盘图片。
图片资源的相关内容在source.c文件中,RESDATA结构体中为所有的键盘图片资源名称,图片替换后需根据图片位置修改对应宏定义和按键坐标。

说明
SKB_WIN_W/SKB_WIN_H键盘的宽高
SKB_CLOSE_L/SKB_CLOSE_T / SKB_CLOSE_R/SKB_CLOSE_B关闭键盘按钮的坐标
SKB_VW_L/SKB_VW_T/SKB_VW_R/SKB_VW_B文字候选词区域坐标
SKB_VW_PU_L/SKB_VW_PU_T/SKB_VW_PU_R/SKB_VW_PU_B文字候选上一页按钮的坐标
SKB_VW_PD_L/SKB_VW_PD_T/SKB_VW_PD_R/SKB_VW_PD_B文字候选下一页按钮的坐标
SKB_SW_L/SKB_SW_T/SKB_SW_R/SKB_SW_B输入字符显示区域坐标
SKB_KW_L/SKB_KW_T/SKB_KW_R/SKB_KW_B键盘按键区域的坐标
VW_ELMT_LEN单个候选词最大长度
VW_BUFFER_LEN一页候选词最大长度
VW_ELMENT_NR一页候选词最多能有多少个候选词
SW_STR_LEN输出字符最大长度

按键坐标则需在size_*.h文件中修改,然后将修改后的坐标与各键盘文件(如en_kbd.c)中的md_key_t结构体匹配,如果图片中按键布局做了调整,则需相应调整md_key_t中的信息,保证按键位置和字符等信息一一对应。

#define RECT_EN_KEY_1           {  2,   2,  31,  33}
#define RECT_EN_KEY_2           { 32,   2,  61,  33}

static md_key_t en_key_pads[] = {
      {RECT_EN_KEY_1,  'q', SCANCODE_Q,  KEY_PAD_CHAR, NULL, share_key_update},
      {RECT_EN_KEY_2,  'w', SCANCODE_W,  KEY_PAD_CHAR, NULL, share_key_update},
}

拼音键盘

拼音键盘的输入需要stroke_window和view_window区域来显示输入的字符和候选字,但由于软键盘窗口空间有限,字体显示会比较小,若将区域空间改大则影响美观。如何实现windows系统下的输入效果,输入字符直接显示在目标控件中,而软键盘中只显示候选字,这样即可取消stroke_window区域,view_window的显示空间会更大,实际效果如图中所示。

在这里插入图片描述

实现方法

1. 隐藏stroke_window

stroke_window区域并不是完全取消,只是将区域空间缩小不显示,而stroke_window的功能依然存在,因为view_window会根据stroke_window中的字符联想候选词,因此输入字符依然要存入stroke_window中。
另外需注意stroke_window宽高不可设为0,因为stroke_window不是实际窗口,没有窗口句柄,判断stroke_window是否存在的方法是判断区域大小是否为0。

#define SKB_SW_L        0
#define SKB_SW_T        0
#define SKB_SW_R        (SKB_SW_L+1)
#define SKB_SW_B        (SKB_SW_T+1)
2. 字符发送到目标控件

英文输入时会直接将字符发送到目标控件,而拼音字符输入时没有将字符显示在目标控件中,因此,我们只需在处理拼音输入时也将字符发送到目标控件。
字符输入的处理在kw_proceed_hit函数中,其中参数flag的作用是区分英文和中文,只需在key->style & KEY_PAD_CHAR的判断为TRUE时加入以下代码。

if (flag == CN) 
{
	PostMessage(pdata->target_hwnd, MSG_CHAR, ch, 0);
}
3. 输入字符选中

为了区分拼音输入字符和英文输入下的不同,将拼音输入的字符设为选中状态,此方法的好处有以下两点:

  • 高亮显示,表示正在输入的字符
  • 可利用选中效果实现点击候选词后的直接覆盖

设置输入高亮需在edit控件中处理MSG_CHAR消息时判断,当前键盘为拼音键盘并且stroke_window中有字符时,设置选中字符,选中部分起点为当前光标位置减去stroke_window中字符的个数,终点为光标位置,代码如下

if (__mg_ime_wnd 
    && IsWindowVisible(__mg_ime_wnd)
    && (NULL != pdata))
{
	if(SFKB_IDX_PINYIN == pdata->current_board_idx)
	{
		if(strlen(pdata->keyboard->stroke_window->str) > 0)
		{
			sleSetSel (hWnd, sled, sled->editPos - strlen(pdata->keyboard->stroke_window->str), sled->editPos);
		}
	}
}

输入字符设为选中后也相应的会出现一些问题:

  • 选中后再输入会自动覆盖前面的输入,只能显示一个字符
  • 删除输入时会将选中的所有字符一起删除,输入错误只能重新输入

为解决此问题,需了解选中效果的处理逻辑,edit控件字符输入函数sleInsertText中,当(sled->selStart != sled->selEnd)即出现选中时,会进行特殊处理,我们只需在此部分处理时,判断当前是否为拼音键盘输入,如果是则不进行此部分处理。

4. 注意

此实现效果有以下几点需要额外注意:

  1. 字符输入时超过控件限制,需要解除字符输入时的限制,仅限制汉字的个数,否则最后一个汉字无法输入完整的拼音
  2. 字符输入时切换键盘,需要清除选中效果
  3. stroke_window需和目标控件中的选中字符同步,包括各种场景下的同步,例如输入字符后为选中态,此时输入数字会将字符覆盖,需同步stroke_window->str
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值