C# 切换(指定)输入法——Windows10,11第二篇

、前言:

上篇文章,介绍了下自己的思路。在个人电脑上,虽然勉强通用,但还时不时地出问题。

这和我的最低需求,还是有不小的差距。

经过对电脑系统,个人需求等因素,进行整合,现推出最新的方法。

二、编程逻辑:

1.将所需求的输入法【搜狗五笔输入法 为例】,设置为系统默认输入法。上一篇中的方法,通用性还是不错的,这里便不是重点介绍的内容。

2.程序打开时,根据当前系统进程的输入法,进行指定输入法切换!

三、BUG问题:

1.个人电脑、网咖(依赖云端服务器类)电脑,两者在开机时,系统加载输入法的方式,有所不同。这是第一个重大影响因素。

2.开机之后,用户在未作出输入法改动时,输入法的指定切换,也会出现不同的情况。这是第二个重大影响因素。

3.windows10、11,输入法的框架问题,和之前的系统有很大的不同。在输入法指定切换时,会产生不小的冲突问题。这是第三个重大影响因素。

四、编程代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        #region 导入user32.dll库文件
        // 导入user32.dll库文件
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetForegroundWindow();

        [DllImport("kernel32.dll")]
        public static extern uint GetCurrentThreadId();
        
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr LoadKeyboardLayout(string pwszKLID, uint Flags);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetKeyboardLayout(uint idThread);


        public const uint KLF_ACTIVATE = 1;
        
        const int KEYEVENTF_EXTENDEDKEY = 0x1;
        const int KEYEVENTF_KEYUP = 0x2;
        const int VK_SHIFT = 0x10;

        const int WM_INPUTLANGCHANGEREQUEST = 0x50;
        const int INPUTLANGCHANGE_FORWARD = 1;

        #endregion

        private void Form1_Load(object sender, EventArgs e)
        {
            //下面两行代码,放在窗口初始化代码的最后,为比较好的位置
            avInput();//执行切换输入法程序
            System.Threading.Thread.Sleep(50);//主线程等待,等待系统反应。
            

        }

        private void avInput()//切换输入法程序
        {
            string sogouKLID = "134481924"; // 搜狗输入法的键盘布局ID
            string spmKLID = "67700740";//简体中文输入法的键盘布局ID
             
            IntPtr foregroundWindow = GetForegroundWindow();// 获取当前前台窗口句柄
            uint currentThreadId = GetCurrentThreadId();// 获取当前线程ID
            IntPtr currentLayout = GetKeyboardLayout(currentThreadId);// 获取当前线程的键盘布局
            if (currentLayout.ToString() == sogouKLID)//系统当前输入法为搜狗【五笔】输入法时,执行的程序
            {
                IntPtr spmLayout = LoadKeyboardLayout(spmKLID, KLF_ACTIVATE);//加载简体中文输入法的键盘布局
                SendMessage(foregroundWindow, WM_INPUTLANGCHANGEREQUEST, spmLayout, IntPtr.Zero);//发送切换输入法的消息
                System.Threading.Thread.Sleep(50);//主线程等待,等待系统反应。
                IntPtr sogouLayout = LoadKeyboardLayout(sogouKLID, KLF_ACTIVATE);//加载搜狗【五笔】输入法的键盘布局
                SendMessage(foregroundWindow, WM_INPUTLANGCHANGEREQUEST, sogouLayout, IntPtr.Zero);//发送切换输入法的消息
                System.Threading.Thread.Sleep(50);//主线程等待,等待系统反应。

                SendMessage(foregroundWindow, WM_INPUTLANGCHANGEREQUEST, sogouLayout, IntPtr.Zero);//发送切换输入法的补充消息
                //【注意!】此行代码为“补充消息”,目的:网咖等依托云端服务器类的电脑系统,需要第二次发送切换消息。
                //这种情况,是搜狗五笔输入法出现的问题。搜狗拼音输入法,没有此问题。这种情况,可以根据实际情况增删!
            }
            else if (currentLayout.ToString() == "67699721")//系统当前输入法为【EN】时,执行的程序
            {
                IntPtr sogouLayout = LoadKeyboardLayout(sogouKLID, KLF_ACTIVATE);//加载搜狗【五笔】输入法的键盘布局
                SendMessage(foregroundWindow, WM_INPUTLANGCHANGEREQUEST, sogouLayout, IntPtr.Zero);//发送切换输入法的消息
                System.Threading.Thread.Sleep(50);//主线程等待,等待系统反应。
                SendMessage(foregroundWindow, WM_INPUTLANGCHANGEREQUEST, sogouLayout, IntPtr.Zero);//发送切换输入法的补充消息
            }
            else//系统当前输入法为其它时,执行的程序
            {
                IntPtr sogouLayout = LoadKeyboardLayout(sogouKLID, KLF_ACTIVATE);//加载搜狗【五笔】输入法的键盘布局
                SendMessage(foregroundWindow, WM_INPUTLANGCHANGEREQUEST, sogouLayout, IntPtr.Zero);//发送切换输入法的消息
            }
        }
    }
}

五、代码解释:

1.本篇代码,重点用到的是系统API。

2.切换程序,是以系统当前输入法的键盘ID,为判断依据。根据任务栏加载的输入法,进行不同情况下,进行不同操作。

3.【EN】模式、【简体中文】、【搜狗五笔输入法】模式、【其它】输入法模式,这四个因素,对于指定切换,有着不小的影响。

4.任务栏【EN】模式:第一次发送切换输入法消息,会将当前线程的输入法,切换到【简体中文】模式,需要再进行一次发送切换消息,作为【补充切换消息】,从而将输入法切换到【搜狗五笔】。(之所以出生这种情况,和系统与搜狗五笔输入法本身,都有一定的关系。别的输入法,部分也会出现此情况。)

5.任务栏【简体中文模式】:绝大部分情况下,不会出现问题。但在个别输入法和系统上,也是会出现,切换到了【EN】模式,这时需要发送【补充切换消息】。

6.任务栏【搜狗五笔】模式:这种情况下,需要将输入法,先切换到【简体中文】模式,再切换到【搜狗五笔】。虽然看起来有点多余操作,但这样操作,可以避免切换到【搜狗五笔】时,输入法的状态为“英文”的BUG。出现这种情况,是因为【搜狗五笔】与【搜狗拼音】在注册中的区分,太过细微。

六、总结:

本篇代码,虽然也有着不小的BUG,但应对大部分情况,还是没有问题。由于本人能力有限,暂时也只能达到此程度。思绪继续整理中,后续还会完善。感谢你看到这里,希望这篇文章,对你的编程有所帮助!