C#下實現空白窗體上中文輸入,可以實現類PS的文字工具

作者: 小獸  來源: 博客園  發布時間: 2009-09-03 09:46  閱讀: 3054 次  推薦: 0   原文鏈接   [收藏]  

 

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);
        }
    }
}
 

 

 

 

 

 

0
0
 
標簽:CSharp
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()