C#-如何捕获移位和x2B;Del组合事件而不仅捕获Shift键?
我有一个文本框和一个列表框。Shift必须清除列表框,Shift+Del组合必须清除文本框 这是我的密码C#-如何捕获移位和x2B;Del组合事件而不仅捕获Shift键?,c#,winforms,key,keydown,event-capturing,C#,Winforms,Key,Keydown,Event Capturing,我有一个文本框和一个列表框。Shift必须清除列表框,Shift+Del组合必须清除文本框 这是我的密码 private void MainForm_KeyDown(object sender, KeyEventArgs e) { if (e.Shift && e.KeyCode == Keys.Delete) textBox.Clear(); if (e.Shift) listBox.Items.Clear(); } 它显然是错误的,因为当班次下降时,列表框总
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.Shift && e.KeyCode == Keys.Delete) textBox.Clear();
if (e.Shift) listBox.Items.Clear();
}
它显然是错误的,因为当班次下降时,列表框总是被清除。我需要能够通过按下Shift+Del来清除文本框,而不是在此时清除列表框
我只能使用Shift键和Del键,不能使用其他键
那我该怎么办呢?如果你只想依靠
键按下
,你可以使用BackgroundWorker
(或者计时器也可以)在清除列表之前等待几毫秒。如果在此期间出现另一个密钥,则取消BackgroundWorker。您的实现可能如下所示:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Shift &&
e.KeyCode == Keys.Delete)
{
if (backgroundWorker1.IsBusy)
{
Trace.WriteLine("cancelling");
backgroundWorker1.CancelAsync();
}
textBox.Clear();
}
if (e.Shift &&
e.KeyCode == Keys.ShiftKey &&
!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
e.Result = false;
// wait 2 seconds (that is a bit long, adjust accordingly)
Thread.Sleep(2000); // HACK, use a proper timer here
// tell RunWorkerCompleted if we're good to clear
e.Result = !backgroundWorker1.CancellationPending;
}
// this gets called on the UI thread
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Trace.WriteLine(String.Format("{0} - {1}", e.Cancelled, e.Result));
if ((bool) e.Result)
{
listBox.Items.Clear();
}
}
如果您还可以利用KeyUp事件,则解决方案将变得更加简单:
private bool onlyShift = false; // keeps shift state
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
// becomes true if this is the shift key pressed
onlyShift = e.Shift && e.KeyCode == Keys.ShiftKey;
if (e.Shift &&
e.KeyCode == Keys.Delete)
{
textBox.Clear();
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
// was the shiftkey the last one in keydown AND
// are we releasing the shiftkey now
if (onlyShift && e.KeyCode == Keys.ShiftKey)
{
listBox.Items.Clear();
}
}
我个人会使用后一种解决方案。首先,让我先说一句,我通常建议不要单独使用Shift键来触发任何桌面软件中的操作,而不是游戏。这样做违反了规则:因为在正常键入过程中,Shift通常用于修改其他键的含义,用户习惯于认为按下它本身不会产生任何后果,当然也不会造成任何破坏。因此,如果用户随意按下Shift键,发现他刚刚丢失了物品列表,他可能会感到非常不愉快的惊讶,尤其是当修复损坏变得困难或乏味时 然而,你在评论中说,你在这件事上没有选择,所以说,这里有一个可能的解决办法 为了能够区分Shift本身和Shift+Del组合之间的区别,我们需要捕获
KeyDown
和keydup
事件,并使用从每个事件中收集的信息
在KeyDown
事件中,我们将KeyEventArgs.KeyData
的值保存到一个私有字段中,但不对其采取任何操作KeyData
包含组合的键
标志,表示按下的主键,以及同时按下的任何修改键,如Ctrl、Shift或Alt。请注意,当按下Shift键时,它既是主键也是修改器,因此KeyData
将包含键。ShiftKey
(键)与键组合。Shift
(修改器)
在KeyUp
事件中,我们查看相对于上次按下的按键释放了哪些按键。我们正在寻找两个特定的键序列:
private void MainForm_KeyUp(object sender, KeyEventArgs e)
{
// Shift + Delete pressed, then Delete released while Shift still held down
if (LastKeysDown == (Keys.Shift | Keys.Delete) && e.KeyData == LastKeysDown)
textBox1.Clear();
// Shift pressed with no other key, then released
else if (LastKeysDown == (Keys.Shift | Keys.ShiftKey) && e.KeyData == Keys.ShiftKey)
listBox1.Items.Clear();
LastKeysDown = Keys.None;
}
请注意,作为最后一个业务订单,我们清除了private
LastKeysDown
字段。这有助于确保如果一行中有两个KeyUp
事件,则只有第一个事件与前一个KeyDown
成对出现。但请注意,这并不是万无一失的:如果您按住一个键足够长的时间,计算机的按键重复将启动并生成额外的KeyDown
事件。只需在短时间内忽略shift事件,比如500毫秒?但你问什么有点不清楚。你不能演示一下你的问题吗?哪些事件?你是如何监控键盘的?有代码吗?非常不清楚你们在谈论什么事件,为什么你们甚至独自“捕捉”了这个转变。。。显然,您知道shift state随KeyDown事件()一起出现,所以您应该询问一些其他问题-请发帖澄清。请用一些代码详细说明您是如何捕获的。通常,键事件会附带一些修改器标志,您可以对这些标志进行检查,例如Shift、Ctrl、Alt。您通常不会显式地侦听Shift,然后再侦听另一个键。我开始更正答案,但实际上,将Shift用作实际键并同时用作其他键的修改器是一个非常糟糕的主意。我建议您使用Shift、Ctrl或Alt以外的任何方法来清除列表框项目。你有没有见过像你这样的功能键?有一个原因你可能没有;)谢谢你的帮助。还有一个问题。e.Shift和(e.KeyCode==Keys.ShiftKey)之间的区别是什么。他们不平等吗?@J.Doe嗯,是的。我没有进一步优化。
private void MainForm_KeyUp(object sender, KeyEventArgs e)
{
// Shift + Delete pressed, then Delete released while Shift still held down
if (LastKeysDown == (Keys.Shift | Keys.Delete) && e.KeyData == LastKeysDown)
textBox1.Clear();
// Shift pressed with no other key, then released
else if (LastKeysDown == (Keys.Shift | Keys.ShiftKey) && e.KeyData == Keys.ShiftKey)
listBox1.Items.Clear();
LastKeysDown = Keys.None;
}