注册 登录
编程论坛 VFP论坛

Win10输入法“中”“英”切换源码(2023.01.14 支持第三方输入法)代码在二楼

kangss 发布于 2023-01-12 18:43, 5477 次点击
只有本站会员才能查看附件,请 登录


代码思路:https://bbs.bccn.net/thread-511088-1-1.html

多键盘布局模式:2个输入法图标
只有本站会员才能查看附件,请 登录


【2023.01.14 支持第三方输入法 代码在二楼】

程序代码:

*****************************************************
* win10输入法([color=#800000]1) &&打开输入法[/color]
* win10输入法([color=#800000]0) &&关闭输入法[/color]
* VFP自身的IMESTATUS([color=#800000]0)对win7有毛病,不支持[/color]
* win10 IME 改为 TFS 模式
* [color=#800000]2023.01.13 增加多键盘布局模式(2个输入法图标)[/color]
*****************************************************
PARAMETERS m._Mode

AGETFILEVERSION(aFile, "ntdll.dll")

IF VAL(aFile(4)) >= 10            && VFP自身的“OS()”在win10中也失灵了
    ******************
    * 判断“中”“英”
    ******************
    *!*    #include <iostream>
    *!*    #include <Windows.h>
    *!*    #pragma comment (lib, "imm32.lib")
    *!*    #define IMC_GETOPENSTATUS 0x0005
    *!*    using namespace std;

    *!*    int main() {
    *!*        while (true) {
    *!*            HWND hIME = ImmGetDefaultIMEWnd(GetForegroundWindow());
    *!*            LRESULT status = SendMessage(hIME, WM_IME_CONTROL, IMC_GETOPENSTATUS, 0);
    *!*            cout << (status ? "Korean" : "English") << endl;
    *!*            Sleep(100);
    *!*        }
    *!*        return 0;
    *!*    }
    #DEFINE WM_IME_CONTROL                0x283
    #DEFINE IMC_GETCONVERSIONMODE        0x0005

    LOCAL m.lnHwnd, m._IME状态    && 0:“英”,否则是“中”或其它

    IF win10鼠标点击切换中英(0) > 1
        DECLARE INTEGER ImmGetContext IN imm32.DLL LONG
        */* DECLARE INTEGER ImmGetOpenStatus IN imm32.DLL LONG
        DECLARE INTEGER ImmSetConversionStatus IN imm32.DLL LONG,LONG iMode,LONG iSentence

        m.lnHwnd = ImmGetContext(_VFP.HWND)
        
*/* m._IME状态 = ImmGetOpenStatus(m._m)
        */* ? IIF(m._IME状态 = 0, "英", "中")
        *!*    中文输入-半角-中文符号    1025
        *!*    中文输入-全角-中文符号    1033
        *!*    中文输入-半角-英文符号    1
        *!*    中文输入-全角-英文符号    9
        *!*    英文输入-半角-中文符号    1024
        *!*    英文输入-全角-中文符号    1032
        *!*    英文输入-半角-英文符号    0
        *!*    英文输入-全角-英文符号    8

        ImmSetConversionStatus(m.lnHwnd, IIF(m._mode = 1,1025, 0), 8)

        CLEAR DLLS ImmSetConversionStatus, ImmGetContext
        RETURN
    ENDIF

    DECLARE INTEGER ImmGetDefaultIMEWnd IN Imm32 LONG
   
*/* DECLARE INTEGER SendMessage IN WIN32API AS "ls_SendMessage" LONG HWND, LONG Msg, LONG wParam, INTEGER
    */* lnHwnd = ImmGetDefaultIMEWnd(_VFP.HWND)        && 输入法会给每个窗口发消息
   
*/* m._IME状态 =  ls_SendMessage(lnHwnd, WM_IME_CONTROL, IMC_GETCONVERSIONMODE, 0)    && m.lcText:任务栏输入指示

    DECLARE INTEGER ImmGetContext IN imm32.DLL LONG
    lnHwnd  = ImmGetContext(_VFP.HWND)
    m._IME状态 = ImmGetOpenStatus(lnHwnd)
    ******************

    IF m._Mode = 0        && 置“英”
        IF m._IME状态 != 0
            win10鼠标点击切换中英()
        ENDIF
    ELSE                && 置“中”
        IF m._IME状态 = 0
            win10鼠标点击切换中英()
        ENDIF
    ENDIF

    CLEAR DLLS "ImmGetDefaultIMEWnd", "ls_SendMessage"
    RETURN
ENDIF

FUNCTION win10鼠标点击切换中英(m._ime_num)
    DECLARE INTEGER FindWindow IN user32 AS "ls_FindWindow" STRING, STRING
    DECLARE INTEGER FindWindowEx IN user32 AS "ls_FindWindowEx" INTEGER, INTEGER, STRING, STRING
    DECLARE INTEGER PostMessage IN user32 AS "ls_PostMessage" INTEGER, INTEGER, INTEGER, INTEGER

    LOCAL m.lnHwnd1, lnHwnd2, m.lnHwnd3, m.lnHwnd4, m.lnHwnd5
    m.lnHwnd1 = ls_FindWindow("Shell_TrayWnd", 0)
    m.lnHwnd2 = ls_FindWindowEx(m.lnHwnd1, 0, "TrayNotifyWnd", NULL)
    m.lnHwnd3 = ls_FindWindowEx(m.lnHwnd2, 0, "TrayInputIndicatorWClass", NULL)
    m.lnHwnd4 = ls_FindWindowEx(m.lnHwnd3, 0, "IMEModeButton", NULL)
    m.lnHwnd5 = ls_FindWindowEx(m.lnHwnd3, 0, "InputIndicatorButton", NULL)    &&

    ************************
    * 检查单键盘、双键盘布局
    ************************
    IF TYPE("_ime_num") = "N"
        LOCAL m._IME布局1, lpRect1, lnWidth1, m._IME布局2, lpRect2, lnWidth2
        lpRect1 = REPLI(CHR(0), 16)
        lpRect2 = REPLI(CHR(0), 16)
        DECLARE SHORT GetWindowRect IN user32 INTEGER HWND, STRING @ lpRect
        GetWindowRect (lnHwnd4, @lpRect1)
        lnWidth1 = CTOB(SUBS(lpRect1,9,4),'4rs') - CTOB(SUBS(lpRect1,1,4),'4rs')
        GetWindowRect (lnHwnd4, @lpRect2)
        lnWidth2 = CTOB(SUBS(lpRect1,9,4),'4rs') - CTOB(SUBS(lpRect2,1,4),'4rs')

        CLEAR DLLS "ls_FindWindow", "ls_FindWindowEx", "ls_PostMessage"

        IF lnWidth1 > 0 AND lnWidth2 > 0
            m._ime_num = 2
        ELSE
            m._ime_num = 1
        ENDIF

        RETURN m._ime_num
    ENDIF
    ************************

    #DEFINE WM_MOUSEMOVE             0x0200
    #DEFINE WM_NCLBUTTONDOWN        0x00A1
    #DEFINE WM_LBUTTONDOWN            0x0201
    #DEFINE WM_LBUTTONUP            0x0202
    #DEFINE MK_LBUTTON                0x0001
    *!* #DEFINE WM_GETTEXT                0x000D

    ls_PostMessage(m.lnHwnd4, WM_LBUTTONDOWN, MK_LBUTTON, 1)        && 按下左键
    ls_PostMessage(m.lnHwnd4, WM_LBUTTONUP, MK_LBUTTON, 1)        && 放开左键

    CLEAR DLLS "ls_FindWindow", "ls_FindWindowEx", "ls_PostMessage"
ENDFUNC



[此贴子已经被作者于2023-1-14 13:26编辑过]

55 回复
#2
kangss2023-01-12 18:50
只有本站会员才能查看附件,请 登录


*!*    中文输入-半角-中文符号    1025                *!*    中文输入-全角-中文符号    1033
*!*    中文输入-半角-英文符号    1                    *!*    中文输入-全角-英文符号    9
*!*    英文输入-半角-中文符号    1024                *!*    英文输入-全角-中文符号    1032
*!*    英文输入-半角-英文符号    0                    *!*    英文输入-全角-英文符号    8
也可以通过发消息“1033”“1032”改变全角半角状态

程序代码:

*****************************************************
* win10输入法([color=#800000]1) &&打开输入法[/color]
* win10输入法([color=#800000]0) &&关闭输入法[/color]
* VFP自身的IMESTATUS([color=#800000]0)对win7有毛病,不支持[/color]
* win10 IME 改为 TFS 模式
* [color=#800000]2023.01.13 增加多键盘布局模式(2个输入法图标)[/color]
* [color=#800000]2023.01.14 取消判断多键盘布局,支持第三方输入法[/color]
*****************************************************
PARAMETERS m._Mode

AGETFILEVERSION(aFile, "ntdll.dll")

IF VAL(aFile(4)) >= 10            && VFP自身的“OS()”在win10中也失灵了
    IF win10鼠标点击切换中英(0) <> m._Mode
        win10鼠标点击切换中英(1)
    ENDIF

    RETURN
ENDIF

FUNCTION win10鼠标点击切换中英(m._ime_num)
    m._ime_num = EVL(m._ime_num, 0)

    DECLARE INTEGER SendMessage IN user32 AS "ls_SendMessage" LONG HWND, LONG Msg, LONG wParam, INTEGER

    ******************
    * 判断“中”“英”
    ******************
    IF m._ime_num = 0
        #DEFINE WM_IME_CONTROL                0x283
        #DEFINE IMC_GETCONVERSIONMODE        0x0005
        #DEFINE KLF_ACTIVATE                0x00000001
        #DEFINE KLF_SETFORPROCESS            0x00000100

        DECLARE INTEGER ImmGetDefaultIMEWnd IN Imm32 LONG
        DECLARE LONG LoadKeyboardLayout IN User32 STRING@, LONG
        DECLARE LONG ActivateKeyboardLayout IN User32 LONG,LONG

        m.lnHwnd0 = ImmGetDefaultIMEWnd(_VFP.HWND)

        hLayout = LoadKeyboardLayout("00000804", 1)            && 切换为中文输入法
        ActivateKeyboardLayout(hLayout, KLF_SETFORPROCESS)

        LOCAL m._请求
        m._请求 = ls_SendMessage(m.lnHwnd0, WM_IME_CONTROL, 1, 1)

        */* ? IIF(m._IME状态 = 0, "英", "中")
        *!*    中文输入-半角-中文符号    1025                *!*    中文输入-全角-中文符号    1033
        *!*    中文输入-半角-英文符号    1                    *!*    中文输入-全角-英文符号    9
        *!*    英文输入-半角-中文符号    1024                *!*    英文输入-全角-中文符号    1032
        *!*    英文输入-半角-英文符号    0                    *!*    英文输入-全角-英文符号    8
        
        RETURN IIF(m._请求 = 0 OR m._请求 = 8 OR m._请求 = 1024 OR m._请求 = 1032, 0, 1)
    ENDIF
    ******************

    DECLARE INTEGER FindWindow IN user32 AS "ls_FindWindow" STRING, STRING
    DECLARE INTEGER FindWindowEx IN user32 AS "ls_FindWindowEx" INTEGER, INTEGER, STRING, STRING
    DECLARE INTEGER PostMessage IN user32 AS "ls_PostMessage" INTEGER, INTEGER, INTEGER, INTEGER

    LOCAL m.lnHwnd1, lnHwnd2, m.lnHwnd3, m.lnHwnd4
    m.lnHwnd1 = ls_FindWindow("Shell_TrayWnd", 0)
    m.lnHwnd2 = ls_FindWindowEx(m.lnHwnd1, 0, "TrayNotifyWnd", NULL)
    m.lnHwnd3 = ls_FindWindowEx(m.lnHwnd2, 0, "TrayInputIndicatorWClass", NULL)
    m.lnHwnd4 = ls_FindWindowEx(m.lnHwnd3, 0, "IMEModeButton", NULL)

    #DEFINE WM_MOUSEMOVE             0x0200
    #DEFINE WM_NCLBUTTONDOWN        0x00A1
    #DEFINE WM_LBUTTONDOWN            0x0201
    #DEFINE WM_LBUTTONUP            0x0202
    #DEFINE MK_LBUTTON                0x0001
    *!* #DEFINE WM_GETTEXT                0x000D

    ls_PostMessage(m.lnHwnd4, WM_LBUTTONDOWN, MK_LBUTTON, 1)        && 按下左键
    ls_PostMessage(m.lnHwnd4, WM_LBUTTONUP, MK_LBUTTON, 1)        && 放开左键

    CLEAR DLLS "ls_FindWindow", "ls_FindWindowEx", "ls_PostMessage"
ENDFUNC


[此贴子已经被作者于2023-1-14 13:46编辑过]

#3
kangss2023-01-12 19:02
有人说怎么不模拟“CTRL+空格键”或“Shift”?
如果客户修改了快捷键,会导致失灵,没有点击输入法图标效果稳妥。

#4
吹水佬2023-01-12 19:09
对第三方的输入法有效吗?
#5
nbwww2023-01-12 19:12
#6
csyx2023-01-12 19:15
以下是引用kangss在2023-1-12 18:50:56的发言:

客户电脑上的win10输入密码的时候,总是默认中文,实在是不得劲
看到论坛上有人问了,就想着顺便搞搞

测试有效,顺便请教:
1. 此函数在其他 windows 版本是否也可用?条件所限,本本只装了 win10,有点懒,不想装虚拟机
2. 其他输入法是否也有效?我只装了搜狗输入法
3. 是否有办法判断全角/半角状态?部分脑残和年纪偏大且被迫使用电脑工作人士,教不会!特别在输入登录密码时,狂抓!
#7
kangss2023-01-12 19:26
以下是引用csyx在2023-1-12 19:15:04的发言:


测试有效,顺便请教:
1. 此函数在其他 windows 版本是否也可用?条件所限,本本只装了 win10,有点懒,不想装虚拟机
2. 其他输入法是否也有效?我只装了搜狗输入法
3. 是否有办法判断全角/半角状态?部分脑残和年纪偏大且被迫使用电脑工作人士,教不会!特别在输入登录密码时,狂抓!


这个代码是给输入法发消息,获取“中”“英”状态,再模拟鼠标点击输入法改变“中”“英”状态

是否有办法判断全角/半角状态,这个没研究过,感觉应该可以
#8
nbwww2023-01-12 19:31
经测试 WIN10  微软拼音   0是乒乓键    1无效
#9
csyx2023-01-12 19:34
以下是引用kangss在2023-1-12 19:26:46的发言:
这个代码是给输入法发消息,获取“中”“英”状态,再模拟鼠标点击输入法改变“中”“英”状态

感谢回复!
刚加装了微软拼音输入法(Office2010附带的),? win10输入法(1) 未切换到拼音状态,请问是用法错误还是函数实现原理所限?
#10
nbwww2023-01-12 19:36
以下是引用csyx在2023-1-12 19:34:07的发言:


感谢回复!
刚加装了微软拼音输入法(Office2010附带的),? win10输入法(1) 未切换到拼音状态,请问是用法错误还是函数实现原理所限?

win10输入法(0)   可以切回
#11
csyx2023-01-12 19:37
以下是引用nbwww在2023-1-12 19:31:22的发言:
经测试 WIN10  微软拼音   0是乒乓键    1无效

确实,传参数0可实现循环切换,1无效
#12
kangss2023-01-12 19:43
以下是引用nbwww在2023-1-12 19:31:22的发言:

经测试 WIN10  微软拼音   0是乒乓键    1无效

这段代码判断都是win10的“中”“英”状态,不是“微软拼音”,是:中文(简体)输入法。

#13
kangss2023-01-12 19:46
以下是引用csyx在2023-1-12 19:34:07的发言:
感谢回复!
刚加装了微软拼音输入法(Office2010附带的),? win10输入法(1) 未切换到拼音状态,请问是用法错误还是函数实现原理所限?

代码是针对“中文(简体)输入法”的,没有判断“微软拼音输入法”

只有本站会员才能查看附件,请 登录
#14
kangss2023-01-12 19:52
回复 6楼 csyx
此函数在其他 windows 版本是否也可用?

1、VFP自带的函数支持XP
2、win7用版主的代码
3、win10用这个先凑合着
#15
kangss2023-01-12 19:56
虚拟键为啥不用 keybd_event?
个人认为 exe 里面有 keybd_event,各种杀毒软件最喜欢拦截,说是木马
SendMessage PostMessage 一般不会
#16
kangss2023-01-12 20:05
以下是引用吹水佬在2023-1-12 19:09:53的发言:

对第三方的输入法有效吗?


搜狗输入法自动会根据win10的“中”“英”状态,自动变

这个代码是单键盘布局模式。多键盘布局模式(就是右下角输入法有 2 个输入法状态图标),明天试试看。
#17
kangss2023-01-12 20:07
以下是引用csyx在2023-1-12 19:34:07的发言:


感谢回复!
刚加装了微软拼音输入法(Office2010附带的),? win10输入法(1) 未切换到拼音状态,请问是用法错误还是函数实现原理所限?

你这个应该是跟多键盘布局模式(就是右下角输入法有 2 个输入法状态图标)有关
#18
csyx2023-01-12 20:15
跟踪了一下:
切换到搜狗拼音时,WM_IME_CONTROL, IMC_GETCONVERSIONMODE 消息可正确返回 中(1)/英(0)
切换到微软拼音时,m._IME状态 始终为 0
看来是微软拼音未实现/不响应此消息

又:------------------------------------------------------
楼主代码中常数定义似乎和网上查到不同,我查到的是这样:
    #DEFINE IMC_GETCONVERSIONMODE        0x0001
    #DEFINE IMC_SETCONVERSIONMODE        0x0002
    #DEFINE IMC_GETOPENSTATUS            0x0005
MSDN 上说这些常数在 imm.h 中,但我查了这个头文件,没有,几个以 IMC_ 开头的第一个就到 0x0007 了

我用网上查到的这个常数试了一下: SendMessage(lnHwnd, 0x283, 1, 0)
无论是切换到搜狗还微软拼音,均能正确返回中/英文状态: 0 或 1025,对咱们来说,基本可认为就是 英 or 中,也就是取状态没问题
实际的消息返回值是一个组合值,可用 vfp 的 bittest 函数测试这些位,例如,搜狗输入法
bit0 - 0(英文)1(非英文),bit3 - 是否全角,bit10 - 是否中文标点
至于微软拼音,惭愧,实在不会用,居然不知道如何输入全角符号和英文标点 ,留给受虐狂用吧,咱是不考虑它了。要做成一个用来替代 IMESTATUS(无参数) 的函数,还需验证更多的常用输入法 。。。。

不过,如果试图用 SendMessage(lnHwnd, 0x283, 2, 0/1025) 来设置中英文状态,则微软拼音成功,搜狗失败
也许搜狗已抛弃 IME,只支持 TSF 了

这样一来,剩下的事情就是选取最合适的设置输入法方式了
楼主的模拟鼠标点击方式适用于搜狗输入法,估计稍加修改也可用于大多数流行的输入法
模拟快捷键的方式暂只测试了搜狗和微软拼音,都没问题
咱也不用其他输入法,只知道搜狗是用 shift 切换(很久以前用过的紫光好像也是),其他流行输入法有哪些快捷键就不清楚了


[此贴子已经被作者于2023-1-13 03:46编辑过]

#19
iswith2023-01-12 20:22
以下是引用kangss在2023-1-12 19:56:37的发言:

虚拟键为啥不用 keybd_event?
个人认为 exe 里面有 keybd_event,各种杀毒软件最喜欢拦截,说是木马
SendMessage PostMessage 一般不会

keybd_event我就是调不起来,各种杀毒软件又没有提示拦截信息,一头大,找不到原因。。。
#20
nbwww2023-01-12 21:25
回复 19楼 iswith
DECLARE Long keybd_event IN user32 long,long,long,long
    keybd_event(16, 0, 0, 0)   &&模拟按下SHIFT
    keybd_event(16,0,2,0)    &&放开SHIFT   

不行吗?
#21
吹水佬2023-01-13 08:40
回复 16楼 kangss
过去的IME架构因安全问题被废(输入法文件是IME,实质是DLL)
现在的TSF是基于COM(Text Services Framework)接口,IME的API基本都无效。
TSF有权限问题的。

[此贴子已经被作者于2023-1-13 08:41编辑过]

#22
easyppt2023-01-13 09:11
点赞,为楼主喝彩,各位大神威武!
#23
laowan0012023-01-13 10:03
回复 楼主 kangss
测试未成功
环境 win10 VFP9SP2 搜狗五笔输入法
 m._IME状态 = ls_SendMessage(lnHwnd, WM_IME_CONTROL, IMC_GETCONVERSIONMODE, 0)    && m.lcText:任务栏输入指示
 不管是中文还是英文,m._IME状态的值总是0
是输入法的问题吗?
另:屏幕的右下角是没有“中”显示的(不是运行这个程序后变化的,是之前已经不显示了,跟这个有关系吗?)
#24
iswith2023-01-13 12:21
以下是引用吹水佬在2023-1-13 08:40:40的发言:

过去的IME架构因安全问题被废(输入法文件是IME,实质是DLL)
现在的TSF是基于COM(Text Services Framework)接口,IME的API基本都无效。
TSF有权限问题的。

InputMethod 你觉它他无效?
#25
nbwww2023-01-13 12:37
以下是引用laowan001在2023-1-13 10:03:12的发言:

测试未成功
环境 win10 VFP9SP2 搜狗五笔输入法
 m._IME状态 = ls_SendMessage(lnHwnd, WM_IME_CONTROL, IMC_GETCONVERSIONMODE, 0)    && m.lcText:任务栏输入指示
 不管是中文还是英文,m._IME状态的值总是0
是输入法的问题吗?
另:屏幕的右下角是没有“中”显示的(不是运行这个程序后变化的,是之前已经不显示了,跟这个有关系吗?)


同样的环境  我是成功了  我有显示输入法状态
#26
laowan0012023-01-13 13:30
以下是引用nbwww在2023-1-13 12:37:36的发言:



同样的环境  我是成功了  我有显示输入法状态

看来跟输入法状态有关了
#27
laowan0012023-01-13 14:10
以下是引用nbwww在2023-1-13 12:37:36的发言:



同样的环境  我是成功了  我有显示输入法状态

您的输入法是 搜狗五笔输入法?
#28
laowan0012023-01-13 14:11
现在有输入法状态了,但m._IME状态总是0
m._IME状态 = ls_SendMessage(lnHwnd, WM_IME_CONTROL, IMC_GETCONVERSIONMODE, 0)    && m.lcText:任务栏输入指示
#29
kangss2023-01-13 14:19
以下是引用laowan001在2023-1-13 14:11:47的发言:

现在有输入法状态了,但m._IME状态总是0
m._IME状态 = ls_SendMessage(lnHwnd, WM_IME_CONTROL, IMC_GETCONVERSIONMODE, 0)    && m.lcText:任务栏输入指示

试试 2023.01.13 增加多键盘布局模式(2个输入法图标)
#30
nbwww2023-01-13 14:26
以下是引用laowan001在2023-1-13 14:10:19的发言:


您的输入法是 搜狗五笔输入法?

是的  搜狗五笔
#31
kangss2023-01-13 14:32
以下是引用csyx在2023-1-12 19:15:04的发言:


测试有效,顺便请教:
1. 此函数在其他 windows 版本是否也可用?条件所限,本本只装了 win10,有点懒,不想装虚拟机
2. 其他输入法是否也有效?我只装了搜狗输入法
3. 是否有办法判断全角/半角状态?部分脑残和年纪偏大且被迫使用电脑工作人士,教不会!特别在输入登录密码时,狂抓!


2023.01.13 增加多键盘布局模式(2个输入法图标)

多键盘布局模式,可以设置半角全角
#32
nbwww2023-01-13 14:33
以下是引用kangss在2023-1-13 14:19:07的发言:


试试 2023.01.13 增加多键盘布局模式(2个输入法图标)



用这个版本测试 搜狗五笔 失效      微软拼音成功
#33
kangss2023-01-13 14:44
以下是引用nbwww在2023-1-13 14:33:27的发言:




用这个版本测试 搜狗五笔 失效      微软拼音成功

单键盘布局模式下:第三方输入法没问题
双键盘布局模式下:第三方输入法,应该还有些BUG。代码只能驱动MS自己的,搜狗等第三放无效


[此贴子已经被作者于2023-1-13 14:52编辑过]

#34
laowan0012023-01-13 15:08
试试 2023.01.13 增加多键盘布局模式(2个输入法图标)


用这个版本测试 搜狗五笔 无效 微软拼音成功
#35
csyx2023-01-13 23:46
装了几种流行的输入法测试,基本可以说,用这些 IMC_* 消息非常的不靠谱!
我测试的结果是:搜狗、QQ、微软 的输入法,用下面代码判断【中/英】文输入状态没问题
程序代码:
Declare Long ImmGetDefaultIMEWnd in Imm32 Long
Declare Long SendMessage in win32api Long, long, long, long
m.hWnd = ImmGetDefaultIMEWnd(Application.hWnd)
m.nStatus = SendMessage(m.hWnd, 0x283, 1, 0)
? Bittest(status, 0)

但是,如果是其他流行的输入法,像极点五笔、万能五笔等便完全失效。准确判断都做不到,用什么方法切换输入状态也就不用考虑了。

所以,感觉还是用切换中英文 KeyboardLayout 可靠点
程序代码:
? '关闭输入法'
IMEstatus2(0)
Wait '按任意键切换回中文输入法 ...'
IMEstatus2(1)

Function IMEstatus2(onoff)
    If Pcount() < 1
        Return .f.
    EndIf
    m.onoff = Cast(m.onoff as I)
    If m.onoff == 0
        Declare Long LoadKeyboardLayout in win32api String, Long
        LoadKeyboardLayout('00000409', 1)
    Else
#IF .F.        && 两种方法都行
        Declare Long LoadKeyboardLayout in win32api String, Long
        LoadKeyboardLayout('00000804', 1)
#ELSE        && 我选择卸载 ENG
        Declare Long UnloadKeyboardLayout in win32api Long
        UnloadKeyboardLayout(0x00000409)
#ENDIF
    EndIf
EndFunc
#36
nbwww2023-01-14 11:24
以下是引用csyx在2023-1-13 23:46:56的发言:

装了几种流行的输入法测试,基本可以说,用这些 IMC_* 消息非常的不靠谱!
我测试的结果是:搜狗、QQ、微软 的输入法,用下面代码判断【中/英】文输入状态没问题
Declare Long ImmGetDefaultIMEWnd in Imm32 Long
Declare Long SendMessage in win32api Long, long, long, long
m.hWnd = ImmGetDefaultIMEWnd(Application.hWnd)
m.nStatus = SendMessage(m.hWnd, 0x283, 1, 0)
? Bittest(status, 0)
但是,如果是其他流行的输入法,像极点五笔、万能五笔等便完全失效。准确判断都做不到,用什么方法切换输入状态也就不用考虑了。

所以,感觉还是用切换中英文 KeyboardLayout 可靠点
? '关闭输入法'
IMEstatus2(0)
Wait '按任意键切换回中文输入法 ...'
IMEstatus2(1)

Function IMEstatus2(onoff)
    If Pcount() < 1
        Return .f.
    EndIf
    m.onoff = Cast(m.onoff as I)
    If m.onoff == 0
        Declare Long LoadKeyboardLayout in win32api String, Long
        LoadKeyboardLayout('00000409', 1)
    Else
#IF .F.        && 两种方法都行
        Declare Long LoadKeyboardLayout in win32api String, Long
        LoadKeyboardLayout('00000804', 1)
#ELSE        && 我选择卸载 ENG
        Declare Long UnloadKeyboardLayout in win32api Long
        UnloadKeyboardLayout(0x00000409)
#ENDIF
    EndIf
EndFunc

如果安装了ENG键盘的话切不回中文输入法,可以切到英文
#37
kangss2023-01-14 12:29
回复 36楼 nbwww
2022.01.14 支持第三方输入法,代码在二楼。
#38
kangss2023-01-14 12:29
以下是引用laowan001在2023-1-13 15:08:39的发言:

试试 2023.01.13 增加多键盘布局模式(2个输入法图标)

用这个版本测试 搜狗五笔 无效 微软拼音成功

2022.01.14 支持第三方输入法,代码在二楼。
#39
kangss2023-01-14 12:30
以下是引用laowan001在2023-1-13 10:03:12的发言:

测试未成功
环境 win10 VFP9SP2 搜狗五笔输入法
 m._IME状态 = ls_SendMessage(lnHwnd, WM_IME_CONTROL, IMC_GETCONVERSIONMODE, 0)    && m.lcText:任务栏输入指示
 不管是中文还是英文,m._IME状态的值总是0
是输入法的问题吗?
另:屏幕的右下角是没有“中”显示的(不是运行这个程序后变化的,是之前已经不显示了,跟这个有关系吗?)

2022.01.14 支持第三方输入法,代码在二楼。
#40
csyx2023-01-14 12:48
以下是引用nbwww在2023-1-14 11:24:53的发言:
如果安装了ENG键盘的话切不回中文输入法,可以切到英文

我这是没问题
只有本站会员才能查看附件,请 登录
#41
kangss2023-01-14 12:59
以下是引用csyx在2023-1-14 12:48:01的发言:


我这是没问题

你的是切换输入法,当切换到ENG键盘布局时,想再按快捷键输入中文可能不太方便了。
我的是切换开关“中”“英”输入法状态。就是输入密码等地方自动切换到“英”,输入品名等需要输入汉字的地方,自动切换到“中”
2个不一样。
#42
csyx2023-01-14 13:31
以下是引用kangss在2023-1-14 12:59:00的发言:
你的是切换输入法,当切换到ENG键盘布局时,想再按快捷键输入中文可能不太方便了。
我的是切换开关“中”“英”输入法状态。就是输入密码等地方自动切换到“英”,输入品名等需要输入汉字的地方,自动切换到“中”
2个不一样。

这我知道,在35楼说明了原因
2022.01.14版这种方法在用户的输入法为万能拼音、极点五笔(它们的用户也不在少数)时是不起作用的,这些输入法的 ImmGetOpenStatus(lnHwnd) 永远返回 1,从而无法判断当前中文输入法是处于中文还是英文输入状态,如果仅考虑使用 搜狗、QQ、微软 输入法的用户可以使用此方案

至于切换到 ENG 时快捷键失效,这倒正常,任何线程同一时刻只允许有一个活动键盘布局,激活 ENG 键盘布局后中文键盘就被停用,而 ENG 键盘是不会处理其他键盘布局的快捷键的。

鉴于主要目的是想在进入某文本/密码框时避免用户输入汉字、全角字符等需求,切换中文键盘的快捷键是否有效就不重要了,只要在丢失焦点后能用函数重新激活中文键盘即可,而禁止输入中文或全角字符,且兼容各种输入法就成了首要需求,因此我还是倾向于使用激活 ENG 键盘的方法
我以前的方法是给文本/密码框设置 InputMask 来避免,可总是存在一些脑残/年龄较大的用户,且数量不在少数,一旦按下键盘而屏幕上没有反应,就吵吵软件有问题,远程过去才发现是输入法状态不对,更让人抓狂的是同样一个坑下次还能再掉进去,所以只能采取禁用中文输入法的方式


[此贴子已经被作者于2023-1-14 13:44编辑过]

#43
nbwww2023-01-14 14:30
2022.01.14版  微软拼音   搜狗五笔  ENG  三种测试成功
#44
kangss2023-01-14 15:00
以下是引用nbwww在2023-1-14 14:30:29的发言:

2022.01.14版  微软拼音   搜狗五笔  ENG  三种测试成功

是2023.01.14,写错了
#45
nbwww2023-01-14 15:05


[此贴子已经被作者于2023-1-14 15:07编辑过]

#46
kangss2023-01-14 15:26
回复 45楼 nbwww
是我写错导致的,对2022念念不忘,不知不觉又过了一年
#47
kangss2023-01-14 16:57
以下是引用csyx在2023-1-12 20:15:47的发言:

跟踪了一下:
切换到搜狗拼音时,WM_IME_CONTROL, IMC_GETCONVERSIONMODE 消息可正确返回 中(1)/英(0)
切换到微软拼音时,m._IME状态 始终为 0
看来是微软拼音未实现/不响应此消息

又:------------------------------------------------------
楼主代码中常数定义似乎和网上查到不同,我查到的是这样:
    #DEFINE IMC_GETCONVERSIONMODE        0x0001
    #DEFINE IMC_SETCONVERSIONMODE        0x0002
    #DEFINE IMC_GETOPENSTATUS            0x0005
MSDN 上说这些常数在 imm.h 中,但我查了这个头文件,没有,几个以 IMC_ 开头的第一个就到 0x0007 了

我用网上查到的这个常数试了一下: SendMessage(lnHwnd, 0x283, 1, 0)
无论是切换到搜狗还微软拼音,均能正确返回中/英文状态: 0 或 1025,对咱们来说,基本可认为就是 英 or 中,也就是取状态没问题
实际的消息返回值是一个组合值,可用 vfp 的 bittest 函数测试这些位,例如,搜狗输入法
bit0 - 0(英文)1(非英文),bit3 - 是否全角,bit10 - 是否中文标点
至于微软拼音,惭愧,实在不会用,居然不知道如何输入全角符号和英文标点 ,留给受虐狂用吧,咱是不考虑它了。要做成一个用来替代 IMESTATUS(无参数) 的函数,还需验证更多的常用输入法 。。。。

不过,如果试图用 SendMessage(lnHwnd, 0x283, 2, 0/1025) 来设置中英文状态,则微软拼音成功,搜狗失败
也许搜狗已抛弃 IME,只支持 TSF 了

这样一来,剩下的事情就是选取最合适的设置输入法方式了
楼主的模拟鼠标点击方式适用于搜狗输入法,估计稍加修改也可用于大多数流行的输入法
模拟快捷键的方式暂只测试了搜狗和微软拼音,都没问题
咱也不用其他输入法,只知道搜狗是用 shift 切换(很久以前用过的紫光好像也是),其他流行输入法有哪些快捷键就不清楚了


消息模式,需要发送2个“0x0006”“0x0002”,可改变“中”“英”“全角/半角”状态,支持第三方输入法

#DEFINE IMC_SETCONVERSIONMODE        0x0002
#DEFINE IMC_GETSENTENCEMODE            0x0003
#DEFINE IMC_SETSENTENCEMODE            0x0004
#DEFINE IMC_GETOPENSTATUS            0x0005
#DEFINE IMC_SETOPENSTATUS            0x0006
#DEFINE IMC_SETCANDIDATEPOS            0x0008
#DEFINE IMC_SETCOMPOSITIONFONT        0x000A
#DEFINE IMC_SETSTATUSWINDOWPOS        0x0010
#DEFINE IMC_SETCOMPOSITIONWINDOW    0x000C
#DEFINE IMC_GETSTATUSWINDOWPOS        0x000F
#DEFINE IMC_OPENSTATUSWINDOW        0x0022

SendMessage(lnHwnd, WM_IME_CONTROL, IMC_SETOPENSTATUS, 0/1025)
SendMessage(lnHwnd, WM_IME_CONTROL, IMC_SETCONVERSIONMODE, 0/1025)

#48
吹水佬2023-01-15 16:21
可以了解一下TSF,官方参考资料:
https://learn.
#49
吹水佬2023-01-17 11:34
试试这样:
只有本站会员才能查看附件,请 登录

程序代码:

DECLARE long EnumEnabledLayoutOrTip IN input string@,string@,string@,string@,long
DECLARE long InstallLayoutOrTip     IN input string,long
of = CREATEOBJECT("form1")
of.show(1)
RETURN

DEFINE CLASS form1 as Form
    width=520
    height=280
    AllowOutput=0
    AutoCenter=1
    ADD OBJECT label1 as label WITH left=10,top=10,autosize=1,caption="KLID or TIP profile for string"
    ADD OBJECT idList as listbox WITH left=10,top=30,width=600,height=200,MultiSelect=1
    ADD OBJECT cmd as commandbutton WITH left=10,top=240,width=60,height=24,caption="确定"
    ADD OBJECT label2 as label WITH left=70,top=246,autosize=1,caption="(输入法选择,选定启用的ID,未选的禁用)"
   
    PROCEDURE init
        aCount = EnumEnabledLayoutOrTip(NULL, NULL, NULL, NULL, 0)
        lotp   = REPLICATE(0h00, aCount*584)
        aCount = EnumEnabledLayoutOrTip(NULL, NULL, NULL, @lotp, LEN(lotp))
        j = 1
        FOR i=1 TO aCount
            id = STRCONV(SUBSTR(lotp,j+64,260), 6)
            id = LEFT(id, AT(0h00,id)-1)
            this.idList.AddItem(id)
            j = j + 584
        ENDFOR
        this.idList.ListIndex = 1
    ENDPROC
   
    PROCEDURE Destroy
        FOR i=1 TO thisform.idList.listcount
            InstallLayoutOrTip(STRCONV(thisform.idList.List(i)+0h00,5), 2)
        ENDFOR
    ENDPROC

    PROCEDURE cmd.click
        FOR i=1 TO thisform.idList.listcount
            nFlags = IIF(thisform.idList.Selected(i), 2, 1)
            InstallLayoutOrTip(STRCONV(thisform.idList.List(i)+0h00,5), nFlags)
        ENDFOR
    ENDPROC
ENDDEFINE

#50
吹水佬2023-01-17 20:22
可以用 SetDefaultLayoutOrTip 切换当前输入法

声明:
DECLARE long SetDefaultLayoutOrTip IN input string,long

代码:
idList = thisform.idList
SetDefaultLayoutOrTip(STRCONV(idList.List(idList.listIndex)+0h00,5), 2)

#51
吹水佬2023-01-25 10:00
以下是引用iswith在2023-1-13 12:21:30的发言:


InputMethod 你觉它他无效?


IME架构被废意思是以前的IME框架模式不用,改用TSF框架模式,并非说废除了IME。
IME框架是IME与用户应用直接互通的,TSF框架是在IME与用户应用之间加入TSF管理层,大概意思是IME与用户应用是由TSF来调度。
所以,IME的API有好多都变质了,VFP调用IME的功能失效原因也如此。


[此贴子已经被作者于2023-1-25 10:04编辑过]

12