XNA中的中文输入(一)

仅供个人学习使用,请勿转载,勿用于任何商业用途。

游戏中的中文输入一直是个很棘手的问题,就连wow也实现的不是很好,很多人不得不在窗口最大化模式下游戏。对大部分程序员来说,如果不开发输入法,永远也不需要关心IME是如果工作的,即使是游戏开发,除了中日韩等少数使用多字符语言的国家,也不需要关心IME。了解游戏IME开发的人,也因为种种原因,不愿过多讨论,因此相关资料非常之少。

最近花了一周时间,终于实现了中文输入。本文主要讨论如何在XNA中调用IME,有些特定WinForm下的行为也许和传统DirectX程序不太一样。本文不会给出详细的实现代码和原理,但会把所有关键步骤都写出来。

继续阅读之前,你应该先了解或准备以下资料:

1. DirectX SDK中CustomeUI的sample。虽然这并不是一个很适合“学习”的例子(代码太过于复杂),但毕竟是ms建议的标准实现方法,也是最兼容性最好的实现。

2.  DirectX SDK中的Using an Input Method Editor in a Game一文,以下简称“指南”。在我看来,这同样也是一篇不太好的指南,很多关键部分讲的非常模糊。

3.  Windows SDK中IME相关的文档,可在MSDN—Win32 and COM—User Interface—Internationalization—SDK Document—International Text Display找到。

4. 对于XNA开发者还需要对windows消息机制(WindowProc)以及P/Invoke有所了解。

我们要做的事情非常简单,1,在游戏程序中打开IME窗口;2,获得IME所“合成”的文字;3,隐藏IME窗口(可选)。实现的思想也很简单:拦截IME相关的windows消息,并进行处理就可以了。

要处理的第一个消息是WM_IME_SETCONTEXT(请先了解文档里Input Cotext的概念),SDK里说“Sent to an application when a window is activated”,按照我的理解,这句话的意思是每次窗口active之后,向窗口发送一次。但我在WinForm下的测试结果是很多IME状态改变都会触发这个消息。SDK里还说“By default, the operating system creates and assigns an input context to each thread”,这句话迷惑了我很久,从后来的实验来看,系统并没有“assigns an input context to each thread”,因为如果在接收到WM_IME_SETCONTEXT时,显式调用ImmAssociateContext,再Ctrl+shift,运气好的话,此时打字会发现IME窗口已经出现了!对,就这么简单(指南里竟然完全没有提到ImmAssociateContext这个函数,怨念啊,我苦苦google了一整个下午T_T)。为什么要说运气好呢?因为此时你见到IME窗口的可能性,基于你安装了哪种输入法!搜狗,恭喜你中奖了;紫光,你有50%的可能性看到;微软或者google拼音,基本上你什么都看不到。无论如何,总算是有了进展。让我讲的更详细一些,以便你能重现这个伟大的时刻J

1. 创建一个新的winForm程序,对我们先从winForm开始,然后再讨论XNA。

2. 声明以下API

class IMM
{
   [DllImport("imm32.dll", SetLastError = true)]
   public static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
}

3. 为了方便使用API,还需要声明以下常量

代码

[Flags]
public enum CompositionStringFlag
{
    ReadingString = 0x0001,
    ReadingStringAttribute = 0x0002,
    ReadingClause = 0x0004,
    CompositionString = 0x0008,
    CompositionStringAttribute = 0x0010,
    CompositionStringClause = 0x0020,
    CursorPosition = 0x0080,
    DeltaStart = 0x0100,
    ResultReadingString = 0x0200,
    ResultReadingStringClause = 0x0400,
    ResultString = 0x0800,
    ResultClause = 0x1000
}

public static class WindowMessage
{
    public const int Char = 0x0102;
    public const int ImeStartCompostition = 0x010D;
    public const int ImeEndComposition = 0x010E;
    public const int ImeComposition = 0x010F;
    public const int ImeKeyLast = 0x010F;
    public const int ImeSetContext = 0x0281;
    public const int ImeNotify = 0x0282;
    public const int ImeControl = 0x0283;
    public const int ImeCompositionFull = 0x0284;
    public const int ImeSelect = 0x0285;
    public const int ImeChar = 0x286;
    public const int ImeRequest = 0x0288;
    public const int ImeKeyDown = 0x0290;
    public const int ImeKeyUp = 0x0291;
    public const int InputLanguageChange = 0x0051;
}

4. 为窗口添加以下函数:

代码

protected override void WndProc(ref Message m)
{
    if (m.Msg == WindowMessage.ImeSetContext)
    {
        if (m.WParam.ToInt32() == 1)
        {
            IntPtr imeContext = IMM.ImmGetContext(this.Handle);
            IMM.ImmAssociateContext(this.Handle, imeContext);
        }
    }
    base.WndProc(ref m);
}

好了,编译运行。成功没有?没有!对,就算你装了先前提到的第一种输入法,此时程序也不会有任何反应。Why?设置断点,你会发现imeContext的值是0,意味着根本没有得到正确的context。再仔细Debug,你会发现在程序启动时,WM_IME_SETCONTEXT消息被触发了不止一次,第一次消息触发时,正确得到了context,但后面的几次消息,只会返回0。所以,必须在初始化时,保存对context的引用,这是与CustomeUI例子非常不同的一点,猜想也许是winForm底层机制的原因。再次运行,你应该能看到些东西了。

