ImeHelper.cs
====================================================================================================================
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ChangeImeFromFullToHalf
{
/// <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)
{
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事件中触发来调整输入法状态
//遍历子控件,使每个控件都用上Enter的委托处理
foreach (Control ctlChild in ctl.Controls)
{
ctlChild.Paint += new PaintEventHandler(frm_Paint);
ctlChild.Enter += new EventHandler(ctl_Enter);
ctlChild.TextChanged += new EventHandler(ctl_TextChanged);
ctlChild.KeyDown += new KeyEventHandler(ctl_KeyDown);
//DataGridView中Cell进行特殊处理
if (ctlChild is DataGridView)
{
DataGridView dgv = ctlChild as DataGridView;
dgv.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dgv_EditingControlShowing);
}
ChangeAllControl(ctlChild);
}
}
static void ctl_TextChanged(object sender, EventArgs e)
{
bool b = false;
TextBox txt = null;
ComboBox cmb = null;
RichTextBox rtb = null;
DataGridTextBox dgtb = null;
if (sender is TextBox)
txt = sender as TextBox;
else if (sender is ComboBox)
cmb = sender as ComboBox;
else if (sender is RichTextBox)
rtb = sender as RichTextBox;
else if (sender is DataGridTextBox)
dgtb = sender as DataGridTextBox;
char[] c = null;
if (b == false)
{
if (txt != null)
c = txt.Text.ToCharArray();
else if (cmb != null)
c = cmb.Text.ToCharArray();
else if (rtb != null)
c = rtb.Text.ToCharArray();
else if (dgtb != null)
c = dgtb.Text.ToCharArray();
if (c == null)
return;
for (int i = 0; i < c.Length; i++)
{
if (c[i] == 12288)
{
c[i] = (char)32;
continue;
}
if (c[i] > 65280 && c[i] < 65375)
c[i] = (char)(c[i] - 65248);
}
}
b = true;
if (txt != null)
{
txt.Text = new string(c);
txt.SelectionStart = txt.Text.Length;
}
else if (cmb != null)
{
cmb.Text = new string(c);
cmb.SelectionStart = cmb.Text.Length;
}
else if (rtb != null)
{
rtb.Text = new string(c);
rtb.SelectionStart = rtb.Text.Length;
}
else if (dgtb != null)
{
dgtb.Text = new string(c);
dgtb.SelectionStart = dgtb.Text.Length;
}
}
static void ctl_KeyDown(object sender, KeyEventArgs e)
{
ChangeControlIme(sender);
}
public 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);
}
//编辑单元格控件发生事件
static void dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
DataGridView dgv = sender as DataGridView;
//获取列序号
int columnIndex = dgv.CurrentCell.ColumnIndex;
//单元格转化成文本框
TextBox tb = e.Control as TextBox;
//委托单元格KeyPress事件
tb.KeyPress += new KeyPressEventHandler(tb_KeyPress);
}
//单元格KeyPress事件
static void tb_KeyPress(object sender, KeyPressEventArgs e)
{
//全角转半角
if (e.KeyChar >= 65296 && e.KeyChar <= 65305)
{
e.KeyChar -= Convert.ToChar(65248);
}
}
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); //转换成半角
}
}
}
}
}
}
在基类窗体中进行调用
================================================================================================================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace ChangeImeFromFullToHalf
{
public partial class BaseFrm : Form
{
public BaseFrm()
{
InitializeComponent();
}
private void BaseFrm_Load(object sender, EventArgs e)
{
ImeHelper.SetIme(this);
}
}
}