文字型窗体域:C#下实现空白窗体上中文输入 可以实现类PS的文字工具来源: 发布时间:星期五, 2009年9月25日 浏览:0次 评论:0
转载自:http://www.cnblogs.com/xiaoshou/archive/2009/09/02/1558696.html
C#下实现空白窗体上中文输入 关键字:类PS的文字工具,中文输入.重复截取中文 最近在研究做一个类PS的文字工具,查了N多的资料,问了N多个人,总算功夫不负有人心.终于给弄出来了.写出来给大家一起讨论.(高手们请多多指点) 在空白窗体上打开输入法,在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);
} } } 0
相关文章读者评论发表评论 |
|