现在来解决只对搜狗和紫光有效的问题(顺便说一下,之前一直觉得各种输入法之间没多大差别,这次才发现搜狗是所有输入法里最神奇的)。这是真正困扰了我一周的问题,结果却出乎意料,只需要在WndProc里添加以下代码:

if (m.Msg == WindowMessage.InputLanguageChange)
{
    return; //Don't pass this message to base class!!!!
}

不出意外的话,现在你已经可以调出所有输入法了。下一次,我将讨论如何取出IME中的字符

转载于:https://www.cnblogs.com/clayman/archive/2009/12/17/1626084.html

XNA中的中文输入(一)相关推荐

  1. Ubuntu18.04中dia中文输入

    开始是希望在ubuntu中找一个比较好的画流程图工具,在网上找了一下,发现dia还可以,但在下载安装后发现我不能进行中文输入,之后有事一顿百度.google,找到几个解决方法(但我试了,都无用) 将配 ...

  2. 在Ubuntu终端中设置中文输入

    说明:我的截图是在我配置完成后,之后截得图,在Ubuntu下切换中英文是win+空格键 1. 首先打开设置,再在设置中找到区域和语言中的管理已安装的语言 2. 再选择添加或删除语言,再在已安装语言里面 ...

  3. dreamweaver半角空格_在Dreamweaver MX中,中文输入时要输入空格应该()。A.在编辑窗口直接输入一个半角空格B.代码中输入...

    在产品生命周期各阶段中,销售增长率最高的阶段是()A.投入期B.成长期C.成熟期D.衰退期 在一定的组织体系中,通过明文规定的渠道所进行的沟通叫()A.正式沟通B.非正式沟通C.单向沟通 肠阿巴病性溃 ...

  4. 开始ubuntu 14.04 的装X模式---终端模式下中文输入,听歌,上irc 开启framebuffer看电影 截图...

    先上图吧 卡卡的全是在tty1 下的操作,看电影,听歌,截图 ,看图  ,上irc 等等,相当适合在小白面前装屁! 需要安装的软件: 为了能正常显示中文:安装fbterm sudo apt-get i ...

  5. vmware 中文输入解决方法

    在vmware的ubuntu系统中无法输入中文,首先打开Language support,点击Install/Remove Languages 勾选中文后点击Apply 下载完成后再设置界面选择key ...

  6. centos7中mysql不能输入中文问题的解决

    centos7中mysql不能输入中文问题的解决 参考文章: (1)centos7中mysql不能输入中文问题的解决 (2)https://www.cnblogs.com/qiangayz/p/868 ...

  7. mysql中更改字符集为utf8mysql中文输入不了问题解决

    mysql中更改字符集为utf8&&mysql中文输入不了问题解决 参考文章: (1)mysql中更改字符集为utf8&&mysql中文输入不了问题解决 (2)http ...

  8. c#中利用keybd_event函数+自定义软键盘实现中文输入时的问题

    (一)声明外部方法 [DllImport("User32.dll")]         public static extern void keybd_event(byte bVK ...

  9. React Native 中 TextInput 组件和中文输入冲突

    原文转载自我的 Github 博客 在用 React Native (下称 RN) 开发面向国人的应用时,不可避免会有用户使用中文输入法的情景.在 RN 中,负责输入内容的控件是 <TextIn ...

  10. IDEA的全局搜索框中,无法输入中文

    问题描述:在idea的全局搜索框(快捷键Ctrl+Shift+F)中,无法输入中文字符,只能输入英文字符 解决办法:清除idea缓存并重启 1.检查输入法 我用的搜狗输入法,把和idea冲突的快捷键全 ...

最新文章

  1. 认识python零基础知识到实战概论的复习和回顾上
  2. SSL/TLSV1.0 programe in linux
  3. ISIS和OSPF的比较
  4. [单刷APUE系列]第五章——标准I/O库
  5. vector简单实现
  6. C和指针之字符串strtok函数
  7. 从网络到分布式-负载均衡
  8. 浏览器事件循环机制与Vue nextTick的实现
  9. 【Python】安装IPython和IPthon Notebook
  10. 2019智能手表推荐_戴过 100 块智能手表后,2019年我觉得这4款智能手表最值得买!...
  11. Django之POST GET与前后端交互
  12. 《编码的奥秘》读后感
  13. 首次项目经验总结(一)
  14. 子龙山人:我从Cocos2d-x团队里学到的
  15. 解决IP地址冲突的方法
  16. python 发送邮件正文字体设置_smtplib文字邮件的发送
  17. android平台下OpenGL ES 3.0绘制纯色背景
  18. SimpleMind Pro中文版
  19. cent os 火狐_本周关注我们:整体框架和Firefox OS
  20. 2021年最后一件大事!

热门文章

  1. Spark面试题梳理
  2. ubuntu安装cairo
  3. 网页内容复制粘贴(三种方案 兼容多种浏览器)
  4. sbt 地址修改备注
  5. python数据包之利器scapy用法!
  6. python if条件判断语句
  7. Django 【第六篇】ORM跨表操作(聚合查询,分组查询,F和Q查询等)
  8. lintcode-76-最长上升子序列
  9. VS2015自带的LocalDB数据库的用法
  10. DIV的摇晃效果---jquery实现