在开发输入法应用的时候,我们需要让候选栏时刻跟踪输入光标的位置,来进行输入。但候选栏定位不准,一直会困扰输入法的开发者。windows老的输入法框架imm在部分场景下比如chrome应用中会定位不准,而新的输入法框架TSF在部分应用中也会定位不准比如Notepad++等应用。
解决定位不准的问题,通常有两种方案
1.通过应用获取输入光标的位置然后进行候选定位
2.通过TSF框架预先上屏占位符号进行定位

两种方案各有利弊,这里我介绍一下两种方案
1.通过应用的输入光标进行定位,获取光标的方法如下

POINT get_candidates_locate_pos()
try
{
    HWND hwnd;
    GUITHREADINFO pg;
    POINT point = {-1,-1};//光标位置
    DWORD dwProcID;
    hwnd= GetForegroundWindow();//获取当前激活应用
    //根据窗口句柄获取线程对应的ID
   DWORD ForeThreadId = GetWindowThreadProcessId(hwnd, &dwProcID);
   pg.cbSize = sizeof(GUITHREADINFO);
   ::GetGUIThreadInfo(ForeThreadId, &pg);
    if (pg.hwndCaret)
    {
        //获得输入光标的位置
        point.x = pg.rcCaret.right;
        point.y = pg.rcCaret.bottom;
        ::ClientToScreen(pg.hwndCaret, &point);
    }
    else
    {
        return point;//取不到对应的光标位置
    }
    return point;
}
catch(exception& e)
{
    log(TEXT("%s throw exception:%s"), __FUNCTION__, e.what());
    return POINT(-1,-1);
}

方案二
通过预先上屏字符进行定位

预先上屏

如上图所示,预先上屏的字符串就是红框框选的字符。这些字符在候选栏上屏之后会消失。这种方案的优点是通过TSF框架进行预先定位,在大部分场景下定位比较精确。缺点是,会预先上屏一部分字符,遮盖住部分内容,影响对应的视觉效果。

图片中的方框内容在TSF框架里面对应的类是ITfRange,预先上屏占位,但候选上屏的时候字符串会消失。为了避免预先上屏的字符串影响用户的视觉效果可以预先上屏一个空格或者宽度为0的Unicode字符\u200b来进行定位

TSF框架获取输入光标的位置,实际就是通过ITfRange上屏的字符串矩形获取定位,框架中的调用流程如下所示.

HRESUL GetCandidateCursorPos(_Out_ RECT *lpRect, _Out_ HWND *hwnd)
{
    HRESULT hr = S_OK;
    BOOL isClipped = TRUE;
    CComPtr<ITfContextView> pContextView = nullptr;
    //先通过ITfContext获取对应的编辑视图
    hr = _ITfContext_ptr->GetActiveView(&pContextView);
    if (FAILED(hr))
    {
        //获取对应的视图失败
        return hr;
    }
    //@1 指定tfEditCookie
    //@2 输入法预上屏的字符_pRange
    //@3 获取_pRange所在输入文档显示的Rect
    //@4 最后一个参数指定位true,则只跟踪被裁剪的pRange//如果预上屏的字符串为空,则获取的定位lpRect可能异常
    if (FAILED(hr = pContextView->GetTextExt(_tfEditCookie, _ptfRange,
    lpRect, &isClipped)))
    {
        return hr;
    }
    pContextView->GetWnd(hwnd);
    return S_OK;
}

其实我觉的两种方案都各有优劣,我建议将两种方案组合起来进行使用,在输入法内部预置一份应用的名单,在部分场景下通过应用获取光标的方式进行候选栏定位,其它的场景下通过预先上屏一个空字符来进行定位,这样的话,整体效果是最佳的.当然也不排除随着windows TSF框架的优化,在不久的将来输入法候选栏定位问题已经不再是一个问题了.

相关推荐

基于文本服务框架(tsf)的拼音输入法研究与实现

摘要:目前的输入法大多采用输入法管理器-输入法编辑器(IMM-IME)进行开发,对于微软发布的新型输入法技术―文本服务框架(TSF)的研究一直比较滞后,该文论述了 TSF 的基本构成、主要接口、输入法

[输入法]tsf框架中预先上屏的字符管理和控制

在TSF框架中有时候我们需要通过框架上屏一些占位字符来进行定位,这时候我们就需要对预先上屏的字符进行管理,以微软的输入法为例图中红框框选出来的部分就是预先上屏的字符。在TSF框架中通过ITfRange

tsftext services framework)和输入法

1.TSF输入接口IMM-IME架构成熟,稳定,易于实现,在Windows中被广泛使用,甚至在Linux曾大量使用的中文输入接口SCIM中也可以看到IMM-IME的影子。但是由于IMM-IME在操作权

tsf输入法

TSF 即文本服务框架的英文缩写微软官方文档(文本服务框架) https://learn.microsoft.com/zh-cn/windows/win32/tsf/text-services-fra

微软输入法tsf sampleIME 源码分析(转载)

类:CCandidateWindow,候选字窗口CCompositionPricessorEngine,拼写引擎CSampleIME,主程序CStringRange, 一个特殊的字符串类 见于 Sam

64位输入法DLL注 (tsf)方案

微软两种输入法方案XP和XP以前是imm(Input Method Manager)输入方案.xp之后的系统是imm和TSF(Text Service Framework)输入方案.共存. win8

IME输入法编程心得(转载) 1

原文地址:https://www.cnblogs.com/freedomshe/archive/2012/11/30/ime_learning.html自然语言处理的输入法作业成品没有做出来,但不想再

获取输入法坐标

以下是微软TSF输入法取坐标的方法,从里面扒出来的int 取坐标(ITfContext *pContext, TfEditCookie ec, ITfComposition* pRangeCompos

输入法的注册、安装和卸载

注册输入法输入法的安装和普通应用程序有一个大的区别是,除了复制文件到安装目录、做一些必要的设置外,还需要向Windows系统注册这个输入法。我们前期一篇博文 TSF(Text Service Fram

逗比的输入法实现(二):基础概念和常用接口

为什么叫 Meow?因为这是给猫用的输入法。。。目录(一):基本情况(二):基础概念和常用接口(三):整体构架(四):编辑和候选(五):界面管理和无界面模式(六):词库和候选算法(七):皮肤的实现(八