艾伟_转载: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);        }    }}

 

 

 

 

时间: 2024-09-15 10:59:47

艾伟_转载:C#下实现空白窗体上中文输入,可以实现类PS的文字工具的相关文章

C#下实现空白窗体上中文输入,可以实现类PS的文字工具

在空白窗体上打开输入法,在C#里的空白窗口是无论如何也是打不开输入法.设 置了this.ImeMode= ImeMode.NoControl也是无法打开输入法的录字窗口.去 Microsoft 开发论坛上问了一些问题.感谢周雪峰版主与Riquel_Dong 版主给的 指点.用了API函数: ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);终 于把输入法给调了出来,它的功能是把输入与指定的窗口进行关联. 代码如 下: f (m.Msg == WM_IME

艾伟_转载:.NET 4.0 Beta2中的BigInteger和Complex类

.NET4.0 Beta2中提供了新的System.Numerics命名空间,对应于System.Numerics.dll.该命名空间下就两个类BigInteger和Complex,我们来简单了解下这两个类的用法. BigInteger:任意大小的带符号整数 1.Int64, SByte, UInt16, UInt32, and UInt64这些都有一个MinValue和MaxValue属性.而BigInteger没有这两个属性,因为它没有大小限制.2.不可变的类型.3.由于他没有大小限制,理论

艾伟_转载:LINQ to SQL、NHibernate比较(二)-- LINQ to SQL实例

    用ADO.NET操作数据库大家一定再熟悉不过了,select.insert.update等等SQL语句大家也都必然滚瓜烂熟.我将自己在学习LINQ to SQL过程中的动手经历记录下来,作为今后学习的参考,也希望对刚刚接触的人有一点帮助.     我在本文涉及到一个很简单的系统,利用DataGridView实现数据库数据的批量增.删.改,不是什么强大的功能.     如果有人感兴趣,可以在看完我的这篇文章之后用ADO.NET实现同样的功能,看看到底会比使用LINQ to SQL多多少时间

艾伟_转载:WinForm二三事(二)

监视消息循环 在上一篇文章中,我们讨论了消息循环是响应用户输入的根本,还提到了在WinForm中执行耗时操作是因为这个耗时操作与消息循环在同一个UI Thread上,导致不能处理用户的后续响应,造成程序假死.除此之外,还说到了Form中的WndProc方法,说这个方法就是Win32时代那个处理消息的方法的.Net版. 那么今天这篇文章我们就来编个小程序来模拟一下这个耗时操作,看看是不是如上一篇所说:耗时操作造成消息循环的临时中断不能响应用户后续输入. 程序很简单,就是一个简单的窗体,上面放置一个

艾伟_转载:ASP.NET实现类似Excel的数据透视表

    代码:/Files/zhuqil/Pivot.zip     数据透视表提供的数据三维视图效果,在Microsoft Excel能创建数据透视表,但是,它并不会总是很方便使用Excel.您可能希望在Web应用程序中创建一个数据透视报表.创建一个简单的数据透视表可能是一件非常复杂的任务.所以,我打算不但为你提供一个非常有用的工具创建简单和高级的数据透视表,而且为你移除一些笼罩他们的神秘面纱.    目标是:我们想要有能力将datatable中的二维的数据转换成三维视图.    在大多数情况

艾伟_转载:用C#设计Windows应用程序模板

通常windows应用程序都有相似的特征:控件.菜单.工具条.状态栏等等.每次我们开始作一个新的windows应用程序时都是以相同的事情开始:建立项目,添加控件和事件处理器.如果我们有一个模板,那么我们就可以节约大量的时间了. 在介绍如何建立模板的过程中,将涉及大量的微软.net framework类库的基本知识.如果你没有使用集成开发环境那么本文介绍的模板对你将非常有用,如果你使用了visual studio.net这样的集成开发环境你也可以从中了解控件的工作方式,这对你也是很有用的. 写一个

艾伟_转载:WinForm二三事(一)

在进入正文之前,想请大家先欣赏下面两段代码: 1: //这是一个控制台程序,请先添加System.Windows.Form.dll的引用 2: using System.Windows.Form; 3:  4: public class ConsoleApplicationShowDialog 5: { 6: static void Main() 7: { 8: Form frm = new Form(); 9: frm.ShowDialog(); 10: } 11: } 1: //这是一个控制

艾伟_转载:ASP.NET MVC分页的实现

在ASP.NET中,GridView控件本身就带有分页的功能,只要把当前页面的索引值赋给GridView的PageIndex就可以实现了分页,至于数据怎么分页,全都由GridView封装起来了. 在ASP.NET MVC中分页的实现就只能靠自己来设计了.首先来说一下分页的原理.现在有一个张news表,中间有很多信息,我们假设一页显示5条记录,这样,页面数量=总记录数/5:这里,如果出现小数,得进位取整.如比总记录和数为51,那么分的页面数量是11,最后一页只有一条记录.好,有这样一个思路后,现在

艾伟_转载:.NET Discovery 系列之二--string从入门到精通(勘误版下)

本系列文章导航 .NET Discovery 系列之一--string从入门到精通(上) .NET Discovery 系列之二--string从入门到精通(勘误版下) .NET Discovery 系列之三--深入理解.NET垃圾收集机制(上) .NET Discovery 系列之四--深入理解.NET垃圾收集机制(下) .Net Discovery 系列之五--Me JIT(上) .NET Discovery 系列之六--Me JIT(下) .NET Discovery 系列之七--深入理解