我正在构建一个应用程序,其中所有键输入必须由Windows本身处理。
我将tabstop设置为false,以使每个控制面板除面板外都能抓住焦点(但我不知道它是否有效果)。
我将KeyPreview设置为true,并且正在处理此表单上的KeyDown事件。
我的问题是,有时箭头键不再响应:
当我仅按箭头键时,不会触发keydown事件。
如果按下带有控制键的箭头键,将触发keydown事件。
您知道为什么我的箭头键突然停止触发事件吗?
我正在构建一个应用程序,其中所有键输入必须由Windows本身处理。
我将tabstop设置为false,以使每个控制面板除面板外都能抓住焦点(但我不知道它是否有效果)。
我将KeyPreview设置为true,并且正在处理此表单上的KeyDown事件。
我的问题是,有时箭头键不再响应:
当我仅按箭头键时,不会触发keydown事件。
如果按下带有控制键的箭头键,将触发keydown事件。
您知道为什么我的箭头键突然停止触发事件吗?
Answers:
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;
}
}
我遇到了完全相同的问题。我考虑了@Snarfblam提供的答案;但是,如果您阅读了MSDN上的文档,则ProcessCMDKey方法将覆盖应用程序中菜单项的键事件。
最近,我偶然从Microsoft偶然发现了这篇文章,该文章看起来很有希望:http : //msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx。据微软称,做的最好的事情是设置e.IsInputKey=true;
在PreviewKeyDown
检测方向键后事件。这样做会触发该KeyDown
事件。
这对我来说效果很好,并且比覆盖ProcessCMDKey少了些hacker。
IsInputKey
在e
类中e.IsInputKey=true
。
我正在使用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事件中省略这些键,因为它们会影响多个控件并移动焦点,但是这使得使应用程序以任何其他方式对这些键做出反应非常困难。
不幸的是,由于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...
如果将此与KeyDown事件结合使用,我认为您可以可靠地实现目标。
从WinForms调用WPF窗口时,我遇到了类似的问题。
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.Show();
但是,将window显示为对话框,它可以工作
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.ShowDialog();
希望这可以帮助。
为了捕获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);
}
完整资料... C#中的箭头键
韦恩
我认为最好的方法是像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;
}
我有同样的问题,已经在所选答案中使用了代码。这个链接是我的答案;也许对其他人也是如此。