C#下實現空白窗體上中文輸入,可以實現類PS的文字工具
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; } } /// /// 打印文字 /// private void intoText()// { Graphics g = this.CreateGraphics(); g.DrawString(sb.ToString(), font, Brushes.Black, 10, 10); } } }