调用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方法.
这样修改之后绑定事件即可接收到键盘输入.
水平有限难免有所纰漏,如有错误请留言指出.=_=