注意用户体验细节--把窗体控件输入由全角转换为半角
有一次,一个用户埋怨,说我输入的电子邮件内容是正常的,为什么不允许输入,保存不成功,老是提示格式有问题。
又有一次,另外一个用户埋怨,为输入的数字式正确的,可以跳出数字输入控件后,内容有变为0了,怎么回事呢?
诸如此类的问题,你可能自己也会碰到,究其原因,就是在桌面程序中,当你在文本框或者数字输入框中输入内容的时候,输入法莫名奇妙的由半角变为全角,你没有发现,继续填写或者保存,就会出现问题。
如果我们不注意这些细节,用户输入的内容部经过验证,他们在数据查询检索的时候,就会找不到内容,或者出现莫名其妙的错误,这是我们不愿意看到的。
其实解决这个问题,做好这个细节问题的处理预防,是很简单的事情,下面我来介绍一个辅助类,调用一下他的函数就可以了,如下所示。
///
<summary>
///
输入法帮助,全角 转换为半角
///
</summary>
public
class
ImeHelper
{
#region
声明一些API函数
[DllImport(
"
imm32.dll
"
)]
public
static
extern
IntPtr ImmGetContext(IntPtr hwnd);
[DllImport(
"
imm32.dll
"
)]
public
static
extern
bool
ImmGetOpenStatus(IntPtr himc);
[DllImport(
"
imm32.dll
"
)]
public
static
extern
bool
ImmSetOpenStatus(IntPtr himc,
bool
b);
[DllImport(
"
imm32.dll
"
)]
public
static
extern
bool
ImmGetConversionStatus(IntPtr himc,
ref
int
lpdw,
ref
int
lpdw2);
[DllImport(
"
imm32.dll
"
)]
public
static
extern
int
ImmSimulateHotKey(IntPtr hwnd,
int
lngHotkey);
public
const
int
IME_CMODE_FULLSHAPE
=
0x8
;
public
const
int
IME_CHOTKEY_SHAPE_TOGGLE
=
0x11
;
#endregion
///
<summary>
///
重载SetIme,传入Form
///
</summary>
///
<param name="frm"></param>
public
static
void
SetIme(Form frm)
{
frm.Paint
+=
new
PaintEventHandler(frm_Paint);
ChangeAllControl(frm);
}
///
<summary>
///
重载SetIme,传入Control
///
</summary>
///
<param name="ctl"></param>
public
static
void
SetIme(Control ctl)
{
ChangeAllControl(ctl);
}
///
<summary>
///
重载SetIme,传入对象句柄
///
</summary>
///
<param name="Handel"></param>
public
static
void
SetIme(IntPtr Handel)
{
ChangeControlIme(Handel);
}
private
static
void
ChangeAllControl(Control ctl)
{
//
在控件的的Enter事件中触发来调整输入法状态
ctl.Enter
+=
new
EventHandler(ctl_Enter);
//
遍历子控件,使每个控件都用上Enter的委托处理
foreach
(Control ctlChild
in
ctl.Controls)
{
ChangeAllControl(ctlChild);
}
}
static
void
frm_Paint(
object
sender, PaintEventArgs e)
{
/**/
/*
有人问为什么使用Pain事件,而不用Load事件或Activated事件,是基于下列考虑:
* 、在您的Form中,有些控件可能是运行时动态添加的
* 、在您的Form中,使用到了非.NET的OCX控件
* 、Form调用子Form的时候,Activated事件根本不会触发
*/
ChangeControlIme(sender);
}
///
<summary>
///
控件的Enter处理程序
///
</summary>
///
<param name="sender"></param>
///
<param name="e"></param>
static
void
ctl_Enter(
object
sender, EventArgs e)
{
ChangeControlIme(sender);
}
private
static
void
ChangeControlIme(
object
sender)
{
Control ctl
=
(Control)sender;
ChangeControlIme(ctl.Handle);
}
///
<summary>
///
下面这个函数才是真正检查输入法的全角半角状态
///
</summary>
///
<param name="h"></param>
private
static
void
ChangeControlIme(IntPtr h)
{
IntPtr HIme
=
ImmGetContext(h);
if
(ImmGetOpenStatus(HIme))
//
如果输入法处于打开状态
{
int
iMode
=
0
;
int
iSentence
=
0
;
bool
bSuccess
=
ImmGetConversionStatus(HIme,
ref
iMode,
ref
iSentence);
//
检索输入法信息
if
(bSuccess)
{
if
((iMode
&
IME_CMODE_FULLSHAPE)
>
0
)
//
如果是全角
{
ImmSimulateHotKey(h, IME_CHOTKEY_SHAPE_TOGGLE);
//
转换成半角
}
}
}
}
}