在win10上,若是安裝了某些輸入法(好比QQ輸入法),會形成unity的鍵盤事件被輸入法捕獲而不能觸發的狀況。只有將輸入法切換到英文狀態下才能響應鍵盤事件。api
解決辦法有,緩存
1:用戶主動切換輸入法,甚至卸載輸入法函數
2:程序在非輸入狀態下,屏蔽輸入法測試
因爲方法1在全屏狀態下,用戶徹底不知道是否在輸入法劫持中,經常致使覺得是程序的bug,因此這裏採用方法2ui
在unity中,官方並無提供一個很好的解決方案(Input.imeCompositionMode無效)。因此只能藉助win api。this
其中最爲重要的API是設置輸入法狀態:spa
[DllImport("imm32.dll")]
private static extern bool ImmSetOpenStatus(IntPtr himc, bool b);.net
其中himc爲當前正在輸入的窗口的輸入法句柄,b爲true表示開啓,false表示關閉code
himc能夠經過另一個api函數獲取blog
[DllImport("imm32.dll")]
private static extern IntPtr ImmGetContext(IntPtr hwnd);
其中,hwnd爲程序窗口的句柄
該值的獲取方式能夠參考:http://blog.csdn.net/linkrules/article/details/50420797
整個代碼以下:
using System; using System.Diagnostics; using System.Runtime.InteropServices; public class Win32Help { private delegate bool Wndenumproc(IntPtr hwnd, uint lParam); [DllImport("user32.dll", SetLastError = true)] private static extern bool EnumWindows(Wndenumproc lpEnumFunc, uint lParam); [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr GetParent(IntPtr hWnd); [DllImport("user32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref uint lpdwProcessId); [DllImport("kernel32.dll")] private static extern void SetLastError(uint dwErrCode); /// <summary> /// 獲取當前進程的窗口句柄 /// </summary> /// <returns></returns> public static IntPtr GetProcessWnd() { var ptrWnd = IntPtr.Zero; var pid = (uint)Process.GetCurrentProcess().Id; // 當前進程 ID var bResult = EnumWindows(delegate (IntPtr hwnd, uint lParam) { uint id = 0; if (GetParent(hwnd) != IntPtr.Zero) return true; GetWindowThreadProcessId(hwnd, ref id); if (id != lParam) return true; ptrWnd = hwnd; // 把句柄緩存起來 SetLastError(0); // 設置無錯誤 return false; // 返回 false 以終止枚舉窗口 }, pid); return (!bResult && Marshal.GetLastWin32Error() == 0) ? ptrWnd : IntPtr.Zero; } [DllImport("imm32.dll")] private static extern IntPtr ImmGetContext(IntPtr hwnd); [DllImport("imm32.dll")] private static extern bool ImmGetOpenStatus(IntPtr himc); [DllImport("imm32.dll")] private static extern bool ImmSetOpenStatus(IntPtr himc, bool b); /// <summary> /// 設置輸入法狀態 /// </summary> /// <param name="tf"></param> public static void SetImeEnable(bool tf) { var handle = GetProcessWnd(); var hIme = ImmGetContext(handle); ImmSetOpenStatus(hIme, tf); } /// <summary> /// 獲取輸入法狀態 /// </summary> /// <returns></returns> public bool GetImeStatus() { var handle = GetProcessWnd(); var hIme = ImmGetContext(handle); return ImmGetOpenStatus(hIme); } }
而後在程序中可使用Win32Help.SetImeEnable(false)的方法來屏蔽輸入法,好比:
using UnityEngine;
public class InputTest : MonoBehaviour { // Use this for initialization protected void Start() { Win32Help.SetImeEnable(false); } // Update is called once per frame protected void Update() { if (Input.GetKey(KeyCode.A)) { Debug.Log("AAAAAAAAAAAs"); } } }
注意:只對Windows系統有效,Win10測試可用,其餘系統未經測試