本文来自http://hi.baidu.com/wingingbob/item/a2cb3fc0fe3bd1bb0d0a7b5b

《WinForm IME输入法BUG测试》里,我描述了在.NET Framework 2.0的WinForm中,中文输入法的BUG。这个BUG由来已久,听说在最新的VS2010中也没有真正得到解决。在文章后面,我怀疑是那些产生此类BUG的中文输入法本身在设计上存在的缺陷,才导致了WinForm无法正确识别。不管怎么样,问题出了就得想办法解决,今天的方法是一个“简单而有效的”解决办法,就是在窗体加载时将输入法预置为ImeMode.OnHalf。最终的结果如上图所示,王码五笔可以正确切换出来,而且以半角的方式显示(ImeMode.OnHalf不同于ImeMode.On的地方),只是默认使用英文标点符号。但是你不用担心,主流的中文输入法(如搜狗拼音)会默认采用中文标点的。代码片段如下:

  1. protected override void OnLoad(EventArgs e)
  2. {
  3. KeyPreview = true;
  4. DrawTextboxes();
  5. // 让输入法为开启半角状态
  6. ImeMode = ImeMode.OnHalf;
  7. base.OnLoad(e);
  8. }

完美修复

现在是通过对imm32.dll API调用,使之输入法状态为开启,这样就保证了WinForm程序其它窗口的输入法状态也正确显示。重写第一个窗口的OnActivited事件即可。注意,不要再使用Control的ImeMode属性了。测试下面代码,点击按钮打开一个新的窗口,仍然可以正确使用输入法。OK,问题得到完美解决~~!

  1. /* WinForm IME输入法BUG完美修复
  2. * 编译:csc.exe /target:winexe WinformImeBugFixed.cs
  3. */
  4. using System;
  5. using System.Windows.Forms;
  6. using System.Drawing;
  7. using System.Runtime.InteropServices;
  8. namespace WinformImeBugFixed
  9. {
  10. public class Form1 : Form
  11. {
  12. #region 解决输入法BUG
  13. //解决输入法BUG
  14. [DllImport("imm32.dll")]
  15. public static extern IntPtr ImmGetContext(IntPtr hwnd);
  16. [DllImport("imm32.dll")]
  17. public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);
  18. protected override void OnActivated(EventArgs e)
  19. {
  20. base.OnActivated(e);
  21. IntPtr HIme = ImmGetContext(this.Handle);
  22. ImmSetOpenStatus(HIme, true);
  23. }
  24. #endregion
  25. #region 不感兴趣的
  26. private void DrawTextboxes()
  27. {
  28. Controls.Clear();
  29. int x, y, d;
  30. x = y = d = 10;
  31. for (int i = 0; i < 2; i++)
  32. {
  33. var textbox = new TextBox()
  34. {
  35. Width = 200,
  36. Location = new Point(x, y)
  37. };
  38. y += textbox.Height + d;
  39. textbox.DataBindings.Add("Text", textbox, "ImeMode");
  40. Controls.Add(textbox);
  41. }
  42. }
  43. private void DrawButton()
  44. {
  45. var button = new Button()
  46. {
  47. Text = "Show Form2",
  48. Location = new Point(10, 70)
  49. };
  50. button.Click += delegate
  51. {
  52. var form2 = new Form();
  53. form2.Text = "Form2";
  54. var textbox = new TextBox()
  55. {
  56. Width = 200,
  57. Location = new Point(10, 10)
  58. };
  59. form2.Controls.Add(textbox);
  60. form2.Show();
  61. };
  62. Controls.Add(button);
  63. }
  64. protected override void OnLoad(EventArgs e)
  65. {
  66. Text = "IME输入法BUG修复 F5-刷新 F1-博客";
  67. KeyPreview = true;
  68. DrawTextboxes();
  69. DrawButton();
  70. base.OnLoad(e);
  71. }
  72. public Form1()
  73. {
  74. InitializeComponent();
  75. }
  76. protected override void OnKeyDown(KeyEventArgs e)
  77. {
  78. try { HandleKeyDown(e); }
  79. finally { base.OnKeyDown(e); }
  80. }
  81. private void HandleKeyDown(KeyEventArgs e)
  82. {
  83. if (e.KeyCode == Keys.F5) DrawTextboxes();
  84. else if (e.KeyCode == Keys.F1) NavigateBlog();
  85. }
  86. private void NavigateBlog()
  87. {
  88. System.Diagnostics.Process.Start("http://hi.baidu.com/wingingbob/blog/item/20741734532af846251f14f1.html");
  89. }
  90. #endregion
  91. #region Form1设计器
  92. private System.ComponentModel.IContainer components = null;
  93. protected override void Dispose(bool disposing)
  94. {
  95. if (disposing && (components != null))
  96. {
  97. components.Dispose();
  98. }
  99. base.Dispose(disposing);
  100. }
  101. private void InitializeComponent()
  102. {
  103. this.SuspendLayout();
  104. this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
  105. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  106. this.ClientSize = new System.Drawing.Size(240, 100);
  107. this.Name = "Form1";
  108. this.Text = "Form1";
  109. this.ResumeLayout(false);
  110. }
  111. #endregion
  112. #region 入口点
  113. static class Program
  114. {
  115. [STAThread]
  116. static void Main()
  117. {
  118. Application.EnableVisualStyles();
  119. Application.SetCompatibleTextRenderingDefault(false);
  120. Application.Run(new Form1());
  121. }
  122. }
  123. #endregion
  124. }
  125. }

