Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#-如何捕获移位和x2B;Del组合事件而不仅捕获Shift键?_C#_Winforms_Key_Keydown_Event Capturing - Fatal编程技术网

C#-如何捕获移位和x2B;Del组合事件而不仅捕获Shift键?

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(); } 它显然是错误的,因为当班次下降时,列表框总

我有一个文本框和一个列表框。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();
}
它显然是错误的,因为当班次下降时,列表框总是被清除。我需要能够通过按下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
事件中,我们查看相对于上次按下的按键释放了哪些按键。我们正在寻找两个特定的键序列:

  • 按下Shift+Del,然后在按住Shift的同时释放Del
  • 在没有其他键的情况下按下Shift,然后释放
  • 如果我们找到了我们要找的东西,我们就会采取适当的行动,否则我们什么也不做

    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;
    }