unity3d屏蔽Windows10輸入法

在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測試可用,其餘系統未經測試

相關文章
相關標籤/搜索