C#下实现空白窗体中文输入

简介: 在空白窗体上打开输入法,在C#里的空白窗口是无论如何也是打不开输入法.设置了this.ImeMode= ImeMode.NoControl也是无法打开输入法的录字窗口.去Microsoft 开发论坛上问了一些问题.

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

  在空白窗体上打开输入法,在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);
  }
  }
  }
相关文章
|
7月前
|
Java 数据库 C#
C#winforms实现windows窗体人脸识别
C#winforms实现windows窗体人脸识别
|
关系型数据库 MySQL C#
C# winform 一个窗体需要调用自定义用户控件的控件名称
给用户控件ucQRCode增加属性: //二维码图片 private PictureBox _pictureBoxFSHLQrCode; public PictureBox PictureBoxFSHLQrCode {   get { return _pictureBoxFSHLQrCode; }   set { this.pictureBoxFSHLQrCode = value; } } 在Form1窗体直接调用即可: ucQRCode uQRCode=new ucQRCode(); ucQRCode.PictureBoxFSHLQrCode.属性= 要复制或传给用户控件上的控件的值
73 0
|
2月前
|
API C# Windows
【C#】在winform中如何实现嵌入第三方软件窗体
【C#】在winform中如何实现嵌入第三方软件窗体
127 0
|
5月前
|
开发框架 数据可视化 C#
|
7月前
|
C#
C#如何实现窗体最小化到托盘
C#如何实现窗体最小化到托盘
97 0
|
7月前
|
JavaScript Linux C#
【傻瓜级JS-DLL-WINCC-PLC交互】1.C#用windows窗体控件创建.net控件
【傻瓜级JS-DLL-WINCC-PLC交互】1.C#用windows窗体控件创建.net控件
149 0
|
7月前
|
C# Windows
C#安装“Windows 窗体应用(.NET Framework)”
C#安装“Windows 窗体应用(.NET Framework)”
202 0
|
C# 数据安全/隐私保护
C# 窗体之间参数互相传递的两种方法与使用
C# 窗体之间参数互相传递的两种方法与使用
|
C# Kotlin
C#is、as关键字及获取当前活动窗体的实例
这篇日志记录一下C#中is关键字及as关键字的用法。 Is :判断检查对象是否与给定类型兼容 As :将对象转换为指定类型(强转),就跟(int )这样的用法是一样的。 获取当前窗体的活动子窗体。
59 0
|
C# 数据安全/隐私保护
ApeForms | C# WinForm窗体控件平滑减速运动
在桌面软件开发中,有时会需要控制窗体或控件移动以实现某些界面效果,比如幻灯片换页、侧面的展开栏等。 通常情况下我们会使用Timer以每隔一段时间修改一下坐标位置的方式来实现目标对象的位移效果,但通过这个方式实现的动效存在几个问题: 匀速运动效果生硬; 运动过程中不便灵活改变运动状态(如侧栏展开一半时令其收起); 动效多时需要创建多个Timer对象,不易管理且占用资源; ApeForms中为控件和窗体提供了平滑运动的扩展方法,很好的解决了这些问题。不仅是坐标的平滑运动,还有控件\窗体尺寸的平滑变化、透明度的平滑变化。允许在变化的中途随时更改目标坐标\尺寸\透明度,且使用共享的Timer
11401 1
ApeForms | C# WinForm窗体控件平滑减速运动