选择显示字体大小

vs2005中文输入法自动转换的解决方法


  最近在用vs2005做项目的时候,一直忍受着vs2005输入法自动切换到全角的bug的作怪,一边等待着微软给我们一个解决的方案。但是,我的项目都要作为产品打包出去了,微软还是闷头不对这个bug出一个解决方法。怎么办?我可以忍受这个输入法来回切换之苦,可用户体验可不会饶过我们的。弄不好,来个集体罢用,让我们都到微软喝西北风去啊!

  总不能就这么交出产品出去吧,只有自己动手了。下面我用两种方法来实现如何避免输入法的这个bug。

  方法一:

  form的pain和遍历control的enter方法。

  首先,我们为了使您原有的代码更简洁,我们把所要做的步骤封装到一个单独的类中,类代码如下:

1using system;
2using system.runtime.interopservices;
3
4namespace mydemo
5{
6 public static class clsime
7 {
8 //声明一些api函数
9 [dllimport("imm32.dll")]
10 public static extern intptr immgetcontext(intptr hwnd);
11 [dllimport("imm32.dll")]
12 public static extern bool immgetopenstatus(intptr himc);
13 [dllimport("imm32.dll")]
14 public static extern bool immsetopenstatus(intptr himc, bool b);
15 [dllimport("imm32.dll")]
16 public static extern bool immgetconversionstatus(intptr himc, ref int lpdw, ref int lpdw2);
17 [dllimport("imm32.dll")]
18 public static extern int immsimulatehotkey(intptr hwnd, int lnghotkey);
19 public const int ime_cmode_fullshape = 0x8;
20 public const int ime_chotkey_shape_toggle = 0x11;
21 //重载setime,传入form
22 public static void setime(form frm)
23 {
24 frm.paint += new painteventhandler(frm_paint);
25 changeallcontrol(frm);
26 }
27 //重载setime,传入control
28 public static void setime(control ctl)
29 {
30 changeallcontrol(ctl);
31 }
32 //重载setime,传入对象句柄
33 public static void setime(intptr handel)
34 {
35 changecontrolime(handel);
36 }
37 private static void changeallcontrol(control ctl)
38 {
39 //在控件的的enter事件中触发来调整输入法状态
40 ctl.enter += new eventhandler(ctl_enter);
41 //遍历子控件,使每个控件都用上enter的委托处理
42 foreach (control ctlchild in ctl.controls)
43 changeallcontrol(ctlchild);
44 }
45
46 static void frm_paint(object sender, painteventargs e)
47 {
48 /**//*有人问为什么使用pain事件,而不用load事件或activated事件,是基于下列考虑:
49 * 1、在您的form中,有些控件可能是运行时动态添加的
50 * 2、在您的form中,使用到了非.net的ocx控件
51 * 3、form调用子form的时候,activated事件根本不会触发 */
52 changecontrolime(sender);
53 }
54 //控件的enter处理程序
55 static void ctl_enter(object sender, eventargs e)
56 {
57 changecontrolime(sender);
58 }
59 private static void changecontrolime(object sender)
60 {
61 control ctl = (control)sender;
62 changecontrolime(ctl.handle);
63 }
64 //下面这个函数才是真正检查输入法的全角半角状态
65 private static void changecontrolime(intptr h)
66 {
67 intptr hime = immgetcontext(h);
68 if (immgetopenstatus(hime)) //如果输入法处于打开状态
69 {
70 int imode = 0;
71 int isentence = 0;
72 bool bsuccess = immgetconversionstatus(hime, ref imode, ref isentence); //检索输入法信息
73 if (bsuccess)
74 {
75 if ((imode & ime_cmode_fullshape) > 0) //如果是全角
76 immsimulatehotkey(h, ime_chotkey_shape_toggle); //转换成半角
77 }
78 }
79 }
80 }
81}

  有人问为什么使用pain事件,而不用load事件或activated事件,我是基于下列考虑:

  1、在您的form中,有些控件可能是运行时动态添加的

  2、在您的form中,使用到了非.net的ocx控件

  3、form调用子form的时候,activated事件根本不会触发

  使用这个类的方法为:

  在您的界面中,在load的时候,在里面加上这样一句话:

clsime.setime(this);

  方法二:

  使用继承的方法。首先,建立一个独立的类如下:

1using system;
2using system.collections.generic;
3using system.componentmodel;
4using system.data;
5using system.collections;
6using system.drawing;
7using system.text;
8using system.windows.forms;
9using system.runtime.interopservices;
10
11namespace mydemo
12{
13 public class imeform:system.windows.forms.form
14 {
15 //声明一些api函数
16 [dllimport("imm32.dll")]
17 public static extern intptr immgetcontext(intptr hwnd);
18 [dllimport("imm32.dll")]
19 public static extern bool immgetopenstatus(intptr himc);
20 [dllimport("imm32.dll")]
21 public static extern bool immsetopenstatus(intptr himc, bool b);
22 [dllimport("imm32.dll")]
23 public static extern bool immgetconversionstatus(intptr himc, ref int lpdw, ref int lpdw2);
24 [dllimport("imm32.dll")]
25 public static extern int immsimulatehotkey(intptr hwnd, int lnghotkey);
26 private const int ime_cmode_fullshape = 0x8;
27 private const int ime_chotkey_shape_toggle = 0x11;
28 //重载form的onactivated
29 protected override void onactivated(eventargs e)
30 {
base.onactivated(e);
31 intptr hime = immgetcontext(this.handle);
32 if (immgetopenstatus(hime)) //如果输入法处于打开状态
33 {
34 int imode = 0;
35 int isentence = 0;
36 bool bsuccess = immgetconversionstatus(hime, ref imode, ref isentence); //检索输入法信息
37 if (bsuccess)
38 {
39 if ((imode & ime_cmode_fullshape) > 0) //如果是全角
40 immsimulatehotkey(this.handle, ime_chotkey_shape_toggle); //转换成半角
41 }
42
43 }
44 }
45 }
46}
47

  使用这个类的方法为:

  修改所有的form的继承关系,比如,你有这样的一个form类:

public partial class form1 :form
{
...
}

  那么,把它改成:

public partial class form1 :imeform
{
...
}

  相信,这样的修改会很快,全项目查找替换一下即可。

  记住,如果你的form是多重继承下来的,例如:formc派生于formb,而formb又派生于forma,那么,仅仅需要forma从imeform派生即可。
方法二的使用优势是明显的,把ime的事件从form最上一层就截取了,避免了在您的form中控件的多样性所带来的困扰。

  还有,网上有一些说的调整imemode和使用imemodechanged方法来解决这个问题,建议你暂时(只是暂时)不要使用,因为修改imemode根本不能解决窗口切换时输入法自动变全角的问题,而且imemodechanged是在imemode改变的时候才触发,在用户手工操作输入法状态改变时(比如按ctrl+shift)是不会触发的。


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons