《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 } } |