c#KeyUpEvent发生在KeyDownEvent之前

时间:2012-09-27 13:14:29

标签: c# winforms

修改

好的我觉得我遇到了问题。我忘记了我在全球范围内挂钩了keyUpEvent。 由于首先处理全局关键事件,因此可能发生这种现象。

原始

我有点问题。 keyup事件发生在keydown事件之前。

我的计划应该做的是: 当用户按下某个键时,正在记录麦克风输入。 当用户释放时,键记录被停止并且正在保存wav文件。

如果用户正在按一个键,一切都很好。 但是在短时间内按下几个键会导致上述行为。 我添加了一些代码,以便我可以看到会发生什么。这是这种情况的输出。

Key down NumPad4, NumPad4, 100
128 = KeyDownTime
Key up NumPad4, NumPad4, 100
117 = KeyUpTime
Key up NumPad5, NumPad5, 101
0 = KeyUpTime
Key up NumPad6, NumPad6, 102
0 = KeyUpTime
Key down NumPad5, NumPad5, 101
58 = KeyDownTime
Key down NumPad6, NumPad6, 102
0 = KeyDownTime

你可以看到numpad5和numpad6的keyup事件发生在他们的keydown事件之前。 是否会发生2次事件但第二次事件更早结束? 我想用thread.sleep将leyup事件延迟50毫秒。 但我希望有更好的解决方案。

我没有添加任何代码,因为它是微不足道的,我不知道什么可以帮助你帮助我。 但如果你需要看它,只要告诉我将发布哪一部分。

这里编辑是代码的一部分:这里是KeyDownEvent

private void UserControl_KeyDown(object sender, KeyEventArgs e)
        {
            richTextBox1.AppendText("Key down"+e.KeyCode.ToString() + ", " + e.KeyData.ToString() + ", " + e.KeyValue.ToString()+"\n");
            StWt1 = new Stopwatch();
            StWt1.Start();
            try
            {                
                if (ready && !keyPressed)
                {
                    switch (e.KeyData)
                    {
                        case Keys.D0:
                            keyPressed = true;
                            calib = 10.0;
                            calib2 = mySaver.ID;
                            adjustLabelDisplay(10);
                            break;
                            // this is all the same with different value for calib depending on the pressed key
                        case Keys.Decimal:
                            keyPressed = true;
                            calib = 100.0;
                            calib2 = mySaver.ID;
                            adjustLabelDisplay(100);
                            break;
                        default:
                            break;
                    }
                }
                else if (!ready)
                {
                    MessageBox.Show("Missing at least one calibration value!");
                    labelDisplay.ForeColor = Color.Red;
                    labelDisplay.Text = "--------";
                }
            }
            catch (Exception ex)
            {
                richTextBox1.Visible = true;
                buttonHideRTB.Visible = true;
                richTextBox1.AppendText("Exception:\n");
                if (e == null)
                    richTextBox1.AppendText("Eventargs are Zero");
                if (sender == null)
                    richTextBox1.AppendText("Sender is null");
                if (calib == null)
                    richTextBox1.AppendText("calib is null");
                if (calib2 == null)
                    richTextBox1.AppendText("calib2 is null");
                richTextBox1.AppendText("Exception Message: " + ex.Message + "\n");
                richTextBox1.AppendText("Exception source: " + ex.Source + "\n");
                richTextBox1.AppendText("Exception Stack Trace: " + ex.StackTrace + "\n");
                richTextBox1.AppendText("Exception Traget Site: " + ex.TargetSite + "\n");
                MessageBox.Show("Exception was thrown. Check The Rich Text Box for further information.");
            }
            richTextBox1.AppendText(StWt1.ElapsedMilliseconds.ToString() + " = KeyDownTime\n");
            StWt1.Stop();
        } 

切换部分中KeyDownevent调用的方法:

private void adjustLabelDisplay(int x)
        {
            calib_ValueChangedEvent();
            calib2_ValueChangedEvent();
            currentKey = x;
            labelDisplay.Text = "Key: " + x;
            labelDisplay.BackColor = Color.FromArgb(255,128,0);
            this.labelDisplay.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            if (labelCB1.Text[0] != x.ToString()[0])
            {
                MessageBox.Show("Change to working page!");
            }
            if (checkBoxMode.Checked)
                enhRec.startRec();
            else
            {
                recorder.startRecordVoice();
                startTime = DateTime.Now;
            }
        }

和keyUpEvent:

private void UserControl_KeyUp(object sender, KeyEventArgs e)
        {
            richTextBox1.AppendText("Key up" + e.KeyCode.ToString() + ", " + e.KeyData.ToString() + ", " + e.KeyValue.ToString()+"\n");
            StWt2 = new Stopwatch();
            StWt2.Start();
            if (ready)
            {
                if (keyPressed)
                {
                    calib2=0;
                    calib=0;
                    labelCB1.Text = "0";
                    labelCB2.Text = "0";
                    keyPressed = false;
                    labelDisplay.Text = "Key: ";
                    labelDisplay.BackColor = Color.FromArgb(100, 255, 255, 255);
                    this.labelDisplay.BorderStyle = System.Windows.Forms.BorderStyle.None;
                    if (checkBoxMode.Checked)
                        enhRec.saveRec(getSaveString());
                    else
                        recorder.stopRecordVoice(getSaveString(), startTime, (int)numericUpDown1.Value);
                }
            }
            else
            {
                labelDisplay.ForeColor = Color.Black;
                labelDisplay.Text = "Key: ";
            }
            richTextBox1.AppendText(StWt2.ElapsedMilliseconds.ToString() + " = KeyUpTime\n");
            StWt2.Stop();
        }

2 个答案:

答案 0 :(得分:0)

您正在使用全局状态(keyPressed成员)来存储键盘状态信息。在您的代码中任何 KeyUp事件都会停止您的录制会话。这意味着您可以按一个键(开始录音),然后按另一个键并释放它,同时仍按住第一个键,您的录音将停止。

答案 1 :(得分:0)

如果我没有弄错的话,这些事件会在两个不同的地方处理,这就解释了为什么按键越快,结果变得越零。您看,处理KeyUp事件的控件没有KeyDown事件的处理程序,因此当消息泵开始进入时,您将在{{1}之前获取KeyUp事件因为某些KeyDown事件正在等待其他事件完成。

这是竞争条件。

在一个班级处理事件,你会没事的。