C#RichTextBox全角问题!!忽略的KatakanaHalf!!

C#RichTextBox全角问题一直在困扰着我们,【ImeMode】属性的【OnHalf】无法设置,一点下去就变成了【On】值。恶心!!!憋气!!!

网上到处传的解决办法也有很多的弊端,诸如:

    class clsIme
    {
        #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

        ///  重载SetIme,传入Form 
        /// 
        public static void SetIme(Form frm)
        {
            frm.Paint += new PaintEventHandler(frm_Paint);
            ChangeAllControl(frm);
        }

        ///  重载SetIme,传入Control 
        /// 
        public static void SetIme(Control ctl)
        {
            ChangeAllControl(ctl);
        }
        //重载SetIme,传入对象句柄
        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事件,是基于下列考虑:
             * 1、在您的Form中,有些控件可能是运行时动态添加的
             * 2、在您的Form中,使用到了非.NET的OCX控件
              * 3、Form调用子Form的时候,Activated事件根本不会触发 */
            ChangeControlIme(sender);
        }
        //控件的Enter处理程序
        static void ctl_Enter(object sender, EventArgs e)
        {
            ChangeControlIme(sender);
        }
        private static void ChangeControlIme(object sender)
        {
            Control ctl = (Control)sender;
            ChangeControlIme(ctl.Handle);
        }
        //下面这个函数才是真正检查输入法的全角半角状态
        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);  // 如果是全角 转换成半角
                }
            }
        }
    }

    public partial class ImeForm : DockContent
    {
        public ImeForm()
        {
            InitializeComponent();
        }
        #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

        protected override void OnActivated(EventArgs e)
        {
            base.OnActivated(e);
            IntPtr HIme = ImmGetContext(this.Handle);
            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(this.Handle, IME_CHOTKEY_SHAPE_TOGGLE);  //转换成半角
                }
                else if ((iMode & IME_CMODE_FULLSHAPE) > 0)   //如果是全角
                    ImmSimulateHotKey(this.Handle, IME_CHOTKEY_SHAPE_TOGGLE);  //转换成半角
            }
        }
    }


这个用API不停的在监控,1~2S刷新一次,强制转换半角,如果碰到你想用全角的时候。。。

还有一个 ImeMode = ImeMode.KatakanaHalf;  这个方法不错,不过,一但有其他可供输入文字的  ***TextBox之类控件,那就抓瞎了,ImeMode = ImeMode.KatakanaHalf; 这个方法只能管一个***TextBox之类控件,多了的全部全角。汗!!!

假设,有comboBox1、TextBox1、RichTextBox1各一个, ImeMode全设为【On】,然后再在代码里添加下面几句:

            ImeMode = ImeMode.KatakanaHalf;
            richTextBox1.ImeMode = ImeMode.KatakanaHalf;
            textBox1.ImeMode = ImeMode.KatakanaHalf;

妥妥的,comboBox1会是全角。如果只加 ImeMode =  ImeMode .KatakanaHalf;  那全部都是全角。

要嘛在创建窗口时就设置ImeMode属性值为KatakanaHalf,要嘛后面一个一个的去改,要嘛就后面砸代码。三选一,自己选。

 ImeMode.KatakanaHalf是我们有意忽略还是故意忽略???看看说明就觉得一阵肝疼!!!


你可能感兴趣的:(.NET/C#,C#richTextBox,ImeMode,KatakanaHalf,全角问题)