一、前言:
上篇文章,介绍了下自己的思路。在个人电脑上,虽然勉强通用,但还时不时地出问题。
这和我的最低需求,还是有不小的差距。
经过对电脑系统,个人需求等因素,进行整合,现推出最新的方法。
二、编程逻辑:
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。出现这种情况,是因为【搜狗五笔】与【搜狗拼音】在注册中的区分,太过细微。