none
WPF的TEXTBOX只輸入數字 使用PreviewKeyDown e.key 但是key.numpad只能用英文輸入 不能使用中文輸入 RRS feed

  • 問題

  •  各位大大您好,程式碼如下

    WPF的TEXTBOX只輸入數字 使用PreviewKeyDown  e.key  但是這些key只能用英文輸入 不能使用中文輸入 我想要讓key.numpad可以使用中文輸入

    查到的原因是使用中文輸入法KeyCode 全為 229

    private void textBoxStartNumber_PreviewKeyDown(object sender, KeyEventArgs e)
            {
                if (e.Key != Key.D0 && e.Key != Key.D1 && e.Key != Key.D2 && e.Key != Key.D3 && e.Key != Key.D4 && e.Key != Key.D5 && e.Key != Key.D6 && e.Key != Key.D7 && e.Key != Key.D8 && e.Key != Key.D9 && e.Key != Key.Back && e.Key !=  Key.NumPad0 && e.Key != Key.NumPad1 && e.Key != Key.NumPad2 && e.Key != Key.NumPad3 && e.Key != Key.NumPad4 && e.Key != Key.NumPad5 && e.Key != Key.NumPad6 && e.Key != Key.NumPad7 && e.Key != Key.NumPad8 && e.Key != Key.NumPad9 && e.Key != Key.Delete && e.Key != Key.Right && e.Key != Key.Left)
                {
                    e.Handled = true ;
                }
            }

    請問如何在可以使用中文輸入法 然後key.numpad可以使用 謝謝各位大大

    2017年8月4日 上午 03:02

解答

  • InputMethod.SetIsInputMethodEnabled设置为false即可。

    • 已標示為解答 Eden Knight 2017年8月18日 上午 07:59
    • 已編輯 [-] 2018年1月11日 上午 11:35
    2017年8月9日 上午 11:47
  • 在您的基礎上,簡化一些步驟后給出另外一個版本的:

    1)XAML:乾脆禁用輸入法輸入東西(因為輸入法一般不是用於輸入數字,而是漢字或者其它符號的,這裡禁用,模仿NumericInput的控件):

    <TextBox x:Name="txtNumeric"

    HorizontalAlignment="Left" Height="23"

    Margin="192,130,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"

    InputMethod.IsInputMethodEnabled="False"/>

    2)代碼:

     private void txtNumeric_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
            {
                TextBox textBox = sender as TextBox;
                //獲取當前光標點選的位置,保存起來
    
                TextChange[] changes = new TextChange[e.Changes.Count];
                e.Changes.CopyTo(changes, 0);
    
                //捕捉當前滑鼠或者指針粘貼位置的變數
                int offset = changes[0].Offset;
                int totalCount = changes[0].AddedLength;
    
                //當前總共增加了多少字符,大於0開始操作
                if (totalCount > 0)
                {
                    //把全部的字串拷貝當前的字串到臨時區域
                    char[] charArray = new char[textBox.Text.Length];
                    textBox.Text.CopyTo(0, charArray, 0, charArray.Length);
                    StringBuilder sbu = new StringBuilder(new string(charArray));
    
                    //從增加的那個變數位置開始檢測是否是Number,不是的話直接幹掉當前字符
                    for (int i = sbu.Length - 1; i >= offset; --i)
                    {
                        if (charArray[i] < 48 || charArray[i] > 57)
                        {
                            sbu = sbu.Remove(i, 1);
                        }
                    }
                    //因為直接對Text操作,所以只能這樣,否則調用AppendText等其它方式會引發死循環(TextBoxChanged)
                    textBox.Text = sbu.ToString();
                    //當前發生的位置+總的輸入字符長度(光標定位在後面)
                    textBox.Select(offset+totalCount, 0);
                }
            }

    3、實測效果:


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    • 已標示為解答 Eden Knight 2017年8月18日 上午 07:59
    2017年8月9日 下午 01:44
  • WPF/SL中如何在TextBox屏蔽中屏蔽输入法

    這網站內容可以幫助您

    測試過後  是會強制只能輸入英數

    剩下的就看樓主怎麼應用了

    • 已標示為解答 Eden Knight 2017年8月18日 上午 07:58
    2017年8月10日 上午 10:01
  • 程式已修改完成,感謝各位大大!!

    程式碼如下:

    <TextBox x:Name="textBoxStartNumber" HorizontalAlignment="Left" Height="40" Margin="275,270,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="270" FontSize="28" PreviewKeyDown="textBoxStartNumber_PreviewKeyDown" TextChanged="textBoxStartNumber_TextChanged" InputMethod.IsInputMethodEnabled="False" />

    private void textBoxStartNumber_PreviewKeyDown(object sender, KeyEventArgs e)

    {

    if (e.Key == Key.Space || e.Key == Key.Back)

    {

    e.Handled = true;

    }

    if (e.Key != Key.D0 && e.Key != Key.D1 && e.Key != Key.D2 && e.Key != Key.D3 && e.Key != Key.D4 && e.Key != Key.D5 && e.Key != Key.D6 && e.Key != Key.D7 && e.Key != Key.D8 && e.Key != Key.D9 && e.Key != Key.Back && e.Key != Key.NumPad0 && e.Key != Key.NumPad1 && e.Key != Key.NumPad2 && e.Key != Key.NumPad3 && e.Key != Key.NumPad4 && e.Key != Key.NumPad5 && e.Key != Key.NumPad6 && e.Key != Key.NumPad7 && e.Key != Key.NumPad8 && e.Key != Key.NumPad9 && e.Key != Key.Delete && e.Key != Key.Right && e.Key != Key.Left)

    {

    e.Handled = true;

    } }


    • 已編輯 Eden Knight 2017年8月18日 上午 07:58 字型不一
    • 已標示為解答 Eden Knight 2018年3月9日 上午 02:08
    2017年8月18日 上午 07:56

