用ProcessCmdKey按住箭头键向下事件
本文关键字:事件 ProcessCmdKey | 更新日期: 2023-09-27 18:09:38
只要按住箭头键,我就需要执行某个方法。现在,对于Visual studio 2012中的常规箭头键,使用OnKeyDown
不起作用,所以我需要使用ProcessCmdKey
,它像一个魅力。是否有一种方法可以使用ProcessCmdKey
来检测箭头何时被释放/被按住?
我采纳了Markus和Hans的建议,并将两者结合起来。我使用了
ProcessKeyPreview
方法,但我仍然有一些问题。当我按住任何箭头键时,此方法将不会检测到WM_KEYDOWN
已经发生…但一旦我释放我的手指从关键,它实际上确实注意到,WM_KEYUP
已经发生。有趣的是,当我按住任何其他键(即字母'S')时,它正确地识别它何时被按下和释放。我把我的代码片段贴在下面:
const int WM_KEYUP = 0x0101;
const int WM_KEYDOWN = 0x0100;
protected override bool ProcessKeyPreview(ref Message m)
{
int msgVal = m.WParam.ToInt32();
if (m.Msg == WM_KEYDOWN)
{
switch ((Keys)msgVal) {
case Keys.Down:
Console.WriteLine("down pressed"); //not detected
break;
case Keys.S:
Console.WriteLine("S pressed!"); //detected
break;
}
}
if (m.Msg == WM_KEYUP)
{
switch ((Keys)msgVal)
{
case Keys.Down:
Console.WriteLine("down released"); //detected
break;
case Keys.S:
Console.WriteLine("s released!"); //detected
break;
}
}
return base.ProcessKeyPreview(ref m);
}
您无法使用ProcessCmdKey()看到KeyUp事件,它仅用于处理KeyDown事件。如果表单包含控件,则需要在更低的级别处理此问题。诀窍是在Winforms通过正常的键处理和WndProc链发送消息之前拦截消息。这需要实现IMessageFilter接口。这样的:
public partial class Form1 : Form, IMessageFilter { // NOTE: added IMessageFilter
public Form1() {
InitializeComponent();
Application.AddMessageFilter(this);
}
protected override void OnFormClosed(FormClosedEventArgs e) {
Application.RemoveMessageFilter(this);
base.OnFormClosed(e);
}
bool IMessageFilter.PreFilterMessage(ref Message m) {
// Trap WM_KEYUP/DOWN for Keys.Down key
if ((m.Msg == 0x100 || m.Msg == 0x101) && (Keys)m.WParam.ToInt32() == Keys.Down) {
bool repeat = (m.LParam.ToInt32() & (1 << 30)) != 0;
bool down = m.Msg == 0x100;
// But only for this form
Form form = null;
var ctl = Control.FromHandle(m.HWnd);
if (ctl != null) form = ctl.FindForm();
if (form == this) {
OnCursorDown(down, repeat & down);
return true;
}
}
return false;
}
private void OnCursorDown(bool pressed, bool repeat) {
// etc..
}
}
你可以重载ProcessKeyPreview,这将让你看到WM_KEYDOWN消息以及WM_KEYUP消息。请确保为表单打开KeyPreview。
WM_KEYDOWN:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646280(v=vs.85).aspx
WM_KEYUP:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646281(v=vs.85).aspx
的例子:
public partial class TestForm : Form
{
public TestForm()
{
InitializeComponent();
this.KeyPreview = true;
}
const int WM_KEYUP = 0x0101;
const int WM_KEYDOWN = 0x0100;
protected override bool ProcessKeyPreview(ref Message m)
{
switch (m.Msg)
{
case WM_KEYDOWN:
Console.WriteLine(m.LParam);
break;
case WM_KEYUP:
Console.WriteLine(m.LParam);
break;
}
return base.ProcessKeyPreview(ref m);
}
}