停止重复键(C#)

时间:2010-12-12 09:18:14

标签: c# winforms keypress keydown

在这个应用程序中,我需要能够停止来自按下的键的响应,以防止不可靠的数据进入输出。我遇到的问题是,使用我下面的代码中的方法确实可以防止密钥重复,但它也会阻止它们反应不足 - 因为用户很快就会按键。

我不确定这是我的硬件,api限制还是我的代码问题,但我下面的例程并不是简单快速地完成工作而不会使程序无法使用。识别密钥是否被主动关闭(以及持续多长时间)的方法也有助于该程序的另一个功能并解决当前的问题。

有什么想法吗?

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    e.SuppressKeyPress = isKeyDown;
    isKeyDown = true;
}

private void Form1_KeyUp(object sender, KeyEventArgs e)
{
    isKeyDown = false;
}

private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (!isStreamPlaying) return;
    if (e.KeyChar.Equals('d') || e.KeyChar.Equals('j'))
    {
        //red hit
        SoundPlayer hitSounds = new SoundPlayer(taikoLiveMapper.Properties.Resources.normal_hitnormal);
        hitSounds.Play();
        outputlist.Add(string.Format("320,240,{0},1,{1}", ms, 0));
        lastms = ms;
    }
    else if (e.KeyChar.Equals('s') || e.KeyChar.Equals('k'))
    {
        //blue hit
        SoundPlayer hitSounds = new SoundPlayer(taikoLiveMapper.Properties.Resources.normal_hitclap);
        hitSounds.Play();
        outputlist.Add(string.Format("320,240,{0},1,{1}", ms, 8));
        lastms = ms;
    }
}

3 个答案:

答案 0 :(得分:3)

您可以使用GetKeyState查明密钥是否已关闭并使用该密钥来跟踪密钥:

    [DllImport("user32.dll")]
    static extern short GetKeyState(int key);

    static bool IsKeyPressed(Keys key)
    {
        short state = GetKeyState((int)key);
        return ((state & 128) != 0);
    }

    int i = 0;

    Dictionary<Keys, DateTime> downSince = new Dictionary<Keys, DateTime>();

    private void UpdateKeyStates()
    {
        foreach (var entry in downSince.ToArray())
        {
            if (!IsKeyPressed(entry.Key))
                downSince.Remove(entry.Key);
        }
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        UpdateKeyStates();
        if (!downSince.ContainsKey(e.KeyCode))
        {
            downSince.Add(e.KeyCode, DateTime.UtcNow);
            i++;

        }
        Text = i.ToString() + " " +(int)(DateTime.UtcNow - downSince[e.KeyCode]).TotalMilliseconds;
    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        UpdateKeyStates();
    }

此示例在每次按下某个键时计算i,并显示按下的时间。它使用GetKeyState而不是跟踪KeyDown / KeyUp,因为如果其他东西有焦点,你可能会错过这些消息。

答案 1 :(得分:0)

使用定时器:初始化定时器,每个“动作”一个(例如按d / j或s / k)移动定时器内的红色命中/蓝色命中代码而不是当前代码,请执行以下操作:

if (e.KeyChar.Equals('d') || e.KeyChar.Equals('j'))
{
    //red hit
    if (!tmrRedHit.Enabled)
        tmrRedHit.Enabled = true;
}
else if (e.KeyChar.Equals('s') || e.KeyChar.Equals('k'))
{
    //blue hit
    if (!tmrBlueHit.Enabled)
        tmrBlueHit.Enabled = true;
}

在计时器中,Elpased事件在执行代码后也将其Enabled设置为false

答案 2 :(得分:0)

根据documentation,“每次密钥重复时都会发生[d]重复的KeyDown事件,如果按住密钥,但在用户释放密钥时只生成一个KeyUp事件。”

所以最简单的解决方案是忽略重复的KeyDown事件,除非看到相应的KeyUp事件。

为我工作。