• unity3d屏蔽Windows10输入法


    在win10上,如果安装了某些输入法(比如QQ输入法),会造成unity的键盘事件被输入法捕获而不能触发的情况。只有将输入法切换到英文状态下才能响应键盘事件。

    解决办法有,

    1:用户主动切换输入法,甚至卸载输入法

    2:程序在非输入状态下,屏蔽输入法

    由于方法1在全屏状态下,用户完全不知道是否在输入法劫持中,常常导致以为是程序的bug,所以这里采用方法2

    在unity中,官方并没有提供一个很好的解决方案(Input.imeCompositionMode无效)。所以只能借助win api。

    其中最为重要的API是设置输入法状态:

    [DllImport("imm32.dll")]
    private static extern bool ImmSetOpenStatus(IntPtr himc, bool b);

    其中himc为当前正在输入的窗口的输入法句柄,b为true表示开启,false表示关闭

    himc可以通过另外一个api函数获取

    [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测试可用,其他系统未经测试

    个人博客请访问:http://www.cnblogs.com/CodeGize/
  • 相关阅读:
    用SQL语言操作数据
    用表组织数据
    第一个C#程序
    利用CSS3制作网页动画
    CSS3美化网页元素
    列表、表格与媒体元素
    表单
    HTML5基础
    使用Java编译思想
    Day06:方法 / 猜字母游戏
  • 原文地址:https://www.cnblogs.com/CodeGize/p/5612067.html
Copyright © 2020-2023  润新知