在空白窗體上打開輸入法,在C#裡的空白窗口是無論如何也是打不開輸入法.設 置了this.ImeMode= ImeMode.NoControl也是無法打開輸入法的錄字窗口.去 Microsoft 開發論壇上問了一些問題.感謝周雪峰版主與Riquel_Dong 版主給的 指點.用了API函數: ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);終 於把輸入法給調了出來,它的功能是把輸入與指定的窗口進行關聯.
代碼如 下:
f (m.Msg == WM_IME_SETCONTEXT && m.WParam.ToInt32() == 1)
{
ImmAssociateContext(this.Handle, m_hImc);
}
現在可以調用輸入法了.可是又出現了新的問題. 怎麼樣取得輸入法錄字窗體上的字呢.
當打開輸入法輸入文字時,會發送 WM_IME_CHAR的消息.我們在這個消息下處理下就可以得到漢字了
可以用 IMM的函數: ImmGetCompositionString(IntPtr hIMC, int dwIndex, StringBuilder lpBuf, int dwBufLen);取得錄字窗體上輸入的漢字或者 NUICODE類的字.當然,這裡就不研究別的了.只說漢字問題.
取字的代碼如 下:
case WM_IME_CHAR:
int size = ImmGetCompositionString(m_hImc, GCS_COMPSTR, null, 0);
size += sizeof(Char);
ImmGetCompositionString(m_hImc, GCS_RESULTSTR, str, size);
sb.Append(str.ToString());
MessageBox.Show (str.ToString());
intoText();//打印文字
isShowChina = true;
break;
OK,.好象是大功告成了.測試了一下才發現打印出來的都 是重復的文字.比如輸入”為人民服務”,打印出的卻是”為為人 人民民服服務務”我的天吶,問題出在哪裡呢.
去查了一下MSDN.對 WM_IME_CHAR有這樣的說明:
the WM_IME_CHAR message includes a double-byte character and the application passes this message to DefWindowProc
是不是問題就出在這裡了.是發送消息兩次的問題.
看了一個網上的討論,得出一個解決方案:加上判斷
if (m.WParam.ToInt32() == PM_REMOVE)
{
}
測試.終於 沒有了問題了
代碼帖子上
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsApplication2
{
public partial class UserControl1 : UserControl
{
IntPtr m_hImc;
bool isShowChina = false;
public 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_COMPSTR = 0x0008;
[DllImport ("Imm32.dll")]
public static extern IntPtr ImmGetContext(IntPtr hWnd);
[DllImport ("Imm32.dll")]
public static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
[DllImport("imm32.dll")]
static extern int ImmGetCompositionString(IntPtr hIMC, int dwIndex, StringBuilder lpBuf, int dwBufLen);
private int GCS_RESULTSTR = 0x0800;
private const int HC_ACTION = 0;
private const int PM_REMOVE = 0x0001;
StringBuilder sb = new StringBuilder();
Font font = new Font("宋 體", 14, FontStyle.Regular);
public UserControl1()
{
InitializeComponent();
}
private void UserControl1_Load(object sender, EventArgs e)
{
m_hImc = ImmGetContext (this.Handle);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_IME_SETCONTEXT && m.WParam.ToInt32() == 1)
{
ImmAssociateContext (this.Handle, m_hImc);
}
switch (m.Msg)
{
case WM_CHAR:
KeyEventArgs e = new KeyEventArgs(((Keys)((int)((long)m.WParam))) | ModifierKeys);
char a = (char) e.KeyData; //英文
sb.Append(a);
intoText();
isShowChina = false;
break;
case WM_IME_CHAR:
if (m.WParam.ToInt32() == PM_REMOVE) //如果不 做這個判斷.會打印出重復的中文
{
StringBuilder str = new StringBuilder();
int size = ImmGetCompositionString(m_hImc, GCS_COMPSTR, null, 0);
size += sizeof(Char);
ImmGetCompositionString(m_hImc, GCS_RESULTSTR, str, size);
sb.Append (str.ToString());
MessageBox.Show(str.ToString());
intoText();
isShowChina = true;
}
break;
}
}
/// <summary>
/// 打印文 字
/// </summary>
private void intoText()//
{
Graphics g = this.CreateGraphics();
g.DrawString (sb.ToString(), font, Brushes.Black, 10, 10);
}
}
}