天天看點

注意使用者體驗細節--把窗體控件輸入由全角轉換為半角

有一次,一個使用者埋怨,說我輸入的電子郵件内容是正常的,為什麼不允許輸入,儲存不成功,老是提示格式有問題。

又有一次,另外一個使用者埋怨,為輸入的數字式正确的,可以跳出數字輸入控件後,内容有變為0了,怎麼回事呢?

諸如此類的問題,你可能自己也會碰到,究其原因,就是在桌面程式中,當你在文本框或者數字輸入框中輸入内容的時候,輸入法莫名奇妙的由半角變為全角,你沒有發現,繼續填寫或者儲存,就會出現問題。

如果我們不注意這些細節,使用者輸入的内容部經過驗證,他們在資料查詢檢索的時候,就會找不到内容,或者出現莫名其妙的錯誤,這是我們不願意看到的。

其實解決這個問題,做好這個細節問題的處理預防,是很簡單的事情,下面我來介紹一個輔助類,調用一下他的函數就可以了,如下所示。

     /// <summary>

    /// 輸入法幫助,全角 轉換為半角

    /// </summary>

    public class ImeHelper

    {

        #region 聲明一些API函數

        [DllImport("imm32.dll")]

        public static extern IntPtr ImmGetContext(IntPtr hwnd);

        public static extern bool ImmGetOpenStatus(IntPtr himc);

        public static extern bool ImmSetOpenStatus(IntPtr himc, bool b);

        public static extern bool ImmGetConversionStatus(IntPtr himc, ref int lpdw, ref int lpdw2);

        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);

        }

        /// 重載SetIme,傳入Control

        /// <param name="ctl"></param>

        public static void SetIme(Control ctl)

            ChangeAllControl(ctl);

        /// 重載SetIme,傳入對象句柄

        /// <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);

        /// 控件的Enter處理程式

        /// <param name="sender"></param>

        /// <param name="e"></param>

        static void ctl_Enter(object sender, EventArgs e)

        private static void ChangeControlIme(object sender)

            Control ctl = (Control)sender;

            ChangeControlIme(ctl.Handle);

        /// 下面這個函數才是真正檢查輸入法的全角半角狀态

        /// <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);  //轉換成半角

                    }

                }

    }

繼續閱讀