我正在构建一个应用程序,所有关键的输入必须由Windows自己处理。
对于每个能够获取焦点的控件,我将tabstop设置为false,但不包括一个面板(但我不知道它是否有效)。
我将KeyPreview设置为true,并在此表单上处理KeyDown事件。
我的问题是有时箭头键不再响应:
当我只按下箭头键时,keydown事件不会触发。
如果我按下带有控制修改器的箭头键,则会触发keydown事件。
您有想法为什么我的箭头键突然停止触发事件吗?
我正在构建一个应用程序,所有关键的输入必须由Windows自己处理。
对于每个能够获取焦点的控件,我将tabstop设置为false,但不包括一个面板(但我不知道它是否有效)。
我将KeyPreview设置为true,并在此表单上处理KeyDown事件。
我的问题是有时箭头键不再响应:
当我只按下箭头键时,keydown事件不会触发。
如果我按下带有控制修改器的箭头键,则会触发keydown事件。
您有想法为什么我的箭头键突然停止触发事件吗?
我遇到了完全相同的问题。我考虑了@Snarfblam提供的答案; 然而,如果你阅读MSDN上的文档,ProcessCMDKey方法是用来覆盖应用程序菜单项中的键事件。
我最近发现了这篇来自微软的文章,看起来很有前途:http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx。根据微软的说法,最好的做法是在检测到箭头键后,在PreviewKeyDown事件中设置e.IsInputKey=true;
这样将会触发KeyDown事件。
这对我很有效,并且比重写ProcessCMDKey更不那么hack。
IsInputKey
在e
类中:e.IsInputKey=true
。 - T30 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;
}
}
我正在使用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;
}
}
参见Rodolfo Neuber的回答,得到最佳答案。
(我的原始回答):
从控件类派生,您可以覆盖ProcessCmdKey方法。 Microsoft选择从KeyDown事件中省略这些键,因为它们会影响多个控件并移动焦点,但这使得应用程序在任何其他方式下对这些键做出反应非常困难。
当我从WinForms调用WPF窗口时,遇到了类似的问题。
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.Show();
然而,将窗口显示为对话框时,它起作用了。
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.ShowDialog();
很遗憾,由于KeyDown事件的限制,使用箭头键实现这一点相当困难。但是,有几种方法可以解决:
我建议尝试使用那个类。这很简单:
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...
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);
}
完整的源代码...C#中的箭头键
Vayne
我认为最好的方法是按照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;
}
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);
}