Как определить текущую нажатую клавишу?
В Windows Forms вы можете в любой момент узнать текущую позицию курсора благодаря Cursors.
То же самое, похоже, не доступно для клавиатуры. Можно ли узнать, нажата ли клавиша Shift?
Необходимо ли отслеживать каждое уведомление с клавиатуры (события KeyDown и KeyUp)?
Ответы
Ответ 1
if ((Control.ModifierKeys & Keys.Shift) != 0)
Это также верно, если Ctrl + Shift не работает. Если вы хотите проверить, нажата ли только Shift,
if (Control.ModifierKeys == Keys.Shift)
Если вы находитесь в классе, который наследует Control
(например, форму), вы можете удалить Control.
Ответ 2
Ниже приведен код, как обнаружить почти все нажатые клавиши, а не только клавишу 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;
}
}
Ответ 3
Вы также можете посмотреть следующее, если вы ссылаетесь на System.Windows.Input
if (Keyboard.Modifiers == ModifierKeys.Shift)
Пространство имен клавиатуры также может использоваться для проверки нажатого состояния других клавиш с Keyboard.IsKeyDown(Key), или если вы подписываетесь на KeyDownEvent или подобное событие, аргументы события содержат список нажатых клавиш.
Ответ 4
Большинство этих ответов слишком сложны или, похоже, не работают для меня (например, 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);
}
}
}
Ответ 5
Начиная с версии .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 или новее, чтобы он работал.
Ответ 6
Вы можете P/Invoke до Win32 GetAsyncKeyState для проверки любой клавиши на клавиатуре.
Вы можете передать значения из перечисления Keys (например, Keys.Shift) в эту функцию, поэтому для его добавления требуется только несколько строк кода.
Ответ 7
if ((ModifierKeys == Keys.Control) && ((e.KeyChar & (char)Keys.F) != 0))
{
// CTRL+F pressed !
}
Ответ 8
if (Control.ModifierKeys == Keys.Shift)
//Shift is pressed
Позиция курсора x/y является свойством, а нажатие клавиши (например, щелчок мышью /mousemove ) является событием. Лучшей практикой, как правило, является то, что интерфейс управляется событиями. Единственный раз, когда вам понадобится вышесказанное, вы пытаетесь сделать операцию shift + mouseclick.
Ответ 9
if (Form.ModifierKeys == Keys.Shift)
работает для текстового поля, если вышеуказанный код находится в событии keydown формы, и никакой другой элемент управления не захватывает событие keydown для нажатия клавиши.
Также можно отказаться от дальнейшей обработки ключа с помощью:
e.Handled = true;
Ответ 10
Лучший способ, которым я нашел управлять клавиатурой ввода в форме Windows Forms, - обработать ее после нажатия клавиши и до того, как сфокусированный элемент управления получит событие. Microsoft поддерживает встроенное свойство Form
-level с именем .KeyPreview, чтобы облегчить эту точную вещь:
public frmForm()
{
// ...
frmForm.KeyPreview = true;
// ...
}
Тогда события формы _KeyDown, _KeyPress и/или _KeyUp могут быть маршализованы для доступа к входным событиям, прежде чем сфокусированный контроль формы когда-либо их увидит, и вы можете применить логику обработчика для захвата события там или позволить ему пройти через сфокусированное управление формой.
Хотя это не так структурно грациозно, как архитектура событий-маршрутизации XAML, это значительно упрощает управление функциями уровня на Winforms. См. заметки MSDN в KeyPreview для оговорок.
Ответ 11
В WinForms:
if( Form.ModifierKeys == Keys.Shift )
Звучит как дубликат вопроса о переполнении стека Отключить клавишу Shift без использования событий в Windows Forms?.