补充:采用OnActivited事件激活输入法,那么这个窗体的TopMost属性应该为false才能使输入法设置有效。这个原因可能是由于设置TopMost为True时,将此句代码写入构造函数里,而此时修复输入法的代码还没有被执行。也就是说,将TopMost=True的代码写在窗体的OnLoad事件中,就没有问题了。于是,我把输入法修复的代码修改如下:

  1. #region 解决输入法BUG
  2. [DllImport("imm32.dll")]
  3. public static extern IntPtr ImmGetContext(IntPtr hwnd);
  4. [DllImport("imm32.dll")]
  5. public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);
  6. delegate void fixImeDele();
  7. protected override void OnLoad(EventArgs e)
  8. {
  9. fixImeDele fixime = delegate
  10. {
  11. IntPtr HIme = ImmGetContext(this.Handle);
  12. ImmSetOpenStatus(HIme, true);
  13. };
  14. this.BeginInvoke(fixime);
  15. this.TopMost = true;
  16. base.OnLoad(e);
  17. }
  18. #endregion

注意这里使用了一个小技巧,用包含BeginInvoke语句的OnLoad方法代替了原先的OnActivited方法,TopMost=True也写在这个OnLoad重载里,这样,窗口置顶和输入法开启的代码全部有效。BTW,在Onload中加入BeginInvoke的方式还可以解决Control.Focus()方法在Load中失效的问题,原理和这个一样,写在委托里调用就是了,范例参见:《WinForm IME输入法BUG测试》

