阅后即焚

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

调用windows的imm32.dll完成窗体接收输入法功能.

代码如下

   /// <summary>
    /// 输入法组件
    /// </summary>
    class ImeComponent
    {
        #region Event
        /// <summary>
        /// 输入文本事件
        /// </summary>
        public delegate void InputTextEvent(string text);
        /// <summary>
        /// 输入文本事件
        /// </summary>
        public event InputTextEvent InputText;
        #endregion

        #region PrivateField
        IntPtr hIMC;
        IntPtr handle;
        private const int WM_IME_SETCONTEXT = 0x0281;
        private const int WM_IME_CHAR = 0x0286;
        private const int WM_CHAR = 0x0102;
        private const int WM_IME_COMPOSITION = 0x010F;
        private const int GCS_RESULTSTR = 0x0800;
        private const int GCS_COMPSTR = 0x0008;
        #endregion

        #region Construction
        public ImeComponent(UserControl control)
        {
            var handle = control.Handle;
            hIMC = ImmGetContext(handle);
            this.handle = handle;
        }
     

      public ImeComponent(Form from)
      {
        var handle = from.Handle;
        hIMC = ImmGetContext(handle);
        this.handle = handle;
      }

#endregion

        #region Method
        /// <summary>
        /// 输入事件
        /// </summary>
        /// <param name="m"></param>
        public void ImmOperation(Message m)
        {
            if (m.Msg == ImeComponent.WM_IME_SETCONTEXT && m.WParam.ToInt32() == 1)
            {
                this.ImmAssociateContext(handle);
            }
            else if (m.Msg == WM_IME_COMPOSITION)
            {
                var res = m.WParam.ToInt32();
                string text = CurrentCompStr(this.handle);
                if (!string.IsNullOrEmpty(text))
                {
                    InputText(text);
                }
            }
            else if (m.Msg == WM_CHAR)
            {
                char inputchar = (char)m.WParam;
                if (inputchar > 31 && inputchar < 127)
                {
                    InputText(inputchar.ToString());
                }
            }
        }
        /// <summary>
        /// 当前输入的字符串流
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        public string CurrentCompStr(IntPtr handle)
        {
            try
            {
                int strLen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, null, 0);
                if (strLen > 0)
                {
                    var buffer = new byte[strLen];
                    ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buffer, strLen);
                    return Encoding.Unicode.GetString(buffer);
                }
                else
                {
                    return string.Empty;
                }
            }
            finally
            {
                ImmReleaseContext(handle, hIMC);
            }
        }
        #endregion

        #region Win Api
        /// <summary>
        /// 建立指定输入环境与窗口之间的关联
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        private IntPtr ImmAssociateContext(IntPtr hWnd)
        {
            return ImeComponent.ImmAssociateContext(hWnd, hIMC);
        }

        [DllImport("imm32.dll")]
        public static extern IntPtr ImmGetContext(IntPtr hWnd);
        [DllImport("Imm32.dll")]
        public static extern bool ImmReleaseContext(IntPtr hWnd, IntPtr hIMC);
        [DllImport("Imm32.dll")]
        private static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        private static extern int ImmCreateContext();
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        private static extern bool ImmDestroyContext(int hImc);
        [DllImport("imm32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SetFocus(IntPtr hWnd);
        [DllImport("Imm32.dll", CharSet = CharSet.Unicode)]
        private static extern int ImmGetCompositionStringW(IntPtr hIMC, int dwIndex, byte[] lpBuf, int dwBufLen);
        [DllImport("imm32.dll")]
        static extern int ImmGetCompositionString(IntPtr hIMC, int dwIndex, StringBuilder lPBuf, int dwBufLen);
        #endregion
    }

此外还需要重构一下窗体或控件的WndProc方法

代码如下:

     /// <summary>
        /// win消息
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (isInitialization)
            {
                this.imeComponent.ImmOperation(m); //输入法
            }
        }

需要注意的是要保证输入法组件在实例化之后才会执行对象的ImmOperation方法.

这样修改之后绑定事件即可接收到键盘输入.

 

水平有限难免有所纰漏,如有错误请留言指出.=_=

posted on 2018-09-24 17:59  阅后即焚  阅读(2510)  评论(2编辑  收藏  举报