如何检测当前按下的键?

121 .net c# keyboard winforms

Windows窗体中,由于Cursors类,您可以随时知道光标的当前位置.

键盘似乎没有相同的功能.是否可以知道,例如,Shift按键是否被按下?

是否有必要追踪每个键盘通知(KeyDown和KeyUp事件)?

SLa*_*aks 160

if ((Control.ModifierKeys & Keys.Shift) != 0) 
Run Code Online (Sandbox Code Playgroud)

如果Ctrl+ Shift下降,这也将成立.如果要检查是否按下Shift,

if (Control.ModifierKeys == Keys.Shift)
Run Code Online (Sandbox Code Playgroud)

如果您在继承的类Control(例如表单)中,则可以删除Control.

  • 除非我遗漏了什么,否则你没有正确回答这个问题.OP询问所有键并仅使用Shift键作为示例.那么如何检测其他键,如A到Z,0到9等. (7认同)
  • 而不是`(Control.ModifierKeys&Keys.Shift)!= 0`可以使用`Control.ModifierKeys.HasFlag(Keys.Shift)` (3认同)
  • 鉴于他接受了答案,似乎他只需要修改键.如果你想要其他键,你需要调用`GetKeyState` API函数. (2认同)
  • 不需要GetKeyState.您只需添加一个消息过滤器.看我的回答. (2认同)
  • 对于** WPF解决方案**,您可以使用`Keyboard.Modifiers == ModifierKeys.Shift`(对于那些来自搜索的对象) (2认同)

Ash*_*Ash 55

下面的代码是如何检测几乎所有当前按下的键,而不仅仅是Shift键.

private KeyMessageFilter m_filter = new KeyMessageFilter();

private void Form1_Load(object sender, EventArgs e)
{
    Application.AddMessageFilter(m_filter);
}


public class KeyMessageFilter : IMessageFilter
{
    private const int WM_KEYDOWN = 0x0100;
    private const int WM_KEYUP = 0x0101;
    private bool m_keyPressed = false;

    private Dictionary<Keys, bool> m_keyTable = new Dictionary<Keys, bool>();

    public Dictionary<Keys, bool> KeyTable
    {
        get { return m_keyTable; }
        private set { m_keyTable = value; }
    }

    public bool IsKeyPressed()
    {
        return m_keyPressed;
    }

    public bool IsKeyPressed(Keys k)
    {
        bool pressed = false;

        if (KeyTable.TryGetValue(k, out pressed))
        {
            return pressed;
        }

        return false;
    }

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            KeyTable[(Keys)m.WParam] = true;

            m_keyPressed = true;
        }

        if (m.Msg == WM_KEYUP)
        {
            KeyTable[(Keys)m.WParam] = false;

            m_keyPressed = false;
        }

        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Slaks,除非你有一些基准数据,否则你猜测.此外,GetKeyState将告诉您键的状态,*if*您可以在第一时间捕获该键盘事件.我对这个问题的解读是OP希望知道如何在任何时候*获取密钥的状态.所以GetKeyState本身就没用了. (3认同)
  • 你究竟如何利用它来显示按下的按键? (3认同)

Jef*_*ain 23

如果引用System.Windows.Input,也可以查看以下内容

if (Keyboard.Modifiers == ModifierKeys.Shift)
Run Code Online (Sandbox Code Playgroud)

Keyboard命名空间也可用于使用Keyboard.IsKeyDown(Key)检查其他键的按下状态,或者如果您订阅了KeyDownEvent或类似事件,则事件参数带有当前按下的键列表.

  • 实际上,Keyboard.Modifiers 并不总是能正常工作。必须找到困难的方法:http://discoveringdotnet.alexeyev.org/2008/09/keyboardmodifiers-sometimes-doesnt-work.html (2认同)

par*_*y72 17

大多数答案要么太复杂,要么似乎对我不起作用(例如System.Windows.Input似乎不存在).然后我找到了一些工作正常的示例代码:http: //www.switchonthecode.com/tutorials/winforms-accessing-mouse-and-keyboard-state

如果将来页面消失,我将在下面发布相关的源代码:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace MouseKeyboardStateTest
{
  public abstract class Keyboard
  {
    [Flags]
    private enum KeyStates
    {
      None = 0,
      Down = 1,
      Toggled = 2
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern short GetKeyState(int keyCode);

    private static KeyStates GetKeyState(Keys key)
    {
      KeyStates state = KeyStates.None;

      short retVal = GetKeyState((int)key);

      //If the high-order bit is 1, the key is down
      //otherwise, it is up.
      if ((retVal & 0x8000) == 0x8000)
        state |= KeyStates.Down;

      //If the low-order bit is 1, the key is toggled.
      if ((retVal & 1) == 1)
        state |= KeyStates.Toggled;

      return state;
    }

    public static bool IsKeyDown(Keys key)
    { 
      return KeyStates.Down == (GetKeyState(key) & KeyStates.Down);
    }

    public static bool IsKeyToggled(Keys key)
    { 
      return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • `System.Windows.Input`存在; 对于其他人来说,你需要添加对'PresentationCore`的引用,以及对`WindowsBase`的额外引用来访问`System.Windows.Input.Key`枚举.此信息始终可以在MSDN上找到. (3认同)
  • "如果将来页面消失,我会在下面发布相关的源代码" (2认同)

Ste*_*art 10

从.NET Framework 3.0版开始,可以使用Keyboard.IsKeyDownSystem.Windows.Input命名空间中的方法.例如:

if (((Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) && Keyboard.IsKeyDown(Key.F))
{
    // CTRL + F is currently pressed
}
Run Code Online (Sandbox Code Playgroud)

尽管它是WPF的一部分,但该方法适用于WinForm应用程序(前提是您添加了对PresentationCore.dllWindowsBase.dll的引用).不幸的是,3.0和3.5版本的Keyboard.IsKeyDown方法不适用于WinForm应用程序.因此,如果您确实想在WinForm应用程序中使用它,则需要将.NET Framework 4.0或更高版本作为目标才能使用.

  • @DiegoVieira实际上,那不是真的.该功能是作为WPF的一部分添加的,它要求引用那些WPF库,但是`Keyboard.IsKeyDown`方法可以工作,即使在WinForm项目中也是如此. (2认同)
  • 请注意,由于Win32KeyboardDevice.GetKeyStatesFromSystem(Key)的实现发生变化,如果以.Net 3.5或更早版本为目标,只有4.0+,这不起作用(在WinForms中):( (2认同)

Jas*_*ams 8

您可以P/Invoke到Win32 GetAsyncKeyState来测试键盘上的任何键.

您可以将Keys enum(例如Keys.Shift)中的值传递给此函数,因此只需要几行代码即可添加它.


小智 5

if ((ModifierKeys == Keys.Control) && ((e.KeyChar & (char)Keys.F) != 0))
{
     // CTRL+F pressed !
}
Run Code Online (Sandbox Code Playgroud)