Клавиши "Вверх", "Вниз", "Влево" и "Вправо" не запускают событие KeyDown
Я создаю приложение, в котором все входные данные ключа должны обрабатываться самими окнами.
Я устанавливаю tabstop в false для каждого элемента управления, который может захватить фокус, кроме панели (но я не знаю, имеет ли он эффект).
Я устанавливаю KeyPreview в true, и я обрабатываю событие KeyDown в этой форме.
Моя проблема в том, что иногда клавиша со стрелками больше не реагирует:
-
Событие keydown не запускается, когда я нажимаю только клавишу со стрелкой.
-
Событие keydown запускается, если я нажимаю клавишу со стрелкой с помощью модификатора элемента управления.
У вас есть идея, почему моя стрелочная клавиша внезапно прекращает стрельбу?
Ответы
Ответ 1
protected override bool IsInputKey(Keys keyData)
{
switch (keyData)
{
case Keys.Right:
case Keys.Left:
case Keys.Up:
case Keys.Down:
return true;
case Keys.Shift | Keys.Right:
case Keys.Shift | Keys.Left:
case Keys.Shift | Keys.Up:
case Keys.Shift | Keys.Down:
return true;
}
return base.IsInputKey(keyData);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
switch (e.KeyCode)
{
case Keys.Left:
case Keys.Right:
case Keys.Up:
case Keys.Down:
if (e.Shift)
{
}
else
{
}
break;
}
}
Ответ 2
У меня была такая же проблема. Я рассмотрел ответ @Snarfblam; однако, если вы прочитали документацию в MSDN, метод ProcessCMDKey предназначен для переопределения ключевых событий для пунктов меню в приложении.
Недавно я наткнулся на эту статью от Microsoft, которая выглядит довольно многообещающе: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx. Согласно microsoft, лучше всего установить e.IsInputKey=true;
в событии PreviewKeyDown
после обнаружения клавиш со стрелками. Это приведет к срабатыванию события KeyDown
.
Это работало довольно хорошо для меня и было менее хакерским, чем переопределение ProcessCMDKey.
Ответ 3
См Родольфо Нойбер ответ для лучшего ответа
(Мой оригинальный ответ):
Получите из класса управления, и вы можете переопределить метод ProcessCmdKey. Microsoft решила исключить эти ключи из событий KeyDown, поскольку они влияют на несколько элементов управления и перемещают фокус, но это очень затрудняет реакцию приложения на эти клавиши любым другим способом.
Ответ 4
Я использую PreviewKeyDown
private void _calendar_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e){
switch (e.KeyCode){
case Keys.Down:
case Keys.Right:
//action
break;
case Keys.Up:
case Keys.Left:
//action
break;
}
}
Ответ 5
К сожалению, это довольно сложно выполнить с помощью клавиш со стрелками из-за ограничений в событиях KeyDown. Однако есть несколько способов обойти это:
- Как указано в @Snarfblam, вы можете переопределить метод ProcessCmdKey, который сохраняет возможность разбора нажатий клавиш со стрелками.
- Как принятый ответ из этого вопроса говорится, что XNA имеет встроенный метод Keyboard.GetState(), который позволяет использовать входы со стрелкой. Однако WinForms этого не имеет, но это можно сделать с помощью P/Invoke или с помощью с помощью класс, который помогает с ним.
Я рекомендую попробовать использовать этот класс. Это довольно просто:
var left = KeyboardInfo.GetKeyState(Keys.Left);
var right = KeyboardInfo.GetKeyState(Keys.Right);
var up = KeyboardInfo.GetKeyState(Keys.Up);
var down = KeyboardInfo.GetKeyState(Keys.Down);
if (left.IsPressed)
{
//do something...
}
//etc...
Если вы используете это в сочетании с событием KeyDown, я думаю, вы можете надежно выполнить свою цель.
Ответ 6
У меня была аналогичная проблема при вызове окна WPF из WinForms.
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.Show();
Однако, показывая окно как диалог , он работал
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.ShowDialog();
Надеюсь, что это поможет.
Ответ 7
Чтобы зафиксировать нажатия клавиш в элементе управления Forms, вы должны получить новый класс, основанный на классе элемента управления, который вы хотите, и вы переопределите ProcessCmdKey().
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
//handle your keys here
}
Пример:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
//capture up arrow key
if (keyData == Keys.Up )
{
MessageBox.Show("You pressed Up arrow key");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
Полный источник... Клавиши со стрелками на С#
Вейн
Ответ 8
Лучший способ сделать, я думаю, - это обработать его, как сказал MSDN
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx
Но справитесь с этим, как вам это действительно нужно. Мой способ (в приведенном ниже примере) - поймать каждый KeyDown; -)
/// <summary>
/// onPreviewKeyDown
/// </summary>
/// <param name="e"></param>
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
{
e.IsInputKey = true;
}
/// <summary>
/// onKeyDown
/// </summary>
/// <param name="e"></param>
protected override void OnKeyDown(KeyEventArgs e)
{
Input.SetFlag(e.KeyCode);
e.Handled = true;
}
/// <summary>
/// onKeyUp
/// </summary>
/// <param name="e"></param>
protected override void OnKeyUp(KeyEventArgs e)
{
Input.RemoveFlag(e.KeyCode);
e.Handled = true;
}
Ответ 9
У меня была та же проблема, и я уже использовал код в выбранном ответе. эта ссылка была ответом для меня; возможно, и для других.
Как отключить навигацию по WinForm со стрелками на С#?
Ответ 10
protected override bool IsInputKey(Keys keyData)
{
if (((keyData & Keys.Up) == Keys.Up)
|| ((keyData & Keys.Down) == Keys.Down)
|| ((keyData & Keys.Left) == Keys.Left)
|| ((keyData & Keys.Right) == Keys.Right))
return true;
else
return base.IsInputKey(keyData);
}