zoukankan      html  css  js  c++  java
  • KeyDown,KeyPress和KeyUp详解(转)

    1.按键的类型

      Windows窗体将键盘输入标识为由按位Keys枚举表示的虚拟键代码。使用Keys枚举,可以综合一系列按键以生成单个值,这些值与WM_KEYDOWN和WM_SYSKEYDOWNWindows消息所伴随的值相对应。另外,程序开发人员可通过处理KeyDown或KeyUp 事件来检测大多数物理按键操作。字符键是Keys枚举的子集,它们与WM_CHAR和WM_SYSCHAR Windows消息所伴随的值相对应,如果通过组合按键得到一个字符,则可以通过处理KeyPress事件来检测该字符。

    2. 定义

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

    KeyPress:在控件有焦点的情况下按下键时发生。(下面会说和KeyDown 的区别)

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

    注意:KeyDown触发后,不一定触发KeyUp,当KeyDown 按下后,拖动鼠标,那么将不会触发KeyUp事件。

    3.键盘事件的顺序

      一个控件上可能出现3个与键盘相关的事件,下面是这些事件发生的常规顺序:

      用户按“a”键,该键将被预处理和调度,而且会发生KeyDown事件。 
      用户按住“a”键,该键将被预处理和调度,而且会发生KeyPress事件。 
      用户松开“a”键,该键将被预处理和调度,而且会发生KeyUp事件。
     
    4.键的预处理

      像其他消息一样,键盘消息是在窗体或控件的WndProc方法中处理的。窗体或控件在处理键盘消息之前,PreProcessMessage方法会调用一个或多个方法,这些方法可被重写以处理特殊的字符键和物理按键。


    5. KeyPress 和KeyDown 、KeyPress之间的区别

    KeyPress主要用来捕获数字(注意:包括Shift+数字的符号)、字母(注意:包括大小写)、小键盘等除了F1-12、SHIFT、Alt、Ctrl、Insert、Home、PgUp、Delete、End、PgDn、ScrollLock、Pause、NumLock、{菜单键}、{开始键}和方向键外的ANSI字符。
    KeyDown 和KeyUp 通常可以捕获键盘除了PrScrn所有按键(这里不讨论特殊键盘的特殊键)。 
    KeyPress 只能捕获单个字符 
    KeyDown 和KeyUp 可以捕获组合键(任何时候都可用Control.ModifierKeys属性获取SHIFT、Alt、Ctrl的状态,这对于不支持KeyDown 事件的控件非常有用)。 
    KeyPress 可以捕获单个字符的大小写 
    KeyDown和KeyUp 对于单个字符捕获的KeyValue 都是一个值,也就是不能判断单个字符的大小写。 (可通过.net 2.0中新增Control.IsKeyLocked(Keys.CapsLock)方法判断CapsLock的状态,类似,Scroll Lock和Num Lock也可通过Control.IsKeyLocked()方法来判断)。 
    KeyPress 不区分小键盘和主键盘的数字字符。 
    KeyDown 和KeyUp 区分小键盘和主键盘的数字字符。 
    其中PrScrn 按键KeyPress、KeyDown和KeyUp 都不能捕获。

    以上说明可以通过一些简单代码测试,例如:

    private void txtKey_KeyPress(object sender, KeyPressEventArgs e)
    {
      label1.Text = "key press:" + e.KeyChar.ToString();
    }

    private void txtKey_KeyDown(object sender, KeyEventArgs e)
    {
      label2.Text = "key code:" + e.KeyCode.ToString();
      label2.Text += " key value:" + e.KeyValue.ToString();
      label2.Text += " key data:" + e.KeyData.ToString();
    }

    6. 获取按键状态

    需获取各键状态,要用到GetKeyState()及GetAsyncKeyState()方法,如下:

    [DllImport("User32.dll")]
    private static extern short GetKeyState(System.Windows.Forms.Keys key);

    ......
    if (GetKeyState(Keys.Insert) == 1)
    {
      // Overwrite mode is on.
    }
    else
    {
      // Insert mode is on.
    }


    [DllImport("User32.dll")]
    private static extern short GetAsyncKeyState(System.Windows.Forms.Keys key);


    ...........

    short state = GetAsyncKeyState(Keys.D);
    switch (state)
    {
      case 0:
      lbl.Text = "D has not been pressed since the last call.";
      break;
      case 1:
      lbl.Text = "D is not currently pressed, but has been pressed since the last call.";
      break;
      case -32767:
      lbl.Text = "D is currently pressed.";
      break;
    }

    那么两者有什么区别呢?查了下,有人提到说:GetKeyState得到的结果是在获取到当前消息时的键盘上按键状态的一个映像,也就是说,这个状态不会随着按键真实按键状态的改变而改变。其实通常情况下得到这样非实时的结果就足够了。由于只是查表,所以速度较快,但是决不能写出下面的代码

    while(GetKeyState(nVirKey))

    {

      //code here

    }

      而要得到某一个键实时的状态,则应该使用GetAsyncKeyState,这个函数通过查询Driver而得到实时的信息。但是这个函数较GetKeyState慢。(这点还不大明白···)


    7. 系统组合键的判定

      在使用键盘的时候,通常会使用到CTRL+SHIFT+ALT 类似的组合键功能。对于此,我们如何来判定?

    通过KeyUp 事件能够来处理(这里说明一下为什么不用KeyDown,因为在判定KeyDown的时候,CTRL、SHIFT和ALT 属于一直按下状态,然后再加另外一个键是不能准确捕获组合键,所以使用KeyDown 是不能准确判断出的,要通过KeyUp 事件来判定 )

    这里简单的列举出CTRL+其它7键的组合判定代码:
    private void Form3_KeyUp(object sender, KeyEventArgs e)
    {
      if (e.Control)
      {
        MessageBox.Show("KeyUp:Ctrl+" + e.KeyValue.ToString());
      }
    }


    8. 捕获PrScrn按键事件

      通过一种钩子的方式可以判定PrScrn 按键事件,钩子可以获取任何键盘事件。

    这里给出CodeProject 上面的开源代码的解决方案。大家有兴趣自己研究吧:Global System Hooks in .NET 。


      其实我们按下一个键时,KeyDown和KeyPress是都要发生的,而且两个人看上去没有什么区别。但是其实两者还是有实质的区别的。

      例如:在一个多行文本框里面输入字符,为什么我们没有定义一个键盘响应事件,但是键盘却响应了,把字符输入到了文本框呢?其实我觉得因为这个事件就是系统默认的一个消息响应,它就KeyPress。如果你自己还给KeyPress定义了自己的响应的话,那么程序会先执行你定义的程序,然后完成系统要求的显示字符事件的响应过程,但是如果你在自己定义KeyPress事件如:private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)里面增加语句:e.Handled=true;那么系统要求的显示字符响应过程就不会被执行,原因就是这个语句的意思就是这个消息响应已经完成。但是如果你在KeyDown,KeyUp里面加这条语句,显示字符串等消息还是会发生,这说明系统的显示字符串和KeyDown,KeyUp是没有关系的,而对于回车和退格消息响应则是由KeyDown控制,增加那条语句则回车换行不会执行,退格响应也不会执行。

      综上:要屏蔽键盘上的一个字符的输入,可以在KeyPress里面进行增加语句,而要屏蔽回车和退格则可以在KeyDown里面进行增加语句。

    ==============================================================

    1.这三个事件的顺序是怎么样的?

    2.KeyDown 触发后,KeyUp是不是一定触发?

    3.三个事件的定义

    4.KeyDown、KeyUp 和KeyPress 之间的区别

    5.如何区分是否按的是小键盘?

    6.PrScrn按键三个事件能够捕获吗?

    7.{菜单键}和{开始键}KeyPress能够捕获吗?

    (一)键事件按下列顺序发生:

    KeyDown

    KeyPress

    KeyUp

    (二)KeyDown触发后,不一定触发KeyUp,当KeyDown 按下后,拖动鼠标,那么将不会触发KeyUp事件。

    (三)定义

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

    KeyPress:在控件有焦点的情况下按下键时发生。(下面会说和KeyDown 的区别)

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

    (四)KeyPress 和KeyDown 、KeyPress之间的区别

      1.KeyPress主要用来捕获数字(注意:包括Shift+数字的符号)、字母(注意:包括大小写)、小键盘等除了F1-12、SHIFT、Alt、Ctrl、Insert、Home、PgUp、Delete、End、PgDn、ScrollLock、Pause、NumLock、{菜单键}、{开始键}和方向键外的ANSI字符
        KeyDown 和KeyUp 通常可以捕获键盘除了PrScrn所有按键(这里不讨论特殊键盘的特殊键)

      2.KeyPress 只能捕获单个字符
        KeyDown 和KeyUp 可以捕获组合键。

      3.KeyPress 可以捕获单个字符的大小写

      4.KeyDown和KeyUp 对于单个字符捕获的KeyValue 都是一个值,也就是不能判断单个字符的大小写。

      5.KeyPress 不区分小键盘和主键盘的数字字符。
        KeyDown 和KeyUp 区分小键盘和主键盘的数字字符。

      6.其中PrScrn 按键KeyPress、KeyDown和KeyUp 都不能捕获。

  • 相关阅读:
    join_tab计算代价
    outer join test
    突然觉得mysql优化器蛮简单
    将数据库字段从float修改为decimal
    小米初体验
    简述安装android开发环境
    Rust语言:安全地并发
    awk里的各种坑
    ubuntu下使用C语言开发一个cgi程序
    Ubuntu下安装和配置Apache2
  • 原文地址:https://www.cnblogs.com/hello-web/p/7532134.html
Copyright © 2011-2022 走看看