所有回覆

  • 我有些糊塗……你是需要你的文本框只允許輸入:

    1)正體字(漢字)。

    2)任何的數字。

    其它都不允許嗎?


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月5日 上午 07:59
  • 我是想要只輸入任何的數字,不能輸入漢字。我在使用英文輸入法時,可以只輸入數字,但是當我使用注音輸入法時,就無法輸入數字(所有鍵盤都不能輸入)。請問可否使用注音輸入法時,也可使用Numpad只輸入數字。
    2017年8月7日 上午 02:51
  • Windows发送的输入消息有两类,一类叫击键消息,一类叫字符消息。在.Net里无法直接接收字符消息,因此也就无法直接拦截字符。击键消息通常用于处理Ctrl、Alt这类的控制键,以便实现快捷键操作,不能用来判定内容。其实这个问题并不仅限于输入法,虚拟键盘、手写识别、语音识别,甚至是条码扫描仪输入,等等这些都不会产生包含与字符相关虚拟键值的击键消息。

    所有涉及内容限制的功能,在.Net中都应该直接判断内容,在WPF中就是TextBox的Text值。如果String的内容符合你的要求,比如都是数字,那么就将其缓存下来,如果不符合,就用之前缓存的内容去覆盖用户的输入。不应该使用击键消息来处理与内容相关的问题。

    WPF應該有實體處理實體輸入文字的方法(PreviewTextInput)的Text字段即可獲得。但是我同意你后面的說法,如WinForm中的KeyPressed可以獲取實際輸入的內容+KeyDown獲取不可見字符(或者組合鍵)一樣。WPF應該使用PreviewKeyDown+PreviewTextInput組合分別判定不同的鍵值內容。

    @樓主:

    不過請注意,該事件不能直接與TextBox綁定,必須使用Manager預先綁定,這樣直接在事件冒泡的時候過濾掉了。這裡假設我的TextBox名稱為“txtNumeric”

    using System.Text.RegularExpressions;
    using System.Windows;
    using System.Windows.Input;
     
    namespace WpfApplication1
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            private static Regex _regExp = new Regex(@"\d");
            public MainWindow()
            {
                InitializeComponent();
     
                //請不要直接綁定,必須用TextCompositionManager綁定偵聽,否則輸入漢字仍然會得到相應。
                TextCompositionManager.AddPreviewTextInputStartHandler(txtNumericable, txtNumericable_PreviewTextInput);
            }
            /// <summary>
            /// 處理實際輸入的內容的事件
            /// </summary>
            private void txtNumericable_PreviewTextInput(object senderSystem.Windows.Input.TextCompositionEventArgs e)
            {
                string singleValue = e.Text;
                e.Handled = !_regExp.Match(singleValue).Success;
            }
            /// <summary>
            /// 處理鍵盤的非實際字符事件
            /// </summary>
            private void txtNumericable_PreviewKeyDown(object senderKeyEventArgs e)
            {
                if (e.Key == Key.Space || e.Key == Key.Back)
                {
                    e.Handled = true;
                }
            }
        }
    }

    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report

    2017年8月7日 上午 07:48
  • Yes。:)

    WinForm中:KeyPressed(判断可见字符)+KeyDown(不可见字符)。

    WPF:PreviewTextInput(可见字符)+PreviewKeyDown(不可见字符)。

    需要組合的。


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月7日 上午 10:03
  • 我实际创建了一个WPF程序后测试了一下,然后发现这种去处理键盘消息的方法还是不行,因为粘贴和用鼠标从其它应用中拖入文本不会产生键盘消息。所以我还是建议直接判断TextBox的Text内容,否则必须针对所有可能的输入方式进行处理。

    可惜沒有KeyPressed事件直接檢測文本內容變化!

    你知道嗎?TextChanged也會有問題耶!那就是當你對Text變數改變,會不會引發死循環呢?

    我測試下來,單純對TextBox的Text賦值不會,但是如果調用AppendText或者拼接“+=某個String”,會引起死循環……

    所以最終的策略是我拷貝全部的文本,刪除不要的內容即可。

    不知道你有何良策?還請提供哦,不靈賜教!


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report

    2017年8月8日 上午 06:47
  • 看錯了,看到Windows Forms,眼花@@


    2017年8月8日 上午 10:00
  • 電腦神手吳子陵:

    WPF沒有這個事件……:(


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月8日 上午 10:10
  • 鍵盤處理應該是可行的,就針對樓主的問題而言應該可以完全滿足。

    不過如果要嚴謹一些,處理全部的事件(包括粘貼等……)或許兩個事件要分別加內容了,而且不像WinForm,WPF找了半日找不到處理文本框捕獲的函數WndProc,所以只能自己寫一個,這樣只要一個事件也不會死循環。

     private void txtNumeric_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
            {
                TextBox textBox = sender as TextBox;
                TextChange[] changes = new TextChange[e.Changes.Count];
                e.Changes.CopyTo(changes, 0);
    
                //捕捉當前花鼠或者指針粘貼位置的變數
                int offset = changes[0].Offset;
                int totalCount = changes[0].AddedLength;
    
                //當前總共增加了多少字符,大於0開始操作
                if (totalCount > 0)
                {
                    //把全部的字串拷貝當前的字串到臨時區域
                    char[] charArray = new char[textBox.Text.Length];
                    textBox.Text.CopyTo(0, charArray, 0, charArray.Length);
                    StringBuilder sbu = new StringBuilder(new string(charArray));
    
                    //從增加的那個變數位置開始檢測是否是Number,不是的話直接幹掉當前字符
                    for (int i = sbu.Length - 1; i >= offset; --i)
                    {
                        if (charArray[i] < 48 || charArray[i] > 57)
                        {
                            sbu = sbu.Remove(i, 1);
                        }
                    }
                    //因為直接對Text操作,所以只能這樣,否則調用AppendText等其它方式會引發死循環(TextBoxChanged)
                    textBox.Text = sbu.ToString();
                    textBox.Select(textBox.Text.Length, 0);
                }
            }

    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report







    2017年8月8日 上午 11:43
  • 啊对不起,你把AppendText注释掉即可,我的代码已经更新了哦,烦请指教!

    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report




    2017年8月9日 上午 08:23
  • 代码:

     private void txtNumeric_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
            {
                TextBox textBox = sender as TextBox;
                TextChange[] changes = new TextChange[e.Changes.Count];
                e.Changes.CopyTo(changes, 0);
    
                //捕捉當前花鼠或者指針粘貼位置的變數
                int offset = changes[0].Offset;
                int totalCount = changes[0].AddedLength;
    
                //當前總共增加了多少字符,大於0開始操作
                if (totalCount > 0)
                {
                    //把全部的字串拷貝當前的字串到臨時區域
                    char[] charArray = new char[textBox.Text.Length];
                    textBox.Text.CopyTo(0, charArray, 0, charArray.Length);
                    StringBuilder sbu = new StringBuilder(new string(charArray));
    
                    //從增加的那個變數位置開始檢測是否是Number,不是的話直接幹掉當前字符
                    for (int i = sbu.Length - 1; i >= offset; --i)
                    {
                        if (charArray[i] < 48 || charArray[i] > 57)
                        {
                            sbu = sbu.Remove(i, 1);
                        }
                    }
                    //因為直接對Text操作,所以只能這樣,否則調用AppendText等其它方式會引發死循環(TextBoxChanged)
                    textBox.Text = sbu.ToString();
                    textBox.Select(textBox.Text.Length, 0);
                }
            }

    测试效果:


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月9日 上午 08:34
  • 我上面的代码在使用其它输入法时都没有问题,唯独在使用win10自带的输入法时会抛出System.ExecutionEngineException,目前还没搞懂是怎么回事。
    你可以用ScreenToGIF像我一樣錄製Bug視頻(GIF圖像)傳上來看看。我用Win8無法模擬問題耶。

    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月9日 上午 11:42
  • InputMethod.SetIsInputMethodEnabled设置为false即可。

    • 已標示為解答 Eden Knight 2017年8月18日 上午 07:59
    • 已編輯 [-] 2018年1月11日 上午 11:35
    2017年8月9日 上午 11:47
  • 在您的基礎上,簡化一些步驟后給出另外一個版本的:

    1)XAML:乾脆禁用輸入法輸入東西(因為輸入法一般不是用於輸入數字,而是漢字或者其它符號的,這裡禁用,模仿NumericInput的控件):

    <TextBox x:Name="txtNumeric"

    HorizontalAlignment="Left" Height="23"

    Margin="192,130,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"

    InputMethod.IsInputMethodEnabled="False"/>

    2)代碼:

     private void txtNumeric_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
            {
                TextBox textBox = sender as TextBox;
                //獲取當前光標點選的位置,保存起來
    
                TextChange[] changes = new TextChange[e.Changes.Count];
                e.Changes.CopyTo(changes, 0);
    
                //捕捉當前滑鼠或者指針粘貼位置的變數
                int offset = changes[0].Offset;
                int totalCount = changes[0].AddedLength;
    
                //當前總共增加了多少字符,大於0開始操作
                if (totalCount > 0)
                {
                    //把全部的字串拷貝當前的字串到臨時區域
                    char[] charArray = new char[textBox.Text.Length];
                    textBox.Text.CopyTo(0, charArray, 0, charArray.Length);
                    StringBuilder sbu = new StringBuilder(new string(charArray));
    
                    //從增加的那個變數位置開始檢測是否是Number,不是的話直接幹掉當前字符
                    for (int i = sbu.Length - 1; i >= offset; --i)
                    {
                        if (charArray[i] < 48 || charArray[i] > 57)
                        {
                            sbu = sbu.Remove(i, 1);
                        }
                    }
                    //因為直接對Text操作,所以只能這樣,否則調用AppendText等其它方式會引發死循環(TextBoxChanged)
                    textBox.Text = sbu.ToString();
                    //當前發生的位置+總的輸入字符長度(光標定位在後面)
                    textBox.Select(offset+totalCount, 0);
                }
            }

    3、實測效果:


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    • 已標示為解答 Eden Knight 2017年8月18日 上午 07:59
    2017年8月9日 下午 01:44
  • WPF/SL中如何在TextBox屏蔽中屏蔽输入法

    這網站內容可以幫助您

    測試過後  是會強制只能輸入英數

    剩下的就看樓主怎麼應用了

    • 已標示為解答 Eden Knight 2017年8月18日 上午 07:58
    2017年8月10日 上午 10:01
  • 程式已修改完成,感謝各位大大!!

    程式碼如下:

    <TextBox x:Name="textBoxStartNumber" HorizontalAlignment="Left" Height="40" Margin="275,270,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="270" FontSize="28" PreviewKeyDown="textBoxStartNumber_PreviewKeyDown" TextChanged="textBoxStartNumber_TextChanged" InputMethod.IsInputMethodEnabled="False" />

    private void textBoxStartNumber_PreviewKeyDown(object sender, KeyEventArgs e)

    {

    if (e.Key == Key.Space || e.Key == Key.Back)

    {

    e.Handled = true;

    }

    if (e.Key != Key.D0 && e.Key != Key.D1 && e.Key != Key.D2 && e.Key != Key.D3 && e.Key != Key.D4 && e.Key != Key.D5 && e.Key != Key.D6 && e.Key != Key.D7 && e.Key != Key.D8 && e.Key != Key.D9 && e.Key != Key.Back && e.Key != Key.NumPad0 && e.Key != Key.NumPad1 && e.Key != Key.NumPad2 && e.Key != Key.NumPad3 && e.Key != Key.NumPad4 && e.Key != Key.NumPad5 && e.Key != Key.NumPad6 && e.Key != Key.NumPad7 && e.Key != Key.NumPad8 && e.Key != Key.NumPad9 && e.Key != Key.Delete && e.Key != Key.Right && e.Key != Key.Left)

    {

    e.Handled = true;

    } }


    • 已編輯 Eden Knight 2017年8月18日 上午 07:58 字型不一
    • 已標示為解答 Eden Knight 2018年3月9日 上午 02:08
    2017年8月18日 上午 07:56