Как обнаружить нажатую клавишу?

на Windows Forms, вы можете узнать, в любое время, текущее положение курсора благодаря курсоры класса.

то же самое, похоже, недоступно для клавиатуры. Можно ли узнать, например,Shift клавиша нажата?

абсолютно ли необходимо отслеживать каждое уведомление клавиатуры (события KeyDown и KeyUp)?

11 ответов


if ((Control.ModifierKeys & Keys.Shift) != 0) 

Это также будет верно, если Ctrl+Shift вниз. Если вы хотите проверить, нажата ли только Shift,

if (Control.ModifierKeys == Keys.Shift)

если вы находитесь в классе, который наследует Control (например, форма), вы можете удалить Control.


приведенный ниже код позволяет обнаружить почти все нажатые в данный момент клавиши, а не только 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;
    }
}

вы также можете посмотреть следующее, Если вы ссылаетесь на систему.Окна.Ввод

if (Keyboard.Modifiers == ModifierKeys.Shift)

пространство имен клавиатуры также может использоваться для проверки состояния нажатия других клавиш с помощью клавиатуры.IsKeyDown (Key), или если вы подписываетесь на KeyDownEvent или подобное событие, аргументы события несут список нажатых в данный момент клавиш.


большинство из этих ответов либо слишком сложны, либо не работают для меня (например, System.Окна.Ввод, похоже,не существует). Затем я нашел пример кода, который отлично работает: 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);
    }
  }
}

начиная с .NET Framework версии 3.0, можно использовать Keyboard.IsKeyDown метод из нового System.Windows.Input пространство имен. Например:

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

даже если это часть WPF, этот метод отлично работает для приложений WinForm (при условии, что вы добавляете ссылки на сборок presentationcore.dll файлы и WindowsBase.dll файлы). К сожалению, однако, версии 3.0 и 3.5 Keyboard.IsKeyDown метод не работал для приложений WinForm. Поэтому, если вы хотите использовать это в приложении WinForm, вам нужно будет ориентироваться на .NET Framework 4.0 или более поздней версии, чтобы он работал.


вы можете P / Invoke вплоть до Win32 GetAsyncKeyState для проверки любой клавиши на клавиатуре.

вы можете передавать значения из перечисления ключей (например, ключи.Shift) для этой функции, поэтому для ее добавления требуется всего несколько строк кода.


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

if (Form.ModifierKeys == Keys.Shift)

работает для текстового поля, если приведенный выше код находится в событии keydown формы, и никакой другой элемент управления не захватывает событие keydown для ключа вниз.

также можно пожелать остановить дальнейшую обработку ключей с помощью:

e.Handled = true;

if (Control.ModifierKeys == Keys.Shift)
    //Shift is pressed

позиция курсора x/y является свойством, а нажатие клавиши (например, щелчок мыши / mousemove) является событием. Рекомендуется, как правило, позволить интерфейсу управляться событиями. Примерно единственный раз, когда вам понадобится выше, - это если вы пытаетесь сделать shift + mouseclick.


лучший способ, который я нашел для управления вводом клавиатуры в форме Windows Forms, - это обработать его после нажатия клавиши и до того, как сфокусированный элемент управления получит событие. Microsoft поддерживает встроенный Form - свойство уровня с именем .KeyPreview чтобы облегчить эту точную вещь:

public frmForm()
{
    // ...
    frmForm.KeyPreview = true;
    // ...
}

затем события _keydown, _KeyPress и / или _KeyUp формы могут быть маршалированы для доступа к входным событиям до того, как сфокусированный элемент управления формой их увидит, и вы можете применить обработчик логика, чтобы захватить событие там или позволить ему пройти через сфокусированный элемент управления формой.

хотя и не так структурно изящно, как в XAML это!--10--> архитектура маршрутизации событий, это делает управление функциями уровня формы в Winforms намного проще. Вижу MSDN примечания на KeyPreview для предостережения.


В WinForms:

if( Form.ModifierKeys == Keys.Shift )

это звучит как дубликат вопроса переполнения стека клавиша Detect Shift нажата без использования событий в Windows Forms?.