調用windows的imm32.dll完成窗體接收輸入法功能. 代碼如下 public ImeComponent(Form from) { var handle = from.Handle; hIMC = ImmGetContext(handle); this.handle = handle; } ...
調用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方法.
這樣修改之後綁定事件即可接收到鍵盤輸入.
水平有限難免有所紕漏,如有錯誤請留言指出.=_=