WinForm IME输入法BUG完美修复
本文来自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的地方),只是默认使用英文标点符号。但是你不用担心,主流的中文输入法(如搜狗拼音)会默认采用中文标点的。代码片段如下:
- protected override void OnLoad(EventArgs e)
- {
- KeyPreview = true;
- DrawTextboxes();
- // 让输入法为开启半角状态
- ImeMode = ImeMode.OnHalf;
- base.OnLoad(e);
- }
完美修复
现在是通过对imm32.dll API调用,使之输入法状态为开启,这样就保证了WinForm程序其它窗口的输入法状态也正确显示。重写第一个窗口的OnActivited事件即可。注意,不要再使用Control的ImeMode属性了。测试下面代码,点击按钮打开一个新的窗口,仍然可以正确使用输入法。OK,问题得到完美解决~~!
- /* WinForm IME输入法BUG完美修复
- * 编译:csc.exe /target:winexe WinformImeBugFixed.cs
- */
- using System;
- using System.Windows.Forms;
- using System.Drawing;
- using System.Runtime.InteropServices;
- namespace WinformImeBugFixed
- {
- public class Form1 : Form
- {
- #region 解决输入法BUG
- //解决输入法BUG
- [DllImport("imm32.dll")]
- public static extern IntPtr ImmGetContext(IntPtr hwnd);
- [DllImport("imm32.dll")]
- public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);
- protected override void OnActivated(EventArgs e)
- {
- base.OnActivated(e);
- IntPtr HIme = ImmGetContext(this.Handle);
- ImmSetOpenStatus(HIme, true);
- }
- #endregion
- #region 不感兴趣的
- private void DrawTextboxes()
- {
- Controls.Clear();
- int x, y, d;
- x = y = d = 10;
- for (int i = 0; i < 2; i++)
- {
- var textbox = new TextBox()
- {
- Width = 200,
- Location = new Point(x, y)
- };
- y += textbox.Height + d;
- textbox.DataBindings.Add("Text", textbox, "ImeMode");
- Controls.Add(textbox);
- }
- }
- private void DrawButton()
- {
- var button = new Button()
- {
- Text = "Show Form2",
- Location = new Point(10, 70)
- };
- button.Click += delegate
- {
- var form2 = new Form();
- form2.Text = "Form2";
- var textbox = new TextBox()
- {
- Width = 200,
- Location = new Point(10, 10)
- };
- form2.Controls.Add(textbox);
- form2.Show();
- };
- Controls.Add(button);
- }
- protected override void OnLoad(EventArgs e)
- {
- Text = "IME输入法BUG修复 F5-刷新 F1-博客";
- KeyPreview = true;
- DrawTextboxes();
- DrawButton();
- base.OnLoad(e);
- }
- public Form1()
- {
- InitializeComponent();
- }
- protected override void OnKeyDown(KeyEventArgs e)
- {
- try { HandleKeyDown(e); }
- finally { base.OnKeyDown(e); }
- }
- private void HandleKeyDown(KeyEventArgs e)
- {
- if (e.KeyCode == Keys.F5) DrawTextboxes();
- else if (e.KeyCode == Keys.F1) NavigateBlog();
- }
- private void NavigateBlog()
- {
- System.Diagnostics.Process.Start("http://hi.baidu.com/wingingbob/blog/item/20741734532af846251f14f1.html");
- }
- #endregion
- #region Form1设计器
- private System.ComponentModel.IContainer components = null;
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
- private void InitializeComponent()
- {
- this.SuspendLayout();
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(240, 100);
- this.Name = "Form1";
- this.Text = "Form1";
- this.ResumeLayout(false);
- }
- #endregion
- #region 入口点
- static class Program
- {
- [STAThread]
- static void Main()
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new Form1());
- }
- }
- #endregion
- }
- }
补充:采用OnActivited事件激活输入法,那么这个窗体的TopMost属性应该为false才能使输入法设置有效。这个原因可能是由于设置TopMost为True时,将此句代码写入构造函数里,而此时修复输入法的代码还没有被执行。也就是说,将TopMost=True的代码写在窗体的OnLoad事件中,就没有问题了。于是,我把输入法修复的代码修改如下:
- #region 解决输入法BUG
- [DllImport("imm32.dll")]
- public static extern IntPtr ImmGetContext(IntPtr hwnd);
- [DllImport("imm32.dll")]
- public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);
- delegate void fixImeDele();
- protected override void OnLoad(EventArgs e)
- {
- fixImeDele fixime = delegate
- {
- IntPtr HIme = ImmGetContext(this.Handle);
- ImmSetOpenStatus(HIme, true);
- };
- this.BeginInvoke(fixime);
- this.TopMost = true;
- base.OnLoad(e);
- }
- #endregion
注意这里使用了一个小技巧,用包含BeginInvoke语句的OnLoad方法代替了原先的OnActivited方法,TopMost=True也写在这个OnLoad重载里,这样,窗口置顶和输入法开启的代码全部有效。BTW,在Onload中加入BeginInvoke的方式还可以解决Control.Focus()方法在Load中失效的问题,原理和这个一样,写在委托里调用就是了,范例参见:《WinForm IME输入法BUG测试》。
WinForm IME输入法BUG完美修复的更多相关文章
- windows8输入法终极完美修复
现在WIN8正式版出现以来,win8的用户越来越多,毕竟是新系统,BUG肯定是有的,现在小编就为大家解决一个大BUG. 输入法BUG: 现象:1.删除系统输入法,重启后无法调出输入法; 2.卸载用户安 ...
- duilib List控件,横向滚动时列表项不移动或者显示错位的bug的修复
转载请说明出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/42264673 关于这个bug的修复我之前写过一篇博客,连接为:http:/ ...
- duilib combo控件,当鼠标滚动时下拉列表自动关闭的bug的修复
转载请说明出处,谢谢~~ 群里有朋友提到了使用Combo控件时,当下拉列表出现,此时鼠标滚轮滚动,下拉列表就自动消失了.我看了一下源码,这个bug的修复很简单. CComboUI控件被单击时创建CCo ...
- 逆向实战第一讲,寻找OllyDbg调试工具的Bug并修复
逆向实战第一讲,寻找OllyDbg调试工具的Bug并修复 首先我们要知道这个OD的Bug是什么. 我们调试一个UNICODE的窗口,看下其窗口过程. 一丶查看OllyDbg 的Bug 1.1spy++ ...
- Flutter实战视频-移动电商-34.列表页_小BUG的修复
34.列表页_小BUG的修复 当高粱酒的子类没有数据返回的时候就会报错. 解决接口空数据报错的问题 没有数据的时候,给用户一个友好的提示, 我们没有数据的时候还要告诉用户,提示一下他没有数据,在我们的 ...
- IME输入法编程心得
原文:IME输入法编程心得 posted @ 2012-11-30 00:42 from [FreedomShe] 自然语言处理的输入法作业成品没有做出来,但不想再在蛋疼的Win32上面耗费时间了,整 ...
- 常见IE浏览器bug及其修复方案(双外边距、3像素偏移、绝对定位)
1. 双外边距浮动bug IE6和更低版本中存在双外边距浮动bug,顾名思义,这个Windows bug使任何浮动元素上的外边距加倍 bug重现: <!DOCTYPE html> < ...
- duilib List控件,横向滚动时列表项不移动或者移动错位的bug的修复
转载请说明出处,谢谢~~ 这篇博客已经作废,只是留作记录,新的bug修复博客地址:http://blog.csdn.net/zhuhongshu/article/details/42264673 之前 ...
- IE6浏览器常见的bug及其修复方法
IE6不支持min-height,解决办法使用css hack: .target { min-height: 100px; height: auto !important; height: 100px ...
随机推荐
- day--14前端(HTML、CSS)
浏览器相当于客户端,浏览器访问服务端,收到消息之后里面断开,一次请求,一次响应,一次断开. Web框架本质 http://www.cnblogs.com/wupeiqi/articles ...
- 【LOJ】#2078. 「JSOI2016」无界单词
题解 用所有的方案减去有界的方案 我们规定两个前缀后缀相同时长度最短的,设长度为l,因为长度最短所以他们也是无界单词,可以递推 \(f[i] = \sum_{j = 1}^{\lfloor \frac ...
- P1091 合唱队形 DP 最长升序列维护
题目描述 NN位同学站成一排,音乐老师要请其中的(N-KN−K)位同学出列,使得剩下的KK位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K1,2,…,K,他 ...
- cygwin安装sshd服务并实现无密码登录
http://blog.csdn.net/cybercode/article/details/7080743 这篇文章主要是为我在win7(64位)下搭建hadoop环境所准备的.首先参照在cygwi ...
- Python 保存数据的方法(4种方法)
Python 保存数据的方法: open函数保存 使用with open()新建对象 写入数据(这里使用的是爬取豆瓣读书中一本书的豆瓣短评作为例子) import requests from lxml ...
- DSP 程序的执行时间
在访问TSCL寄存器前要定义 cregister volatile unsigned int TSCL; TSCL/TSCH,它们与CPU同频,共同表示一个64-bit数,CPU运行一个cycle,该 ...
- POJ 3009 Curling 2.0(DFS + 模拟)
题目链接:http://poj.org/problem?id=3009 题意: 题目很复杂,直接抽象化解释了.给你一个w * h的矩形格子,其中有包含一个数字“2”和一个数字“3”,剩下的格子由“0” ...
- P1375 小猫(二飞的小憨猫)
P1375 小猫(二飞的小憨猫)连两个点,就把一个多边形,分成了两部分,这两部分的点一定得是偶数,这样就可以递推啦,比如h[5]==h[4][0]+h[3][1]+h[2][2]+h[1][3]+h[ ...
- 007.SMB其他应用
一 目录权限 系统权限需要对共享目录生效 samba服务器权限也会对共享目录生效 当用户过多权限交叉的时候,建议使用系统权限控制共享目录权限,而不建议采用samba权限来控制 例如: [work] p ...
- 命令:man
简介 man命令,是manual的缩写,manual表示手册的意思.通过man命令,可以查询大多数shell外部命令的帮助手册. 语法格式 # man [[section] page ...] ... ...