aardio 文档

输入法与键盘状态检测

aardio 提供以下库或函数用于检测输入法与键盘状态:

一. 输入法状态检测原理与规则

我们先了解两个用于表示输入法状态的变量:

1. 基本规则:

2. 中日韩文输入模式:

convMode & 1/*_IME_CMODE_NATIVE*/ 表示开启中日韩文输入模式。_IME_CMODE_NATIVE 还有 _IME_CMODE_CHINESE,_IME_CMODE_JAPANESE,_IME_CMODE_HANGUL 等别名。如果没有这个标志位则表示 0/*_IME_CMODE_ALPHANUMERIC*/ 这个标志位有效,也就是仍为英文输入模式。

开启中日韩文输入模式后:

3. 英文标点全半角状态:

convMode 还有一些其他状态,中文输入法一般用不到。

4. 键盘布局语言:

如果键盘布局返回错误的语言 ID,则检测到的输入法状态也会是错误的。中文输入法打开以后,无论中英输入模式,键盘布局( HKL )的语言 ID 都应是 0x804, 这与操作系统输入法设置中,中文输入法只能自中文键盘中添加的规则一致。

有些老旧的输入法会强行添加「简体中文美式键盘」,这是不妥的,安装这种输入法会导致输入状态与键盘布局错乱。实际上 Windows 10 开始已经移除了这个键盘,应改为「英文美式键盘」。

ImTip 检测输入法的实现源码

二. 输入法状态检测兼容性

至于第三方输入法工具则更为混乱,早年我写过文章,在 ImTip 发布之前网上流传的代码基本都是错的。例如有的开发者看到中文状态下 convMode 是某个数值就以为这个固定的数值就表示中文输入状态,其实这是未经过严谨测试望文生义,别人切换几个状态或者换个输入法你的程序就乱套了。

三. key.ime.state 函数 #

ImTip 检测输入法状态的功能由 aardio 标准库的 key.ime.state 函数提供,此函数的关键源码如下:

namespace key.ime{

    conversionLangIds =  {[0x804] = 0x409;[0x404] = 0x409;[0xC04] = 0x409;[0x1404] = 0x409;[0x412] = 0x409;[0x0411] = 0x409} ;

    state = function(hwnd){
        if(!hwnd) {
            hwnd = ::User32.GetForegroundWindow();
            if(..winex) hwnd = ..winex.getFocus(hwnd,true) : hwnd;
        }

        var opened = getOpenStatus(hwnd);
        var convMode = getConversionMode(hwnd);
        var langId = getCurrentLangIdByHwnd(hwnd);

        if (opened && langId==0x409) opened = false;

        if(convMode === null) return false,,langId;

        var symbolMode = 1/*_IME_SYMBOLMODE_HALFSHAPE*/; 
        if(!opened && (convMode==1 || convMode==0 ) && ! conversionLangIds[langId] ) symbolMode = 0;
        elseif( (convMode & 0x400/*_IME_CMODE_SYMBOL*/) && opened ) symbolMode = 3/*_IME_SYMBOLMODE_SYMBOL*/;
        elseif(convMode & 8/*_IME_CMODE_FULLSHAPE*/) symbolMode = 2/*_IME_SYMBOLMODE_FULLSHAPE*/;
        elseif(convMode & 0x100/*_IME_CMODE_NOCONVERSION*/) opened = false;

        /*
        首个返回值为是否启用输入转换(例如输入中、日、韩等文字),false 为英文输入状态,
        第二个返回值 symbolMode 用一个数值表示标点模式:
        1. 英文半角标点
        2. 英文全角标点
        3. 中文标点
        0. 或 null 已关闭输入转换
        */
        return opened && (convMode & 3/*_IME_CMODE_LANGUAGE*/),symbolMode,langId,convMode;
    }       
}

Markdown 格式