WinForm IME输入法BUG完美修复的更多相关文章

  1. windows8输入法终极完美修复

    现在WIN8正式版出现以来,win8的用户越来越多,毕竟是新系统,BUG肯定是有的,现在小编就为大家解决一个大BUG. 输入法BUG: 现象:1.删除系统输入法,重启后无法调出输入法; 2.卸载用户安 ...

  2. duilib List控件,横向滚动时列表项不移动或者显示错位的bug的修复

    转载请说明出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/42264673 关于这个bug的修复我之前写过一篇博客,连接为:http:/ ...

  3. duilib combo控件,当鼠标滚动时下拉列表自动关闭的bug的修复

    转载请说明出处,谢谢~~ 群里有朋友提到了使用Combo控件时,当下拉列表出现,此时鼠标滚轮滚动,下拉列表就自动消失了.我看了一下源码,这个bug的修复很简单. CComboUI控件被单击时创建CCo ...

  4. 逆向实战第一讲,寻找OllyDbg调试工具的Bug并修复

    逆向实战第一讲,寻找OllyDbg调试工具的Bug并修复 首先我们要知道这个OD的Bug是什么. 我们调试一个UNICODE的窗口,看下其窗口过程. 一丶查看OllyDbg 的Bug 1.1spy++ ...

  5. Flutter实战视频-移动电商-34.列表页_小BUG的修复

    34.列表页_小BUG的修复 当高粱酒的子类没有数据返回的时候就会报错. 解决接口空数据报错的问题 没有数据的时候,给用户一个友好的提示, 我们没有数据的时候还要告诉用户,提示一下他没有数据,在我们的 ...

  6. IME输入法编程心得

    原文:IME输入法编程心得 posted @ 2012-11-30 00:42 from [FreedomShe] 自然语言处理的输入法作业成品没有做出来,但不想再在蛋疼的Win32上面耗费时间了,整 ...

  7. 常见IE浏览器bug及其修复方案(双外边距、3像素偏移、绝对定位)

    1. 双外边距浮动bug IE6和更低版本中存在双外边距浮动bug,顾名思义,这个Windows bug使任何浮动元素上的外边距加倍 bug重现: <!DOCTYPE html> < ...

  8. duilib List控件,横向滚动时列表项不移动或者移动错位的bug的修复

    转载请说明出处,谢谢~~ 这篇博客已经作废,只是留作记录,新的bug修复博客地址:http://blog.csdn.net/zhuhongshu/article/details/42264673 之前 ...

  9. IE6浏览器常见的bug及其修复方法

    IE6不支持min-height,解决办法使用css hack: .target { min-height: 100px; height: auto !important; height: 100px ...

随机推荐

  1. MyBatis使用示例

    下面是一个简单的MyBatis使用DEMO. 整体结构 整体代码大致如下: POM依赖 需要引用两个jar包,一个是mybatis,另一个是mysql-connector-java,如果是maven工 ...

  2. MVC底层原理

    窥探ASP.Net MVC底层原理 实现跨越Session的分布式TempData 1.问题的引出 我相信大家在项目中都使用过TempData,TempData是一个字典集合,一般用于两个请求之间临时 ...

  3. linux(centos)安装升级ruby

    参考文章:http://www.ruby-lang.org/zh_cn/documentation/installation/ 文章给出了不同平台的多种方法.我的是centos,我选择了一个比较简单的 ...

  4. JS图形化插件利器组件系列 —— Gojs组件

    阅读目录 一.组件效果预览 二.初次接触 1.Gojs简介 2.使用入门 三.综合效果 1.自定义流程的使用 2.工业流程图 四.总结 正文 前言:之前分享过两篇关于流程画图的前端组件,使用的jsPl ...

  5. 洛谷P3576 [POI2014]MRO-Ant colony [二分答案,树形DP]

    题目传送门 MRO-Ant colony 题目描述 The ants are scavenging an abandoned ant hill in search of food. The ant h ...

  6. app微信支付宝支付后台的插件模式+回调通过spring广播处理后续业务(已亲测可用)

    写在前面的话:每当我们做一个项目,基本上都会涉及到支付的业务,最常用的莫过于微信和支付宝的支付了,项目有bug,有问题,都不叫问题,可一旦钱出了问题,那就是大问题了,所以在支付业务上我们必须慎之又慎! ...

  7. C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).

    目录 C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector). auto_ptr scoped_ptr ptr_vector C++智能指针,指针容器原 ...

  8. 基于js的自适应、多样式轮播图插件(兼容IE8+、FF、chrome等主流浏览器)

    插件github地址:https://github.com/pomelott/slider-plug_in 使用方式: slider plug-in 左右滑动的自适应.多样式全能插件.多次调用时只需传 ...

  9. 手动搭建ABP2.1.3——基础框架

    一.基础层搭建 1,创建一个空解决方案 2,层结构 Demo.Core[v:4.6.1]:类库 Demo.EntityFramework[v:4.6.1]:类库(引用Demo.Core) Demo.A ...

  10. BZOJ.1879.[SDOI2009]Bill的挑战(状压DP)

    题目链接 f定义和下面的思路一样,转移时枚举填什么字符,去更新f并算出有哪些字符串可以匹配某个状态(见code吧...). 预处理出有哪些字符串在第i位可以转移到某个字符c,dp时&一下状态即 ...