视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
C#下实现空白窗体上中文输入,可以实现类PS的文字工具
2020-11-27 14:49:48 责编:小采
文档
 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);

}

}

}

更多C#下实现空白窗体上中文输入,可以实现类PS的文字工具 相关文章请关注PHP中文网!

下载本文
显示全文
专题