zoukankan      html  css  js  c++  java
  • 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;

                }

          

            }

            /// <summary>

            /// 打印文字

            /// </summary>

            private void intoText()//

            {

               Graphics g  = this.CreateGraphics();

               g.DrawString(sb.ToString(), font, Brushes.Black, 10, 10);

             

            }


        }

    }

  • 相关阅读:
    swagger在线文档配置
    SpringBoot中使用Shiro和JWT做认证和鉴权
    Java web基础
    spring boot基础
    spring MVC基础
    IDEA破解(自动重置试用期)
    Linux常用jar包启动停止脚本sh命令
    Docker Desktop 容器与镜像的保存和导入
    字符串有长度限制吗
    Thyemleaf报错: Method call: Attempted to call method *** on null context object
  • 原文地址:https://www.cnblogs.com/xiaoshou/p/1558696.html
Copyright © 2011-2022 走看看