• Winform下KeyDown,KeyPress,KeyUp事件的总结(转)


    原文: http://www.cnblogs.com/xiashengwang/archive/2011/09/15/2578798.html

    在winform程序中,经常会用到这几个事件用于控制数字输入,按键动作等操作,但一直没有完全弄清楚他们之间的区别和联系,到底什么时候用哪一个事件合适,闲暇无事,做了一个小小的总结,以免以后犯糊涂。

    1) 这三个事件调用的先后顺序(MSDN)

         1. KeyDown    :在控件有焦点的情况下按下键时发生

         2. KeyPress   :在控件有焦点的情况下按下键时发生。

         3. KeyUp         :在控件有焦点的情况下释放键时发生。

    2) KeyDown和KeyPress在MSDN上的解释完全一样,都是在按下键的时候发生,那区别是什么呢?

    1. textBox1_KeyDown(object sender, KeyEventArgs e)  
    2. textBox1_KeyPress(object sender, KeyPressEventArgs e)  
    3. textBox1_KeyUp(object sender, KeyEventArgs e)  

    从时间函数传入的事件参数可以看出,KeyDown和KeyUp用的是KeyEventArgs,KeyPress 用的是KeyPressEventArgs。

    查阅MSDN,KeyEventArgs 提供了KeyCode,KeyData等System.Windows.Forms.Keys里定义的枚举。如下:

    1. using System;  
    2. using System.ComponentModel;  
    3. using System.Drawing.Design;  
    4. using System.Runtime.InteropServices;  
    5.   
    6. namespace System.Windows.Forms  
    7. {  
    8.     // 概要:  
    9.     //     Specifies key codes and modifiers.  
    10.     [Flags]  
    11.     [ComVisible(true)]  
    12.     [TypeConverter(typeof(KeysConverter))]  
    13.     [Editor("System.Windows.Forms.Design.ShortcutKeysEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]  
    14.     public enum Keys  
    15.     {  
    16.         // 概要:  
    17.         //     The bitmask to extract modifiers from a key value.  
    18.         Modifiers = -65536,  
    19.         //  
    20.         // 概要:  
    21.         //     No key pressed.  
    22.         None = 0,  
    23.         //  
    24.         // 概要:  
    25.         //     The left mouse button.  
    26.         LButton = 1,  
    27.         //  
    28.         // 概要:  
    29.         //     The right mouse button.  
    30.         RButton = 2,  
    31.         //  
    32.         // 概要:  
    33.         //     The CANCEL key.  
    34.         Cancel = 3,  
    35.         //  
    36.         // 概要:  
    37.         //     The middle mouse button (three-button mouse).  
    38.         MButton = 4,  
    39.         //  
    40.         // 概要:  
    41.         //     The first x mouse button (five-button mouse).  
    42.         XButton1 = 5,  
    43.         //  
    44.         // 概要:  
    45.         //     The second x mouse button (five-button mouse).  
    46.         XButton2 = 6,  
    47.         //  
    48.         // 概要:  
    49.         //     The BACKSPACE key.  
    50.         Back = 8,  
    51.         //  
    52.         // 概要:  
    53.         //     The TAB key.  
    54.         Tab = 9,  
    55.         //  
    56.         // 概要:  
    57.         //     The LINEFEED key.  
    58.         LineFeed = 10,        
    59.         //  
    60.         // 概要:  
    61.         //     The CAPS LOCK key.  
    62.         Capital = 20,  
    63.         //内容太多了,略去。。。。。。  
    64.         // 概要:  
    65.         //     The ALT modifier key.  
    66.         Alt = 262144,  
    67.     }  
    68. }  

    KeyPressEventArgs里自只定义了个KeyChar,并且是char型的。因此:

    ----要处理与按键相关的操作只能在KeyDown里处理,如是否按了Ctrl键或是同时按下了Ctrl+A键,诸如此类的按键判断都应该在KeyDown里处理。(KeyUp也能获得按键信息,不过是在按键上升是触发)

    1. private void textBox1_KeyDown(object sender, KeyEventArgs e)  
    2. {  
    3.    //是否安了键盘的A键  
    4.     if (e.KeyCode == Keys.A)  
    5.     {  
    6.     }  
    7. }  

    ----要处理具体按下后的输出字符要用KeyPresss事件,比如验证是不是输入了数字,判断Ascii码即可。

    1. private void textBox1_KeyPress(object sender, KeyPressEventArgs e)  
    2. {  
    3.     if (e.KeyChar >= '0' && e.KeyChar <= '9')  
    4.     {  
    5.     }  
    6. }  


    在KeyDown里可以判断是不是按了数字键来判断,但是要同时判断键盘上的数字和小键盘的数字,不太可取。

    1. private void textBox1_KeyDown(object sender, KeyEventArgs e)  
    2. {  
    3.     if((e.KeyCode >= Keys.D0 && e.KeyCode <=Keys.D9) ||  
    4.         (e.KeyCode>= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9))  
    5.     {  
    6.     }  
    7. }  


    3)取消用户输入应该用什么方法?

    不要用户输入数字以外的字符,已经输入的字符如何取消呢?答案是可以在KeyPress里取消,也可以在KeyDown里取消。

    1, KeyPress里取消输入 (A不能输入)

    1. private void textBox1_KeyPress(object sender, KeyPressEventArgs e)  
    2. {  
    3.     if (e.KeyChar == 'A')  
    4.     {  
    5.         e.Handled = true;  
    6.     }  
    7. }  

    2,KeyDown里取消输入 (A不能输入)

    1. private void textBox1_KeyDown(object sender, KeyEventArgs e)  
    2. {  
    3.     if (e.KeyCode == Keys.A)  
    4.     {  
    5.         e.SuppressKeyPress();  
    6.     }  
    7. }  

    SuppressKeyPress方法可以取消KeyPress事件,注意此时KeyUp事件也被取消了(实验得知)。

    4)关于KeyDown和KeyUp

     KeyDown触发几次KeyUp就触发几次。

    1,按键盘的A键,KeyDwon和KeyUp各触发一次。

    KeyDown里的KeyEventArgs的值如下:(注意:KeyCode,Keydata,KeyValue里的值是伪代码,不一定和程序吻合,只是为了说明问题)

    KeyCode:Keys.A

    KeyData:Keys.A

    KeyValue:65

    KeyUp里的KeyEventArgs的值和KeyDown相同。

    2,按键盘的Ctrl+A,KeyDwon和KeyUp个触发两次。

    第一次KeyDown里的KeyEventArgs的值如下:

    KeyCode:Keys.ContrlKey

    KeyData:Keys.ContrlKey

    KeyValue:17

    第二次KeyDown里的KeyEventArgs的值如下:

    KeyCode:Keys.A

    KeyData:Keys.ContrlKey + Keys.A

    KeyValue:65

    第一次KeyUp里的KeyEventArgs的值如下:

     

    KeyCode:Keys.A

    KeyData:Keys.ContrlKey + Keys.A

    KeyValue:65

    第二次KeyUp里的KeyEventArgs的值如下:

     

    KeyCode:Keys.ContrlKey

    KeyData:Keys.ContrlKey

    KeyValue:17

    可以看出,KeyUp的顺序和KeyDown顺序是相反的,类似于栈,先进后出。

    5) 某些特殊键在控件上被默认处理的解决办法

    比如,TextBox上的TAB键就被默认处理的,在TextBox上按Tab键,将不会触发KeyDown已经后面的KeyPress和KeyUp事件,解决的办法是重新TextBox控件的IsInputKey方法,这个在MSDN上有说明,特实践证明了下,确实可行。

    1. class TextBoxEx :System.Windows.Forms.TextBox  
    2. {  
    3.   
    4.     protected override bool IsInputKey(System.Windows.Forms.Keys keyData)  
    5.     {  
    6.         if (keyData == System.Windows.Forms.Keys.Tab)  
    7.         {  
    8.             return true;  
    9.         }  
    10.         return base.IsInputKey(keyData);  
    11.     }  
    12. }  

    换用以上的TextBoxEx后,按下Tab键,就能触发KeyDown,KeyPress,KeyUp等事件了。


    以上纯属个人无事消遣,各位看官笑过就好。

  • 相关阅读:
    cf914D. Bash and a Tough Math Puzzle(线段树)
    RNQOJ [stupid]愚蠢的矿工(树形依赖背包)
    BZOJ4552: [Tjoi2016&Heoi2016]排序(线段树 二分)
    多项式系数学习笔记
    BZOJ4653: [Noi2016]区间(线段树 双指针)
    洛谷P3372 【模板】线段树 1(树状数组)
    BZOJ3261: 最大异或和(可持久化trie树)
    BZOJ4260: Codechef REBXOR (01Tire树)
    Android 关于显示键盘,布局错乱网上顶的问题
    Java 输入流读取文本文件换行符问题
  • 原文地址:https://www.cnblogs.com/lost0/p/10380516.html
Copyright © 2020-2023  润新知