Windows系統帶GUI的程式在使用時最大的困擾之一就是開啟之後輸入方式是輸入法而不是英文數字,特別是在用在工業生產時。網路上可以找到非常多關於如何用win32 api關閉輸入法的文章,但是這些方法在win10和win11有點小問題(win8未知),就是得要用滑鼠點工作列右邊的ENG才能切換回輸入法,雖然有快速鍵alt+shift可以用,但知道的人不多。在win7之前是可以直接ctrl+空白鍵直接切回輸入法,操作的流暢度差了不少。
我另外找到一個較細膩的方法,可以直接控制目標的輸入法狀態。上篇紀錄兩種作法和所有語言都通用的流程(大概),下篇紀錄如何在LabVIEW上實現這些功能。
一般看到關閉輸入法的流程是這樣,先取得hwnd也就是視窗控制碼,可以經由user32.dll的兩個函式之一取得:(1)取得最上層視窗,
HWND GetForegroundWindow();
或(2)取得指定title名稱的視窗(函式結尾A是ANSI,W是unicode)。
HWND FindWindowA(
[in, optional] LPCSTR lpClassName,
[in, optional] LPCSTR lpWindowName
);
接著載入英文鍵盤配置,這邊msdn提到win8後如果目前的進程沒有擁有具有鍵盤焦點的視窗,此函式就不會有任何作用,要先用GetFocus()取得焦點。我用第一種方法得到hwnd沒遇到函式失效,但是全部的視窗鍵盤配置都一起被改變,而不是只有指定hwnd的視窗。
HKL LoadKeyboardLayoutA(
[in] LPCSTR pwszKLID,
[in] UINT Flags
);
最後對hwnd指向的視窗傳送WM_INPUTLANGCHANGEREQUEST指令(對應的機碼是0x0050),把鍵盤配置改成英文(機碼0x0409)。
LRESULT SendMessage(
[in] HWND hWnd,
[in] UINT Msg,
[in] WPARAM wParam,
[in] LPARAM lParam
);
要確認是否切換完成可以用GetKeyboardLayout()來確認。
另一個方法是透過imm32.dll的函式關閉同PID的視窗的輸入法,如果要關其他PID的輸入法會更複雜點,暫時不在我的應用範圍先不管。首先一樣要取得目前視窗的控制碼hwnd,然後取得輸入法控制碼HIMC。
HIMC ImmGetContext(
HWND unnamedParam1
);
然後設定輸入法的狀態。正確的關閉輸入法後工具列輸入法旁的icon會變成"A"或"英"。另外也可以用ImmGetOpenStatus()來取得輸入法狀態,開啟會回傳,關閉回傳0。
BOOL ImmSetOpenStatus(
HIMC unnamedParam1,
BOOL unnamedParam2
);
這個方法在鍵盤配置為日文時也有作用,應該是通用在各種鍵盤配置。