Как обнаружить нажатую в данный момент клавишу? - PullRequest
121 голосов
/ 09 июля 2009

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

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

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

Ответы [ 11 ]

160 голосов
/ 09 июля 2009
if ((Control.ModifierKeys & Keys.Shift) != 0) 

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

if (Control.ModifierKeys == Keys.Shift)

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

54 голосов
/ 18 декабря 2009

Код ниже показывает, как обнаружить почти все в настоящее время нажатые клавиши, а не только клавишу 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;
    }
}
23 голосов
/ 09 июля 2009

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

if (Keyboard.Modifiers == ModifierKeys.Shift)

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

17 голосов
/ 20 февраля 2012

Большинство из этих ответов либо слишком сложны, либо, кажется, не работают для меня (например, 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);
    }
  }
}
10 голосов
/ 30 декабря 2012

Начиная с версии .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 или более позднюю версию, чтобы он работал.

8 голосов
/ 09 июля 2009

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

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

5 голосов
/ 21 сентября 2011
if ((ModifierKeys == Keys.Control) && ((e.KeyChar & (char)Keys.F) != 0))
{
     // CTRL+F pressed !
}
3 голосов
/ 03 октября 2011

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

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

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

Хотя структура маршрутизации событий 1010 * XAML не столь структурно изящна, она значительно упрощает управление функциями уровня формы в Winforms. См. Примечания MSDN к KeyPreview для уточнений.

2 голосов
/ 17 сентября 2011
if (Form.ModifierKeys == Keys.Shift)

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

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

e.Handled = true;
2 голосов
/ 09 июля 2009
if (Control.ModifierKeys == Keys.Shift)
    //Shift is pressed

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...